mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
test for measuring memcpy throughput (fix #3016)
This commit is contained in:
parent
c2d85ff554
commit
f21493272d
76
repos/libports/run/memcpy.run
Normal file
76
repos/libports/run/memcpy.run
Normal file
@ -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 {
|
||||
<config>
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
|
||||
<default-route> <any-service> <parent/> </any-service> </default-route>
|
||||
<default caps="200"/>
|
||||
|
||||
<start name="test-memcpy">
|
||||
<resource name="RAM" quantum="32M"/>
|
||||
<config>
|
||||
<vfs> <dir name="dev"> <log/> <null/> </dir> </vfs>
|
||||
<libc stdout="/dev/log" stderr="/dev/log" socket="/socket"/>
|
||||
</config>
|
||||
</start>
|
||||
</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)
|
7
repos/libports/src/test/memcpy/linux/Makefile
Normal file
7
repos/libports/src/test/memcpy/linux/Makefile
Normal file
@ -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
|
85
repos/libports/src/test/memcpy/linux/main.cc
Normal file
85
repos/libports/src/test/memcpy/linux/main.cc
Normal file
@ -0,0 +1,85 @@
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
#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<Bytewise_test>();
|
||||
printf("libc memcpy test:\n");
|
||||
memcpy_test<Libc_memcpy_test>();
|
||||
printf("libc memset test:\n");
|
||||
memcpy_test<Libc_memset_test>();
|
||||
}
|
66
repos/libports/src/test/memcpy/main.cc
Normal file
66
repos/libports/src/test/memcpy/main.cc
Normal file
@ -0,0 +1,66 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <libc/component.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#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<Bytewise_test>();
|
||||
memcpy_test<Genode_cpy_test>();
|
||||
memcpy_test<Libc_cpy_test>();
|
||||
memcpy_test<Libc_set_test>();
|
||||
|
||||
Genode::Attached_ram_dataspace uncached_ds(env.ram(), env.rm(),
|
||||
BUF_SIZE, Genode::UNCACHED);
|
||||
|
||||
memcpy_test<Genode_cpy_test>(uncached_ds.local_addr<void>(),
|
||||
nullptr, BUF_SIZE);
|
||||
memcpy_test<Genode_cpy_test>(nullptr, uncached_ds.local_addr<void>(),
|
||||
BUF_SIZE);
|
||||
|
||||
log("Memcpy testsuite finished");
|
||||
}
|
50
repos/libports/src/test/memcpy/memcpy.h
Normal file
50
repos/libports/src/test/memcpy/memcpy.h
Normal file
@ -0,0 +1,50 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
||||
enum {
|
||||
BUF_SIZE = 8UL*1024UL*1024UL,
|
||||
ITERATION = 1024UL,
|
||||
TOTAL_MEM_KB = BUF_SIZE / 1024 * ITERATION,
|
||||
};
|
||||
|
||||
|
||||
template <typename Test>
|
||||
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;
|
||||
}
|
3
repos/libports/src/test/memcpy/target.mk
Normal file
3
repos/libports/src/test/memcpy/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = test-memcpy
|
||||
SRC_CC = main.cc
|
||||
LIBS += libc
|
Loading…
x
Reference in New Issue
Block a user