From f21493272dcb25a186b4404aee46510c23b6ff23 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Wed, 19 Sep 2018 16:00:28 +0200 Subject: [PATCH] test for measuring memcpy throughput (fix #3016) --- repos/libports/run/memcpy.run | 76 +++++++++++++++++ repos/libports/src/test/memcpy/linux/Makefile | 7 ++ repos/libports/src/test/memcpy/linux/main.cc | 85 +++++++++++++++++++ repos/libports/src/test/memcpy/main.cc | 66 ++++++++++++++ repos/libports/src/test/memcpy/memcpy.h | 50 +++++++++++ repos/libports/src/test/memcpy/target.mk | 3 + 6 files changed, 287 insertions(+) create mode 100644 repos/libports/run/memcpy.run create mode 100644 repos/libports/src/test/memcpy/linux/Makefile create mode 100644 repos/libports/src/test/memcpy/linux/main.cc create mode 100644 repos/libports/src/test/memcpy/main.cc create mode 100644 repos/libports/src/test/memcpy/memcpy.h create mode 100644 repos/libports/src/test/memcpy/target.mk diff --git a/repos/libports/run/memcpy.run b/repos/libports/run/memcpy.run new file mode 100644 index 0000000000..ec345adfe8 --- /dev/null +++ b/repos/libports/run/memcpy.run @@ -0,0 +1,76 @@ +if { [get_cmd_switch --autopilot] } { + if {[have_include "power_on/qemu"]} { + puts "\nRun script does not support Qemu.\n" + exit 0 + } +} + +build "core init test/memcpy" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image { + core init test-memcpy + ld.lib.so libc.lib.so vfs.lib.so +} + +append qemu_args " -nographic " + +proc run_test {name serial_id} { + run_genode_until "start $name.*\n" 20 $serial_id + set t1 [clock milliseconds] + run_genode_until "finished $name.*\n" 180 $serial_id + set t2 [clock milliseconds] + return [expr {$t2 - $t1}] +} + +run_genode_until "Memcpy testsuite started.*\n" 60 +set serial_id [output_spawn_id] +set byte_dur [run_test "bytewise memcpy" $serial_id] +set genode_dur [run_test "Genode memcpy" $serial_id] +set libc_cpy_dur [run_test "libc memcpy" $serial_id] +set libc_set_dur [run_test "libc memset" $serial_id] +set uncached_wr_dur [run_test "Genode memcpy" $serial_id] +set uncached_rd_dur [run_test "Genode memcpy" $serial_id] +puts "bytewise: copied 8 GB in $byte_dur milliseconds ([expr {8192000 / $byte_dur}] MiB/sec)" +puts "memcpy: copied 8 GB in $genode_dur milliseconds ([expr {8192000 / $genode_dur}] MiB/sec)" +puts "libc memcpy: copied 8 GB in $libc_cpy_dur milliseconds ([expr {8192000 / $libc_cpy_dur}] MiB/sec)" +puts "libc memset: copied 8 GB in $libc_set_dur milliseconds ([expr {8192000 / $libc_set_dur}] MiB/sec)" +puts "memcpy (uncached write): copied 8 GB in $uncached_wr_dur milliseconds ([expr {8192000 / $uncached_wr_dur}] MiB/sec)" +puts "memcpy (uncached read): copied 8 GB in $uncached_rd_dur milliseconds ([expr {8192000 / $uncached_rd_dur}] MiB/sec)" +exit 0 + +# +# Linux baseline measurements +# + +# Raspberry Pi 1 +# bytewise memcpy: copied 8388608 KiB in 93390210 usecs (87 MiB/sec) +# libc memcpy: copied 8388608 KiB in 6238602 usecs (1313 MiB/sec) +# libc memset: copied 8388608 KiB in 6023324 usecs (1360 MiB/sec) diff --git a/repos/libports/src/test/memcpy/linux/Makefile b/repos/libports/src/test/memcpy/linux/Makefile new file mode 100644 index 0000000000..ec714bf749 --- /dev/null +++ b/repos/libports/src/test/memcpy/linux/Makefile @@ -0,0 +1,7 @@ +INC_DIR = $(PWD)/.. + +memcpy: main.cc $(INC_DIR)/memcpy.h + g++ -I$(INC_DIR) -O2 -Wall -Wextra -Weffc++ -std=gnu++11 $< -o $@ + +clean: + rm -f *~ memcpy diff --git a/repos/libports/src/test/memcpy/linux/main.cc b/repos/libports/src/test/memcpy/linux/main.cc new file mode 100644 index 0000000000..b8872f33dd --- /dev/null +++ b/repos/libports/src/test/memcpy/linux/main.cc @@ -0,0 +1,85 @@ +#include +#include + +#include "memcpy.h" + +struct Duration { unsigned long usecs; }; + + +struct Time +{ + timespec _timespec { 0, 0 }; + + Time() + { + clock_gettime(CLOCK_REALTIME, &_timespec); + } + + Time(timespec timespec) : _timespec(timespec) { } + + void print() const + { + printf("secs=%ld nsecs=%ld\n", + (long)_timespec.tv_sec, (long)_timespec.tv_nsec); + } + + static Duration duration(Time t1, Time t2) + { + auto usecs = [&] (timespec ts) { + return 1000UL*1000UL*((unsigned long)ts.tv_sec % 1000UL) + + (unsigned long)ts.tv_nsec/1000UL; }; + + return Duration { usecs(t2._timespec) - usecs(t1._timespec) }; + } +}; + + +struct Test { + + Time s { }; + + void start() { } + + void finished() + { + Time e; + Duration duration = Time::duration(s, e); + + printf("copied %ld KiB in %ld usecs ", + (unsigned long)TOTAL_MEM_KB, duration.usecs); + printf("(%ld MiB/sec)\n", (unsigned long) + ((float)(TOTAL_MEM_KB/1024)/((float)duration.usecs/1000000))); + } +}; + + +struct Bytewise_test : Test +{ + void copy(void *dst, const void *src, size_t size) { + bytewise_memcpy(dst, src, size); } +}; + + +struct Libc_memcpy_test : Test +{ + void copy(void *dst, const void *src, size_t size) { + memcpy(dst, src, size); } +}; + + +struct Libc_memset_test : Test +{ + void copy(void *dst, const void *, size_t size) { + memset(dst, 0, size); } +}; + + +int main(int, char**) +{ + printf("bytewise memcpy test:\n"); + memcpy_test(); + printf("libc memcpy test:\n"); + memcpy_test(); + printf("libc memset test:\n"); + memcpy_test(); +} diff --git a/repos/libports/src/test/memcpy/main.cc b/repos/libports/src/test/memcpy/main.cc new file mode 100644 index 0000000000..13484e60f9 --- /dev/null +++ b/repos/libports/src/test/memcpy/main.cc @@ -0,0 +1,66 @@ +#include +#include + +#include +#include +#include + +#include "memcpy.h" + +using Genode::log; + +struct Bytewise_test { + + void start() { log("start bytewise memcpy"); } + void finished() { log("finished bytewise memcpy"); } + + void copy(void *dst, const void *src, size_t size) { + bytewise_memcpy(dst, src, size); } +}; + +struct Genode_cpy_test { + + void start() { log("start Genode memcpy"); } + void finished() { log("finished Genode memcpy"); } + + void copy(void *dst, const void *src, size_t size) { + Genode::memcpy(dst, src, size); } +}; + +struct Libc_cpy_test { + + void start() { log("start libc memcpy"); } + void finished() { log("finished libc memcpy"); } + + void copy(void *dst, const void *src, size_t size) { + memcpy(dst, src, size); } +}; + +struct Libc_set_test { + + void start() { log("start libc memset"); } + void finished() { log("finished libc memset"); } + + void copy(void *dst, const void *, size_t size) { + memset(dst, 0, size); } +}; + +void Libc::Component::construct(Libc::Env &env) +{ + log("Memcpy testsuite started"); + + memcpy_test(); + memcpy_test(); + memcpy_test(); + memcpy_test(); + + Genode::Attached_ram_dataspace uncached_ds(env.ram(), env.rm(), + BUF_SIZE, Genode::UNCACHED); + + memcpy_test(uncached_ds.local_addr(), + nullptr, BUF_SIZE); + memcpy_test(nullptr, uncached_ds.local_addr(), + BUF_SIZE); + + log("Memcpy testsuite finished"); +} diff --git a/repos/libports/src/test/memcpy/memcpy.h b/repos/libports/src/test/memcpy/memcpy.h new file mode 100644 index 0000000000..5d453a47dd --- /dev/null +++ b/repos/libports/src/test/memcpy/memcpy.h @@ -0,0 +1,50 @@ +#include +#include +#include + +enum { + BUF_SIZE = 8UL*1024UL*1024UL, + ITERATION = 1024UL, + TOTAL_MEM_KB = BUF_SIZE / 1024 * ITERATION, +}; + + +template +void memcpy_test(void * dst = nullptr, void * src = nullptr, + size_t size = BUF_SIZE) +{ + void * const from_buf = src ? src : malloc(size); + void * const to_buf = dst ? dst : malloc(size); + + Test test; + test.start(); + + for (unsigned i = 0; i < ITERATION; i++) + test.copy(to_buf, from_buf, BUF_SIZE); + + test.finished(); + + if (!src) free(from_buf); + if (!dst) free(to_buf); +} + + +static inline void *bytewise_memcpy(void *dst, const void *src, size_t size) +{ + char *d = (char *)dst, *s = (char *)src; + + /* copy eight byte chunks */ + for (size_t i = size >> 3; i > 0; i--, *d++ = *s++, + *d++ = *s++, + *d++ = *s++, + *d++ = *s++, + *d++ = *s++, + *d++ = *s++, + *d++ = *s++, + *d++ = *s++); + + /* copy left over */ + for (size_t i = 0; i < (size & 0x7); i++, *d++ = *s++); + + return dst; +} diff --git a/repos/libports/src/test/memcpy/target.mk b/repos/libports/src/test/memcpy/target.mk new file mode 100644 index 0000000000..0f56d703a4 --- /dev/null +++ b/repos/libports/src/test/memcpy/target.mk @@ -0,0 +1,3 @@ +TARGET = test-memcpy +SRC_CC = main.cc +LIBS += libc