test/cache: refine test pattern

- run multiple access patterns (touch words, touch lines, memcpy)
- add make file for linux

genodelabs/genode#4454
This commit is contained in:
Johannes Schlatow 2022-03-07 17:24:44 +01:00 committed by Christian Helmuth
parent 5a0e22eb98
commit 052c33fc8c
6 changed files with 189 additions and 59 deletions

55
repos/os/src/test/cache/common.h vendored Normal file
View File

@ -0,0 +1,55 @@
/*
* \brief Test defintions common for Genode and Linux
* \author Johannes Schlatow
* \date 2022-03-07
*
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__TEST__CACHE__COMMON_H_
#define _SRC__TEST__CACHE__COMMON_H_
template <typename TEST>
unsigned long timed_test(void * src, void * dst, size_t sz, unsigned iterations, TEST && func)
{
Time s { };
for (; iterations; iterations--)
func(src, dst, sz);
{
Time e { } ;
Duration d = Time::duration(s, e);
return d.value;
}
}
void touch_words(void * src, void *, size_t size)
{
unsigned * data = reinterpret_cast<unsigned*>(src);
for (size = size/sizeof(unsigned); size; size--)
data[size]++;
}
template<size_t START_SZ_KB, size_t END_SZ_KB, typename TEST>
void sweep_test(void * src, void * dst, unsigned iterations, TEST && func)
{
size_t size = START_SZ_KB;
while (size <= END_SZ_KB)
{
func(src, dst, size*1024, iterations);
size = size << 1;
}
}
#endif /* _SRC__TEST__CACHE__COMMON_H_ */

38
repos/os/src/test/cache/genode_time.h vendored Normal file
View File

@ -0,0 +1,38 @@
/*
* \brief Time-taking defintions for Genode test cases
* \author Johannes Schlatow
* \date 2022-03-07
*
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__TEST__CACHE__GENODE_TIME_H_
#define _SRC__TEST__CACHE__GENODE_TIME_H_
#include <trace/timestamp.h>
using namespace Genode::Trace;
using namespace Genode;
struct Duration { unsigned long value; };
struct Time
{
Timestamp _ts { timestamp() };
static Duration duration(Time t1, Time t2)
{
Timestamp diff = t2._ts - t1._ts;
if (t2._ts < t1._ts) diff--;
return Duration { (unsigned long)diff };
}
};
#endif /* _SRC__TEST__CACHE__GENODE_TIME_H_ */

13
repos/os/src/test/cache/linux/Makefile vendored Normal file
View File

@ -0,0 +1,13 @@
INC_DIR = $(PWD)/..
ifneq (,$(findstring arm-,$(shell gcc -dumpmachine)))
CC_MARCH = -marm
else
CC_MARCH =
endif
cache: main.cc $(INC_DIR)/common.h
g++ -I$(INC_DIR) $(CC_MARCH) -O2 -Wall -Wextra -Weffc++ -std=gnu++11 $< -o $@
clean:
rm -f *~ cache

60
repos/os/src/test/cache/linux/main.cc vendored Normal file
View File

@ -0,0 +1,60 @@
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <cstdio>
struct Duration { unsigned long value; };
struct Time
{
timespec _timespec { 0, 0 };
Time()
{
clock_gettime(CLOCK_REALTIME, &_timespec);
}
Time(timespec timespec) : _timespec(timespec) { }
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) };
}
};
#include "common.h"
void triplet_test(void * src, void * dst, size_t size, unsigned iterations)
{
size_t size_kb = size / 1024;
unsigned long res1 = timed_test(src, nullptr, size, iterations, touch_words);
unsigned long res2 = timed_test(src, src, size, iterations, memcpy);
unsigned long res3 = timed_test(src, dst, size, iterations, memcpy);
printf("%luKB (nsec/KB): %lu | %lu | %lu\n", size_kb,
1000*res1 / size_kb / iterations,
1000*res2 / size_kb / iterations,
1000*res3 / size_kb / iterations);
}
int main(int, char**)
{
enum { MAX_KB = 4*1024 };
char * buf1 = new char[MAX_KB*1024];
char * buf2 = new char[MAX_KB*1024];
memset(buf1, 0, MAX_KB*1024);
memset(buf2, 0, MAX_KB*1024);
sweep_test<8, MAX_KB>(buf1, buf2, 100, triplet_test);
delete[] buf1;
delete[] buf2;
}

View File

@ -15,56 +15,24 @@
#include <base/log.h>
#include <base/component.h>
#include <base/heap.h>
#include <trace/timestamp.h>
using namespace Genode::Trace;
#include "genode_time.h"
#include "common.h"
class Test
void triplet_test(void * src, void * dst, size_t size, unsigned iterations)
{
private:
Genode::Heap &_alloc;
Genode::size_t _size;
size_t size_kb = size / 1024;
unsigned *_data { 0 };
unsigned long res1 = timed_test(src, nullptr, size, iterations, touch_words);
unsigned long res2 = timed_test(src, src, size, iterations, memcpy_cpu);
unsigned long res3 = timed_test(src, dst, size, iterations, memcpy_cpu);
Timestamp ts_to_time(Timestamp start, Timestamp end)
{
Timestamp diff = end - start;
if (end < start) diff--;
log(size_kb, "KB (Cycles/KB): ",
res1 / size_kb / iterations, " | ",
res2 / size_kb / iterations, " | ",
res3 / size_kb / iterations);
}
return diff;
}
Test(const Test &);
void operator=(const Test&);
public:
Test(Genode::Heap &alloc, Genode::size_t size_bytes)
: _alloc(alloc),
_size(size_bytes/sizeof(unsigned))
{
_data = new (_alloc) unsigned[_size];
}
~Test()
{
destroy(_alloc, _data);
}
Timestamp read_write(unsigned iterations=100)
{
Timestamp start_ts = timestamp();
for (Genode::size_t i=0; i < iterations; i++) {
for (Genode::size_t index=0; index < _size; index++) {
_data[index]++;
}
}
return ts_to_time(start_ts, timestamp()) / iterations;
}
};
struct Main
{
@ -80,28 +48,23 @@ Main::Main(Genode::Env &env) : env(env)
{
using namespace Genode;
log("--- test-cache started ---");
enum { MAX_KB = 4*1024 };
enum {
START_SIZE = 8,
END_SIZE = 1024 * 4,
THRESHOLD_PERCENT = 10,
};
char * buf1 = new (heap) char[MAX_KB*1024];
char * buf2 = new (heap) char[MAX_KB*1024];
size_t size = START_SIZE;
while (size <= END_SIZE)
{
log("\n--- Running tests for size ", size, "KB ---");
memset(buf1, 0, MAX_KB*1024);
memset(buf2, 0, MAX_KB*1024);
Test test(heap, size*1024);
log("Read/write: ", test.read_write() / size, " cycles on average per KB");
log("--- test-cache started (touch words | touch lines | memcpy) ---");
size = size << 1;
}
sweep_test<8, MAX_KB>(buf1, buf2, 30, triplet_test);
log("--- test-cache done ---");
destroy(heap, buf1);
destroy(heap, buf2);
}
void Component::construct(Genode::Env &env) { static Main inst(env); }
Genode::size_t Component::stack_size() { return 32*1024*sizeof(long); }

View File

@ -1,3 +1,4 @@
TARGET = test-cache
SRC_CC = main.cc
INC_DIR += $(PRG_DIR)
LIBS = base