Our great sponsors
-
memset_benchmark
This repository contains high-performance implementations of memset and memcpy in assembly.
-
WorkOS
The modern identity platform for B2B SaaS. The APIs are flexible and easy-to-use, supporting authentication, user identity, and complex enterprise features like SSO and SCIM provisioning.
-
InfluxDB
Power Real-Time Data Analytics at Scale. Get real-time insights from all types of time series data with InfluxDB. Ingest, query, and analyze billions of data points in real-time with unbounded cardinality.
Probably poorly. It is a violation to cast an unaligned pointer to an aligned type. And the code looks like it does just that right here: https://github.com/nadavrot/memset_benchmark/blob/main/src/l...
This is undefined behavior under C99 §6.3.2.3 Paragraph 7.
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...
This is an interesting related problem - how do you efficiently test if a buffer contains zeroes? There's actually no standard C function for this. My colleagues came up with the following nice trick though. It reuses the (presumably already maximally optimized) memcmp function from libc:
https://gitlab.com/nbdkit/nbdkit/-/blob/b31859402d1404ba0433...
static inline bool __attribute__((__nonnull__ (1)))
Modern compilers have quite a deep understanding of memcpy, and they will recognize the pattern and put in optimal assembly (on x86, probably "rep movsb" or whatever), and they will recognize the pattern even if you don't literally call memcpy. This is why the GCC implmentation of memcpy is, like, trivial: [1]. The compiler will recognize that this is a memcpy and sub the better implementation.
I wonder though: it seems to me that memory bandwidth should far and away be the limiting factor for a memcpy, so I would think even a straight-forward translation of the "trivial" implementation wouldn't be that far off from an "optimal" one. I guess memory prefetching would make a difference, but would minimizing the number of loads/stores really matter that much?
[1]: https://github.com/gcc-mirror/gcc/blob/master/libgcc/memcpy....
Can't look right now, but you might not have benchmarked against libc, but against an optimized version included in Raspbian (https://github.com/simonjhall/copies-and-fills). I'm not sure if that's still active in the latest Raspberry Pi OS releases.
I do it because nobody else implemented a secure memset. What they call secure is just avoiding that the compiler ignores it. A secure memset also cleans the caches with a memory barrier, so that meltdown cannot read it.
explicit_bzero and it's numerous variants are not only insecure, but also slow. (byte wise!)
Only safelibc has a secure memset_s. https://github.com/rurban/safeclib/blob/master/tests/perf_me...