genode/repos/os/src/test/fb_bench/main.cc

151 lines
4.2 KiB
C++

/*
* \brief Framebuffer throughput test
* \author Norman Feske
* \author Martin Stein
* \date 2015-06-05
*/
/*
* Copyright (C) 2012-2017 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.
*/
/* Genode includes */
#include <base/component.h>
#include <base/heap.h>
#include <base/attached_dataspace.h>
#include <blit/blit.h>
#include <framebuffer_session/connection.h>
#include <timer_session/connection.h>
using namespace Genode;
struct Test
{
enum { DURATION_MS = 2000 };
Env &env;
int id;
Timer::Connection timer { env };
Heap heap { env.ram(), env.rm() };
Framebuffer::Connection fb { env, Framebuffer::Mode() };
Attached_dataspace fb_ds { env.rm(), fb.dataspace() };
Framebuffer::Mode const fb_mode { fb.mode() };
char *buf[2];
Test(Env &env, int id, char const *brief) : env(env), id(id)
{
log("\nTEST ", id, ": ", brief, "\n");
for (unsigned i = 0; i < 2; i++) {
if (!heap.alloc(fb_ds.size(), (void **)&buf[i])) {
env.parent().exit(-1); }
}
/* fill one memory buffer with white pixels */
memset(buf[1], ~0, fb_ds.size());
}
void conclusion(unsigned kib, uint64_t start_ms, uint64_t end_ms) {
log("throughput: ", kib / (end_ms - start_ms), " MiB/sec"); }
~Test() { log("\nTEST ", id, " finished\n"); }
private:
/*
* Noncopyable
*/
Test(Test const &);
Test &operator = (Test const &);
};
struct Bytewise_ram_test : Test
{
static constexpr char const *brief = "byte-wise memcpy from RAM to RAM";
Bytewise_ram_test(Env &env, int id) : Test(env, id, brief)
{
unsigned kib = 0;
uint64_t const start_ms = timer.elapsed_ms();
for (; timer.elapsed_ms() - start_ms < DURATION_MS;) {
memcpy(buf[0], buf[1], fb_ds.size());
kib += fb_ds.size() / 1024;
}
conclusion(kib, start_ms, timer.elapsed_ms());
}
};
struct Bytewise_fb_test : Test
{
static constexpr char const *brief = "byte-wise memcpy from RAM to FB";
Bytewise_fb_test(Env &env, int id) : Test(env, id, brief)
{
unsigned kib = 0;
uint64_t const start_ms = timer.elapsed_ms();
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
memcpy(fb_ds.local_addr<char>(), buf[i % 2], fb_ds.size());
kib += fb_ds.size() / 1024;
}
conclusion(kib, start_ms, timer.elapsed_ms());
}
};
struct Blit_test : Test
{
static constexpr char const *brief = "copy via blit library from RAM to FB";
Blit_test(Env &env, int id) : Test(env, id, brief)
{
unsigned kib = 0;
uint64_t const start_ms = timer.elapsed_ms();
unsigned const w = fb_mode.width() * fb_mode.bytes_per_pixel();
unsigned const h = fb_mode.height();
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
blit(buf[i % 2], w, fb_ds.local_addr<char>(), w, w, h);
kib += (w * h) / 1024;
}
conclusion(kib, start_ms, timer.elapsed_ms());
}
};
struct Unaligned_blit_test : Test
{
static constexpr char const *brief = "unaligned copy via blit library from RAM to FB";
Unaligned_blit_test(Env &env, int id) : Test(env, id, brief)
{
unsigned kib = 0;
uint64_t const start_ms = timer.elapsed_ms();
unsigned const w = fb_mode.width() * fb_mode.bytes_per_pixel();
unsigned const h = fb_mode.height();
for (unsigned i = 0; timer.elapsed_ms() - start_ms < DURATION_MS; i++) {
blit(buf[i % 2] + 2, w, fb_ds.local_addr<char>() + 2, w, w - 2, h);
kib += (w * h) / 1024;
}
conclusion(kib, start_ms, timer.elapsed_ms());
}
};
struct Main
{
Constructible<Bytewise_ram_test> test_1 { };
Constructible<Bytewise_fb_test> test_2 { };
Constructible<Blit_test> test_3 { };
Constructible<Unaligned_blit_test> test_4 { };
Main(Env &env)
{
log("--- Framebuffer benchmark ---");
test_1.construct(env, 1); test_1.destruct();
test_2.construct(env, 2); test_2.destruct();
test_3.construct(env, 3); test_3.destruct();
test_4.construct(env, 4); test_4.destruct();
log("--- Framebuffer benchmark finished ---");
env.parent().exit(0);
}
};
void Component::construct(Env &env) { static Main main(env); }