summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authordrd <drd@ableton.com>2017-02-16 17:28:54 +0100
committerdrd <drd@ableton.com>2017-02-16 17:45:25 +0100
commite2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69 (patch)
treea57fe24b425ad37b3ce5cf32aefec99cee7ede12 /tests
parente29b2efa89ccfab0c631dae771b8c0e5b9616839 (diff)
downloadingen-e2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69.tar.gz
ingen-e2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69.tar.bz2
ingen-e2f6b686003f86af8a64e7c6f7e8cf8c2da7ba69.zip
Preliminary alternative parallel traversal/benchmarking work
Diffstat (limited to 'tests')
-rw-r--r--tests/TestClient.hpp90
-rw-r--r--tests/ingen_bench.cpp189
-rw-r--r--tests/ingen_test.cpp74
3 files changed, 284 insertions, 69 deletions
diff --git a/tests/TestClient.hpp b/tests/TestClient.hpp
new file mode 100644
index 00000000..f1e0c5a7
--- /dev/null
+++ b/tests/TestClient.hpp
@@ -0,0 +1,90 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2017 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef INGEN_TESTCLIENT_HPP
+#define INGEN_TESTCLIENT_HPP
+
+#include "ingen/Interface.hpp"
+
+using namespace Ingen;
+
+class TestClient : public Ingen::Interface
+{
+public:
+ explicit TestClient(Log& log) : _log(log) {}
+ ~TestClient() {}
+
+ Raul::URI uri() const { return Raul::URI("ingen:testClient"); }
+
+ void bundle_begin() {}
+
+ void bundle_end() {}
+
+ void put(const Raul::URI& uri,
+ const Properties& properties,
+ Resource::Graph ctx = Resource::Graph::DEFAULT) {}
+
+ void delta(const Raul::URI& uri,
+ const Properties& remove,
+ const Properties& add) {}
+
+ void copy(const Raul::URI& old_uri,
+ const Raul::URI& new_uri) {}
+
+ void move(const Raul::Path& old_path,
+ const Raul::Path& new_path) {}
+
+ void del(const Raul::URI& uri) {}
+
+ void connect(const Raul::Path& tail,
+ const Raul::Path& head) {}
+
+ void disconnect(const Raul::Path& tail,
+ const Raul::Path& head) {}
+
+ void disconnect_all(const Raul::Path& parent_patch_path,
+ const Raul::Path& path) {}
+
+ void set_property(const Raul::URI& subject,
+ const Raul::URI& predicate,
+ const Atom& value) {}
+
+ void set_response_id(int32_t id) {}
+
+ void get(const Raul::URI& uri) {}
+
+ void undo() {}
+
+ void redo() {}
+
+ void response(int32_t id, Status status, const std::string& subject) {
+ if (status != Status::SUCCESS) {
+ _log.error(fmt("error on message %1%: %2% (%3%)\n")
+ % id % ingen_status_string(status) % subject);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ void error(const std::string& msg) {
+ _log.error(fmt("error: %1%\n") % msg);
+ exit(EXIT_FAILURE);
+ }
+
+private:
+ Log& _log;
+};
+
+#endif // INGEN_TESTCLIENT_HPP
diff --git a/tests/ingen_bench.cpp b/tests/ingen_bench.cpp
new file mode 100644
index 00000000..c8203331
--- /dev/null
+++ b/tests/ingen_bench.cpp
@@ -0,0 +1,189 @@
+/*
+ This file is part of Ingen.
+ Copyright 2007-2017 David Robillard <http://drobilla.net/>
+
+ Ingen is free software: you can redistribute it and/or modify it under the
+ terms of the GNU Affero General Public License as published by the Free
+ Software Foundation, either version 3 of the License, or any later version.
+
+ Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU Affero General Public License for details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with Ingen. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <signal.h>
+#include <stdlib.h>
+
+#include <iostream>
+#include <string>
+#include <thread>
+
+#include <boost/optional.hpp>
+
+#include <glibmm/convert.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/thread.h>
+#include <glibmm/timer.h>
+
+#include "raul/Path.hpp"
+
+#include "serd/serd.h"
+#include "sord/sordmm.hpp"
+#include "sratom/sratom.h"
+
+#include "ingen_config.h"
+
+#include "ingen/AtomReader.hpp"
+#include "ingen/AtomWriter.hpp"
+#include "ingen/Configuration.hpp"
+#include "ingen/Configuration.hpp"
+#include "ingen/EngineBase.hpp"
+#include "ingen/Interface.hpp"
+#include "ingen/Parser.hpp"
+#include "ingen/Serialiser.hpp"
+#include "ingen/Store.hpp"
+#include "ingen/URIMap.hpp"
+#include "ingen/World.hpp"
+#include "ingen/client/ThreadedSigClientInterface.hpp"
+#include "ingen/runtime_paths.hpp"
+#include "ingen/types.hpp"
+#include "../src/server/Clock.hpp" // FIXME
+
+#include "TestClient.hpp"
+
+using namespace std;
+using namespace Ingen;
+
+World* world = NULL;
+
+static void
+ingen_try(bool cond, const char* msg)
+{
+ if (!cond) {
+ cerr << "ingen: Error: " << msg << endl;
+ delete world;
+ exit(EXIT_FAILURE);
+ }
+}
+
+static uint32_t
+flush_events(Ingen::World* world, const uint32_t start)
+{
+ static const uint32_t block_length = 4096;
+ int count = 0;
+ uint32_t offset = start;
+ while (world->engine()->pending_events()) {
+ world->engine()->locate(offset, block_length);
+ world->engine()->run(block_length);
+ world->engine()->main_iteration();
+ g_usleep(1000);
+ ++count;
+ offset += block_length;
+ }
+ return offset;
+}
+
+static std::string
+real_path(const char* path)
+{
+ char* const c_real_path = realpath(path, NULL);
+ const std::string result(c_real_path ? c_real_path : "");
+ free(c_real_path);
+ return result;
+}
+
+int
+main(int argc, char** argv)
+{
+ Glib::thread_init();
+ set_bundle_path_from_code((void*)&flush_events);
+
+ // Create world
+ try {
+ world = new World(NULL, NULL, NULL);
+ world->conf().add(
+ "output", "output", 'O', "File to write benchmark output",
+ Ingen::Configuration::SESSION, world->forge().String, Atom());
+ world->load_configuration(argc, argv);
+ } catch (std::exception& e) {
+ cout << "ingen: " << e.what() << endl;
+ return EXIT_FAILURE;
+ }
+
+ // Get mandatory command line arguments
+ const Atom& load = world->conf().option("load");
+ const Atom& out = world->conf().option("output");
+ if (!load.is_valid() || !out.is_valid()) {
+ cerr << "Usage: ingen_bench --load START_GRAPH --output OUT_FILE" << endl;
+ return EXIT_FAILURE;
+ }
+
+ // Get start graph and output file options
+ const std::string start_graph = real_path((const char*)load.get_body());
+ const std::string out_file = (const char*)out.get_body();
+ if (start_graph.empty()) {
+ cerr << "error: initial graph '"
+ << ((const char*)load.get_body())
+ << "' does not exist" << endl;
+ return EXIT_FAILURE;
+ }
+
+ // Load modules
+ ingen_try(world->load_module("server_profiled"),
+ "Unable to load server module");
+
+ // Initialise engine
+ ingen_try(bool(world->engine()),
+ "Unable to create engine");
+ world->engine()->init(48000.0, 4096, 4096);
+ world->engine()->activate();
+
+ // Load graph
+ if (!world->parser()->parse_file(world, world->interface().get(), start_graph)) {
+ cerr << "error: failed to load initial graph " << start_graph << endl;
+ return EXIT_FAILURE;
+ }
+ uint32_t time = flush_events(world, 0);
+
+ Ingen::Server::Clock clock;
+ static const uint32_t n_test_frames = 1 << 20;
+ static const uint32_t block_length = 4096;
+
+ // Set up real-time scheduling for this (main run) thread
+ pthread_t pthread = pthread_self();
+ const int policy = SCHED_FIFO;
+ sched_param sp;
+ sp.sched_priority = 90;
+ if (pthread_setschedparam(pthread, policy, &sp)) {
+ world->log().error(
+ fmt("Failed to set real-time priority of run thread (%s)\n")
+ % strerror(errno));
+ }
+
+ const uint64_t t_start = clock.now_microseconds();
+ for (uint32_t i = time; i < time + n_test_frames; i += block_length) {
+ world->engine()->locate(i, block_length);
+ world->engine()->run(block_length);
+ //world->engine()->main_iteration();
+ }
+ const uint64_t t_end = clock.now_microseconds();
+
+ FILE* log = fopen(out_file.c_str(), "a");
+ if (ftell(log) == 0) {
+ fprintf(log, "n_threads\trun_time\tn_frames\n");
+ }
+ fprintf(log, "%u\t%llu\t%u\n",
+ world->conf().option("threads").get<int32_t>(),
+ t_end - t_start,
+ n_test_frames);
+ fclose(log);
+
+ // Shut down
+ world->engine()->deactivate();
+
+ delete world;
+ return EXIT_SUCCESS;
+}
diff --git a/tests/ingen_test.cpp b/tests/ingen_test.cpp
index 1ac2e383..d55789db 100644
--- a/tests/ingen_test.cpp
+++ b/tests/ingen_test.cpp
@@ -51,78 +51,13 @@
#include "ingen/runtime_paths.hpp"
#include "ingen/types.hpp"
+#include "TestClient.hpp"
+
using namespace std;
using namespace Ingen;
World* world = NULL;
-class TestClient : public Interface
-{
-public:
- explicit TestClient(Log& log) : _log(log) {}
- ~TestClient() {}
-
- Raul::URI uri() const { return Raul::URI("ingen:testClient"); }
-
- void bundle_begin() {}
-
- void bundle_end() {}
-
- void put(const Raul::URI& uri,
- const Properties& properties,
- Resource::Graph ctx = Resource::Graph::DEFAULT) {}
-
- void delta(const Raul::URI& uri,
- const Properties& remove,
- const Properties& add) {}
-
- void copy(const Raul::URI& old_uri,
- const Raul::URI& new_uri) {}
-
- void move(const Raul::Path& old_path,
- const Raul::Path& new_path) {}
-
- void del(const Raul::URI& uri) {}
-
- void connect(const Raul::Path& tail,
- const Raul::Path& head) {}
-
- void disconnect(const Raul::Path& tail,
- const Raul::Path& head) {}
-
- void disconnect_all(const Raul::Path& parent_patch_path,
- const Raul::Path& path) {}
-
- void set_property(const Raul::URI& subject,
- const Raul::URI& predicate,
- const Atom& value) {}
-
- void set_response_id(int32_t id) {}
-
- void get(const Raul::URI& uri) {}
-
- void undo() {}
-
- void redo() {}
-
- void response(int32_t id, Status status, const std::string& subject) {
- if (status != Status::SUCCESS) {
- _log.error(fmt("error on message %1%: %2% (%3%)\n")
- % id % ingen_status_string(status) % subject);
- exit(EXIT_FAILURE);
- }
- }
-
- void error(const std::string& msg) {
- _log.error(fmt("error: %1%\n") % msg);
- exit(EXIT_FAILURE);
- }
-
-private:
- Log& _log;
-};
-
-
static void
ingen_try(bool cond, const char* msg)
{
@@ -158,7 +93,8 @@ main(int argc, char** argv)
// Create world
try {
- world = new World(argc, argv, NULL, NULL, NULL);
+ world = new World(NULL, NULL, NULL);
+ world->load_configuration(argc, argv);
} catch (std::exception& e) {
cout << "ingen: " << e.what() << endl;
return EXIT_FAILURE;
@@ -194,7 +130,7 @@ main(int argc, char** argv)
world->engine()->init(48000.0, 4096, 4096);
world->engine()->activate();
- // Load patch
+ // Load graph
if (!world->parser()->parse_file(world, world->interface().get(), start_graph)) {
cerr << "error: failed to load initial graph " << start_graph << endl;
return EXIT_FAILURE;