diff options
Diffstat (limited to 'tools/gnuplot/mem_lat.c')
-rw-r--r-- | tools/gnuplot/mem_lat.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/gnuplot/mem_lat.c b/tools/gnuplot/mem_lat.c new file mode 100644 index 0000000..b85a08f --- /dev/null +++ b/tools/gnuplot/mem_lat.c @@ -0,0 +1,67 @@ +#include <assert.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +enum : size_t { + KB = 1024, + MB = 1024 * KB, + + DFL_MAXSZ = 64 * MB, + DFL_STRIDE = 256, + NUM_ACCESS = 1ull << 24, +}; + +static inline uint64_t rdtsc() { + uint32_t eax, edx; + asm volatile("rdtsc" : "=a"(eax), "=d"(edx)); + return ((uint64_t)edx << 32) | eax; +} + +uint64_t run_one_walk(size_t size, size_t stride) { + // Check size is power of two. + assert((size & (size -1)) == 0); + assert((size / stride) <= NUM_ACCESS); + + unsigned char *mem = (unsigned char *)malloc(size); + memset(mem, 0x55, size); + + const uint64_t start = rdtsc(); + for (size_t it = 0; it < NUM_ACCESS; it++) { + ((volatile unsigned char *)mem)[(it * stride) & (size - 1)]++; + } + const uint64_t stop = rdtsc(); + + free(mem); + return stop - start; +} + +int main(int argc, char *argv[]) { + size_t max_sz = DFL_MAXSZ; + size_t stride = DFL_STRIDE; + + if (argc > 1) { + max_sz = strtoll(argv[1], 0, 10); + max_sz *= MB; + } + if (argc > 2) { + stride = strtoll(argv[2], 0, 10); + } + + fprintf(stderr, "max_sz=%zuK stride=%zu access=%zu\n", + max_sz / KB, stride, NUM_ACCESS); + + size_t size = 2048; + while (size <= max_sz) { + uint64_t cycles = 0; + for (size_t loop = 0; loop < 10; ++loop) { + cycles += run_one_walk(size, stride); + } + printf("%6zuK %f\n", size / KB, (double)cycles / NUM_ACCESS / 10.0); + + size *= 2; + } + + return 0; +} |