I am quite new to understanding how memory works so please do correct me if I get the terminology and concepts wrong.
Update
Base on @stevengj’s suggestion, here is an MVE of my function. The unsafe part is step1
but I have provided the rest of the function for context.
function load_bits(s::String)
step1 = s |> pointer |> Ptr{UInt} |> unsafe_load |> ntoh
# now there are some bits at the end that should be padded with 0
# but are not guaranteed to be 0 - so bitshift them away
nbits_to_shift = 8(sizeof(UInt) - sizeof(s))
step2 = step1 >> nbits_to_shift << nbits_to_shift
step2
end
s = "abc"
load_bits(s)
svec = [randstring(rand(1:8)) for i=1:1_000_000]
@time load_bits.(svec)
What’s the best way to optimize the above but is still safe, in that in won’t be allowed to try and access memory that isn’t allocated to the program? Any explanation of the theories I need to make my own optimization in the future would be highly appreciated too.
Orig text
I found that the fastest way to load the underlying bytes of a string is to load 8 bytes at a time using unsafe_load
as above. However the string may be less than 8 bytes in length, so in theory, one could be accessing memory that is not allocated and cause a segfault. But given I have a pointer which is just a memory address, is it possible to find out how “far away” that pointer is from the boundary? Because out of 100_000_000 strings, only one would be right on the boundary, so for the other 99_999_999 strings, I can just load 8 bytes and bitshift away the bits I don’t want. And for that 1 string I can just load it slowly byte by byte to avoid causing any issues.
New MWE showing load 8 bytes at a time is more efficient than loading 1 byte 8 times
A simple MVE to show that load 8 bytes at a time is more efficient than loading 1 byte at a time using codeunit 8 times.
svec = [randstring(rand(1:8)) for i=1:1_000_000];
using BenchmarkTools
@btime load_bits.($svec);
@btime codeunit.($svec,1);