aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/gnuplot/mem_lat.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/gnuplot/mem_lat.c')
-rw-r--r--tools/gnuplot/mem_lat.c67
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;
+}