Live data from Hacker News

A 100LOC C impl of memset, that is faster than glibc's

github.com

81–90 of 110 posts

Re: A 100LOC C impl of memset, that is faster than glibc's

#81
post #47

Earlier quoted context omitted.

It is probably faster, yes (half the number of reads) – but the point of this truck is that you can re-use the (hopefully) vectorized memcmp on every platform with portable code rather than getting on the SIMD ISA treadmill yourself.

The qemu implementation does indeed do it the hard way. It's a lot of code: https://gitlab.com/qemu-project/qemu/-/blob/master/util/buff...

Does your memset version beat QEMU's plain-old-C fallback version ?

Re: A 100LOC C impl of memset, that is faster than glibc's

#82
post #3

I'm curious why the time is so much worse for sizes just slightly larger than 400, but then better again for sizes larger than this?

Could be hitting a critical cache stride. See also https://stackoverflow.com/questions/11413855/why-is-transpos...

Re: A 100LOC C impl of memset, that is faster than glibc's

#84
post #23

There is an interesting related problem - how do you efficiently test if a buffer contains only zeroes? We use this for automatically sparsifying disk images. There's no standard C function for this. My colleague came up with the following nice trick. It reuses the (presumably already maximally optimized) memcmp function from libc: https://gitlab.com/nbdkit/nbdkit/-/blob/b31859402d1404ba0433... static inline bool __a…

It would be interesting if there was a way to measure the voltage difference between two memory addresses and if it was equal, the bits would be all one or zero and then you just need to read one byte to see which it is. I don't know how practical that is, but it would be a constant time check.

Re: A 100LOC C impl of memset, that is faster than glibc's

#85
post #61
post #23

There is an interesting related problem - how do you efficiently test if a buffer contains only zeroes? We use this for automatically sparsifying disk images. There's no standard C function for this. My colleague came up with the following nice trick. It reuses the (presumably already maximally optimized) memcmp function from libc: https://gitlab.com/nbdkit/nbdkit/-/blob/b31859402d1404ba0433... static inline bool __a…

I wonder if it would be meaningfully faster if you checked the first 16 bytes as uint64_t or uint128_t instead of byte by byte. It would save you 14 or 15 comparisons per function call.

GCC (-O3) actually unrolls the loop completely into 16 x (cmpb + jne), which I find slightly surprising.

We can't easily use a larger size because we mustn't read beyond the end of the buffer if it's shorter than 16 bytes and not a multiple of 2, 4, etc.

Re: A 100LOC C impl of memset, that is faster than glibc's

#86
post #65
post #23

There is an interesting related problem - how do you efficiently test if a buffer contains only zeroes? We use this for automatically sparsifying disk images. There's no standard C function for this. My colleague came up with the following nice trick. It reuses the (presumably already maximally optimized) memcmp function from libc: https://gitlab.com/nbdkit/nbdkit/-/blob/b31859402d1404ba0433... static inline bool __a…

There are a number of standard functions that can achieve this, namely in string.h. Performance is a question of course.

Which functions in particular?

Re: A 100LOC C impl of memset, that is faster than glibc's

#87

Earlier quoted context omitted.

What's the use of filling your ram with zeros when the data needs to be on L1, L2 or L3? Unless you are memsetting hundreds of MBs of memory, memset/memcpy in practice need to be handled by the cpu or something very close to it. Zen has CLZERO which can clear a cacheline in one go, but not sure how good it is.

PPC has an instruction to 'load' a line ignoring its previous contents (just set up the cache state). useful in any case when you know you're going to overwrite the whole thing.

I used dcbz extensively back on the Wii.

Re: A 100LOC C impl of memset, that is faster than glibc's

#88
post #85
post #61

Earlier quoted context omitted.

I wonder if it would be meaningfully faster if you checked the first 16 bytes as uint64_t or uint128_t instead of byte by byte. It would save you 14 or 15 comparisons per function call.

GCC (-O3) actually unrolls the loop completely into 16 x (cmpb + jne), which I find slightly surprising. We can't easily use a larger size because we mustn't read beyond the end of the buffer if it's shorter than 16 bytes and not a multiple of 2, 4, etc.

Yeah, dealing with the smaller buffers is annoying. You could put buffers < 16 bytes in a separate codepath, but that's trading elegance for pretty minor gains.

Re: A 100LOC C impl of memset, that is faster than glibc's

#89
post #23

There is an interesting related problem - how do you efficiently test if a buffer contains only zeroes? We use this for automatically sparsifying disk images. There's no standard C function for this. My colleague came up with the following nice trick. It reuses the (presumably already maximally optimized) memcmp function from libc: https://gitlab.com/nbdkit/nbdkit/-/blob/b31859402d1404ba0433... static inline bool __a…

Wouldn’t duff’s device be significantly faster here?
Post reply on HN