Allocating memory for Vec takes long time

I write a redis module which contains a vector using the redis-module crate. When allocating a very large vector 1_000_000_000, it take over 3 seconds to return. Looking at a flamegraph I see that __rust_alloc_zeroed take 99.80% of the time.
I have tried to allocate a similar size directly with the crate outside of redis and I don't see the same delay. It takes under 1ms.
What can be the reason for this behavior?
Thanks

Why is it zeroed? What is the code?

Rust has special optimization for vec![0; N] which asks the system for lazily initialized zeroed pages of memory. They're not allocated until you write something to them.

With other types, it may need to allocate uninitialized memory and then clone the default instance all over it. If the data is larger than your RAM, this may also start swapping memory.

2 Likes

As an additional note to what @kornel said, some kernels may even zero pages in the background and keep a pool of pre-zeroed pages around, ready to give out as the need rises. Or the kernel may decide that the memory is better used for disk cache and only drop the disk cache when the memory starts getting used for other things, and have to zero it at that point.

Do not expect predictable performance out of memory allocation. There is a reason that in hard real-time systems you allocate all your memory up front. You don't want the brake controller in your car to sometimes hang for a few extra ms trying to allocate memory.

1 Like

@kornel @Vorpal Thanks for your help.

In my case, the code interact with the C code of redis. After the struct is initialized, it is passed through unsafe code into the server to be stored as redis key. Can it be that at this stage the optimization @kornel mentioned is dropped since rust cannot track the pointer any more and thus all the data is initilized or is that a duty of the operation system which is independent of rust.

In the past, a user of RedisBloom complained that after initilizing a big filter, he insereted multiple elements and experienced a block on the filter which was caused by what @Vorpal described, the need to get from the kernel multiple zeroed pages.

Currently the lag is of 3-4 seconds which for a server is forever. I need a solution here.

Do you know by chance if there is a way to ask the kernel to keep more zeroed pages around?

Lazy init of zeroed memory is done by the operating system, so it should work and remain lazy even if you pass the pointer to C.

However, if the data is used as a key, could it be that Redis reads it all in order to hash it?

Interesting. I will see if I have someone from the company to look into this.

As for your suggestion, I use this memory as the value, not the key so redis does not look into it.