aboutsummaryrefslogtreecommitdiff
path: root/modules/benchmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/benchmark.c')
-rw-r--r--modules/benchmark.c938
1 files changed, 582 insertions, 356 deletions
diff --git a/modules/benchmark.c b/modules/benchmark.c
index 26de9557..018e30fe 100644
--- a/modules/benchmark.c
+++ b/modules/benchmark.c
@@ -1,10 +1,10 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2009 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2003-2009 L. A. F. Pereira <l@tia.mat.br>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 2.
+ * the Free Software Foundation, version 2 or later.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -16,48 +16,84 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#define _GNU_SOURCE
+#include <config.h>
#include <hardinfo.h>
#include <iconcache.h>
#include <shell.h>
-#include <config.h>
#include <syncmanager.h>
-#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/time.h>
-#include <sys/types.h>
#include <signal.h>
+#include <sys/types.h>
+#include "appf.h"
#include "benchmark.h"
+#include "cpu_util.h"
#include "benchmark/bench_results.c"
bench_value bench_results[BENCHMARK_N_ENTRIES];
static void do_benchmark(void (*benchmark_function)(void), int entry);
-static gchar *benchmark_include_results_reverse(bench_value result, const gchar * benchmark);
-static gchar *benchmark_include_results(bench_value result, const gchar * benchmark);
+static gchar *benchmark_include_results_reverse(bench_value result,
+ const gchar *benchmark);
+static gchar *benchmark_include_results(bench_value result,
+ const gchar *benchmark);
/* ModuleEntry entries, scan_*(), callback_*(), etc. */
#include "benchmark/benches.c"
-static gboolean sending_benchmark_results = FALSE;
-
-char *bench_value_to_str(bench_value r) {
- return g_strdup_printf("%lf; %lf; %d", r.result, r.elapsed_time, r.threads_used);
+char *bench_value_to_str(bench_value r)
+{
+ gboolean has_rev = r.revision >= 0;
+ gboolean has_extra = r.extra && *r.extra != 0;
+ gboolean has_user_note = r.user_note && *r.user_note != 0;
+ char *ret = g_strdup_printf("%lf; %lf; %d", r.result, r.elapsed_time,
+ r.threads_used);
+ if (has_rev || has_extra || has_user_note)
+ ret = appf(ret, "; ", "%d", r.revision);
+ if (has_extra || has_user_note)
+ ret = appf(ret, "; ", "%s", r.extra);
+ if (has_user_note)
+ ret = appf(ret, "; ", "%s", r.user_note);
+ return ret;
}
-bench_value bench_value_from_str(const char* str) {
+bench_value bench_value_from_str(const char *str)
+{
bench_value ret = EMPTY_BENCH_VALUE;
- double r, e;
- int t, c;
+ char rstr[32] = "", estr[32] = "", *p;
+ int t, c, v;
+ char extra[256], user_note[256];
if (str) {
- c = sscanf(str, "%lf; %lf; %d", &r, &e, &t);
+ /* try to handle floats from locales that use ',' or '.' as decimal sep
+ */
+ c = sscanf(
+ str, "%[-+0-9.,]; %[-+0-9.,]; %d; %d; %255[^\r\n;|]; %255[^\r\n;|]",
+ rstr, estr, &t, &v, extra, user_note);
if (c >= 3) {
- ret.result = r;
- ret.elapsed_time = e;
+ if ((p = strchr(rstr, ','))) {
+ *p = '.';
+ }
+ if ((p = strchr(estr, ','))) {
+ *p = '.';
+ }
+ ret.result = g_ascii_strtod(rstr, NULL);
+ ret.elapsed_time = g_ascii_strtod(estr, NULL);
ret.threads_used = t;
}
+ if (c >= 4) {
+ ret.revision = v;
+ }
+ if (c >= 5) {
+ strcpy(ret.extra, extra);
+ }
+ if (c >= 6) {
+ strcpy(ret.user_note, user_note);
+ }
}
return ret;
}
@@ -65,46 +101,51 @@ bench_value bench_value_from_str(const char* str) {
typedef struct _ParallelBenchTask ParallelBenchTask;
struct _ParallelBenchTask {
- gint thread_number;
- guint start, end;
- gpointer data, callback;
+ gint thread_number;
+ guint start, end;
+ gpointer data, callback;
int *stop;
};
static gpointer benchmark_crunch_for_dispatcher(gpointer data)
{
- ParallelBenchTask *pbt = (ParallelBenchTask *)data;
+ ParallelBenchTask *pbt = (ParallelBenchTask *)data;
gpointer (*callback)(void *data, gint thread_number);
- gpointer return_value = g_malloc(sizeof(int));
+ gpointer return_value = g_malloc(sizeof(double));
int count = 0;
if ((callback = pbt->callback)) {
- while(!*pbt->stop) {
+ while (!*pbt->stop) {
callback(pbt->data, pbt->thread_number);
/* don't count if didn't finish in time */
if (!*pbt->stop)
count++;
}
} else {
- DEBUG("this is thread %p; callback is NULL and it should't be!", g_thread_self());
+ DEBUG("this is thread %p; callback is NULL and it should't be!",
+ g_thread_self());
}
g_free(pbt);
- *(double*)return_value = (double)count;
+ *(double *)return_value = (double)count;
return return_value;
}
-bench_value benchmark_crunch_for(float seconds, gint n_threads,
- gpointer callback, gpointer callback_data) {
- int cpu_procs, cpu_cores, cpu_threads, thread_number, stop = 0;
+bench_value benchmark_crunch_for(float seconds,
+ gint n_threads,
+ gpointer callback,
+ gpointer callback_data)
+{
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+ int thread_number, stop = 0;
GSList *threads = NULL, *t;
GTimer *timer;
bench_value ret = EMPTY_BENCH_VALUE;
timer = g_timer_new();
- cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
if (n_threads > 0)
ret.threads_used = n_threads;
else if (n_threads < 0)
@@ -120,19 +161,22 @@ bench_value benchmark_crunch_for(float seconds, gint n_threads,
DEBUG("launching thread %d", thread_number);
pbt->thread_number = thread_number;
- pbt->data = callback_data;
+ pbt->data = callback_data;
pbt->callback = callback;
pbt->stop = &stop;
- thread = g_thread_new("dispatcher",
- (GThreadFunc)benchmark_crunch_for_dispatcher, pbt);
+#if GLIB_CHECK_VERSION(2,32,0)
+ thread = g_thread_new("dispatcher", (GThreadFunc)benchmark_crunch_for_dispatcher, pbt);
+#else
+ thread = g_thread_create((GThreadFunc)benchmark_crunch_for_dispatcher, pbt,TRUE,NULL);
+#endif
threads = g_slist_prepend(threads, thread);
DEBUG("thread %d launched as context %p", thread_number, thread);
}
/* wait for time */
- //while ( g_timer_elapsed(timer, NULL) < seconds ) { }
+ // while ( g_timer_elapsed(timer, NULL) < seconds ) { }
g_usleep(seconds * 1000000);
/* signal all threads to stop */
@@ -144,7 +188,7 @@ bench_value benchmark_crunch_for(float seconds, gint n_threads,
for (t = threads; t; t = t->next) {
DEBUG("waiting for thread with context %p", t->data);
gpointer *rv = g_thread_join((GThread *)t->data);
- ret.result += *(double*)rv;
+ ret.result += *(double *)rv;
g_free(rv);
}
@@ -158,17 +202,21 @@ bench_value benchmark_crunch_for(float seconds, gint n_threads,
static gpointer benchmark_parallel_for_dispatcher(gpointer data)
{
- ParallelBenchTask *pbt = (ParallelBenchTask *)data;
- gpointer (*callback)(unsigned int start, unsigned int end, void *data, gint thread_number);
- gpointer return_value = NULL;
+ ParallelBenchTask *pbt = (ParallelBenchTask *)data;
+ gpointer (*callback)(unsigned int start, unsigned int end, void *data,
+ gint thread_number);
+ gpointer return_value = NULL;
if ((callback = pbt->callback)) {
DEBUG("this is thread %p; items %d -> %d, data %p", g_thread_self(),
pbt->start, pbt->end, pbt->data);
- return_value = callback(pbt->start, pbt->end, pbt->data, pbt->thread_number);
- DEBUG("this is thread %p; return value is %p", g_thread_self(), return_value);
+ return_value =
+ callback(pbt->start, pbt->end, pbt->data, pbt->thread_number);
+ DEBUG("this is thread %p; return value is %p", g_thread_self(),
+ return_value);
} else {
- DEBUG("this is thread %p; callback is NULL and it should't be!", g_thread_self());
+ DEBUG("this is thread %p; callback is NULL and it should't be!",
+ g_thread_self());
}
g_free(pbt);
@@ -177,31 +225,43 @@ static gpointer benchmark_parallel_for_dispatcher(gpointer data)
}
/* one call for each thread to be used */
-bench_value benchmark_parallel(gint n_threads, gpointer callback, gpointer callback_data) {
- int cpu_procs, cpu_cores, cpu_threads;
- cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
- if (n_threads == 0) n_threads = cpu_threads;
- else if (n_threads == -1) n_threads = cpu_cores;
- return benchmark_parallel_for(n_threads, 0, n_threads, callback, callback_data);
+bench_value
+benchmark_parallel(gint n_threads, gpointer callback, gpointer callback_data)
+{
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
+
+ if (n_threads == 0)
+ n_threads = cpu_threads;
+ else if (n_threads == -1)
+ n_threads = cpu_cores;
+
+ return benchmark_parallel_for(n_threads, 0, n_threads, callback,
+ callback_data);
}
/* Note:
* benchmark_parallel_for(): element [start] included, but [end] is excluded.
- * callback(): expected to processes elements [start] through [end] inclusive.
+ * callback(): expected to processes elements [start] through [end]
+ * inclusive.
*/
-bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
- gpointer callback, gpointer callback_data) {
- gchar *temp;
- int cpu_procs, cpu_cores, cpu_threads;
- guint iter_per_thread, iter, thread_number = 0;
- GSList *threads = NULL, *t;
- GTimer *timer;
+bench_value benchmark_parallel_for(gint n_threads,
+ guint start,
+ guint end,
+ gpointer callback,
+ gpointer callback_data)
+{
+ gchar *temp;
+ int cpu_procs, cpu_cores, cpu_threads, cpu_nodes;
+ guint iter_per_thread, iter, thread_number = 0;
+ GSList *threads = NULL, *t;
+ GTimer *timer;
bench_value ret = EMPTY_BENCH_VALUE;
timer = g_timer_new();
- cpu_procs_cores_threads(&cpu_procs, &cpu_cores, &cpu_threads);
+ cpu_procs_cores_threads_nodes(&cpu_procs, &cpu_cores, &cpu_threads, &cpu_nodes);
if (n_threads > 0)
ret.threads_used = n_threads;
@@ -214,18 +274,19 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
iter_per_thread = (end - start) / ret.threads_used;
if (iter_per_thread == 0) {
- DEBUG("not enough items per thread; disabling one thread");
- ret.threads_used--;
+ DEBUG("not enough items per thread; disabling one thread");
+ ret.threads_used--;
} else {
- break;
+ break;
}
}
- DEBUG("Using %d threads across %d logical processors; processing %d elements (%d per thread)",
+ DEBUG("Using %d threads across %d logical processors; processing %d "
+ "elements (%d per thread)",
ret.threads_used, cpu_threads, (end - start), iter_per_thread);
g_timer_start(timer);
- for (iter = start; iter < end; ) {
+ for (iter = start; iter < end;) {
ParallelBenchTask *pbt = g_new0(ParallelBenchTask, 1);
GThread *thread;
@@ -238,13 +299,17 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
DEBUG("launching thread %d", 1 + thread_number);
pbt->thread_number = thread_number++;
- pbt->start = ts;
- pbt->end = te - 1;
- pbt->data = callback_data;
+ pbt->start = ts;
+ pbt->end = te - 1;
+ pbt->data = callback_data;
pbt->callback = callback;
- thread = g_thread_new("dispatcher",
- (GThreadFunc)benchmark_parallel_for_dispatcher, pbt);
+#if GLIB_CHECK_VERSION(2,32,0)
+ thread = g_thread_new("dispatcher", (GThreadFunc)benchmark_parallel_for_dispatcher, pbt);
+#else
+ thread = g_thread_create((GThreadFunc)benchmark_parallel_for_dispatcher, pbt,TRUE,NULL);
+#endif
+
threads = g_slist_prepend(threads, thread);
DEBUG("thread %d launched as context %p", thread_number, thread);
@@ -255,8 +320,9 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
DEBUG("waiting for thread with context %p", t->data);
gpointer *rv = g_thread_join((GThread *)t->data);
if (rv) {
- if (ret.result == -1.0) ret.result = 0;
- ret.result += *(double*)rv;
+ if (ret.result == -1.0)
+ ret.result = 0;
+ ret.result += *(double *)rv;
}
g_free(rv);
}
@@ -272,140 +338,256 @@ bench_value benchmark_parallel_for(gint n_threads, guint start, guint end,
return ret;
}
-static gchar *clean_cpuname(gchar *cpuname)
+gchar *hi_more_info(gchar *entry)
{
- gchar *ret = NULL, *tmp;
- gchar *remove[] = {
- "(R)", "(r)", "(TM)", "(tm)", "Processor",
- "Technology", "processor", "CPU",
- "cpu", "Genuine", "Authentic", NULL
- };
- gint i;
+ const gchar *info = moreinfo_lookup_with_prefix("BENCH", entry);
+ return g_strdup(info ? info : "?");
+}
+
+gchar *hi_get_field(gchar *field)
+{
+ const gchar *info = moreinfo_lookup_with_prefix("BENCH", field);
+ return g_strdup(info ? info : field);
+}
- ret = g_strdup(cpuname);
- for (i = 0; remove[i]; i++) {
- tmp = strreplace(ret, remove[i], "");
- g_free(ret);
- ret = tmp;
+static void br_mi_add(char **results_list, bench_result *b, gboolean select)
+{
+ static unsigned int ri = 0; /* to ensure key is unique */
+ gchar *rkey, *lbl, *elbl, *this_marker;
+
+ if (select) {
+ this_marker = format_with_ansi_color(_("This Machine"), "0;30;43",
+ params.fmt_opts);
+ } else {
+ this_marker = "";
}
- ret = strend(ret, '@');
- ret = g_strstrip(ret);
+ rkey = g_strdup_printf("%s__%d", b->machine->mid, ri++);
- tmp = g_strdup(ret);
- g_free(ret);
+ lbl = g_strdup_printf("%s%s%s%s", this_marker, select ? " " : "",
+ b->machine->cpu_name,
+ b->legacy ? problem_marker() : "");
+ elbl = key_label_escape(lbl);
- return tmp;
-}
+ *results_list = h_strdup_cprintf("$@%s%s$%s=%.2f|%s\n", *results_list,
+ select ? "*" : "", rkey, elbl,
+ b->bvalue.result, b->machine->cpu_config);
-gchar *hi_more_info(gchar * entry)
+ moreinfo_add_with_prefix("BENCH", rkey, bench_result_more_info(b));
+
+ g_free(lbl);
+ g_free(elbl);
+ g_free(rkey);
+ if (*this_marker)
+ g_free(this_marker);
+}
+gint bench_result_sort(gconstpointer a, gconstpointer b)
{
- gchar *info = moreinfo_lookup_with_prefix("BENCH", entry);
- if (info)
- return g_strdup(info);
- return g_strdup("?");
+ bench_result *A = (bench_result *)a, *B = (bench_result *)b;
+ if (A->bvalue.result < B->bvalue.result)
+ return -1;
+ if (A->bvalue.result > B->bvalue.result)
+ return 1;
+ return 0;
}
-gchar *hi_get_field(gchar * field)
+struct append_machine_result_json_data {
+ GSList **result_list;
+ const gchar *benchmark_name;
+};
+
+static void append_machine_result_json(JsonArray *array,
+ guint index,
+ JsonNode *element_node,
+ gpointer user_data)
{
- gchar *info = moreinfo_lookup_with_prefix("BENCH", field);
- if (info)
- return g_strdup(info);
- return g_strdup(field);
+ struct append_machine_result_json_data *data = user_data;
+ bench_result *result;
+
+ result = bench_result_benchmarkjson(data->benchmark_name, element_node);
+ *data->result_list = g_slist_append(*data->result_list, result);
}
-static void br_mi_add(char **results_list, bench_result *b, gboolean select) {
- gchar *ckey, *rkey;
+static GSList *benchmark_include_results_json(const gchar *path,
+ bench_value r,
+ const gchar *benchmark)
+{
+ JsonParser *parser;
+ JsonNode *root;
+ bench_result *this_machine = NULL;
+ GSList *result_list = NULL;
+ GError *error=NULL;
+
+ DEBUG("Loading benchmark results from JSON file %s", path);
+
+ parser = json_parser_new();
+ json_parser_load_from_file(parser, path, &error);
+ if(error){
+ DEBUG ("Unable to parse JSON %s %s", path, error->message);
+ g_error_free(error);
+ g_object_unref(parser);
+ return result_list;
+ }
- ckey = hardinfo_clean_label(b->machine->cpu_name, 0);
- rkey = strdup(b->machine->mid);
+ root = json_parser_get_root(parser);
+ if (json_node_get_node_type(root) != JSON_NODE_OBJECT) goto out;
- *results_list = h_strdup_cprintf("$%s%s$%s=%.2f|%s\n", *results_list,
- select ? "*" : "", rkey, ckey,
- b->bvalue.result, b->machine->cpu_config);
+ JsonObject *results = json_node_get_object(root);
+ if (results) {
+ JsonArray *machines = json_object_get_array_member(results, benchmark);
- moreinfo_add_with_prefix("BENCH", rkey, bench_result_more_info(b) );
+ if (machines) {
+ struct append_machine_result_json_data data = {
+ .result_list = &result_list,
+ .benchmark_name = benchmark,
+ };
+ json_array_foreach_element(machines, append_machine_result_json,
+ &data);
+ }
+ }
- g_free(ckey);
- g_free(rkey);
+out:
+ g_object_unref(parser);
+
+ return result_list;
}
-static gchar *__benchmark_include_results(bench_value r,
- const gchar * benchmark,
- ShellOrderType order_type)
+static gchar *find_benchmark_conf(void)
{
- bench_result *b = NULL;
- GKeyFile *conf;
- gchar **machines, *temp = NULL;;
- gchar *path, *results = g_strdup(""), *return_value, *processor_frequency, *processor_name;
- int i, n_threads;
+ const gchar *config_dir = g_get_user_config_dir();
+ gchar *path;
- moreinfo_del_with_prefix("BENCH");
+ path = g_build_filename(config_dir, "hardinfo2", "benchmark.json", NULL);
+ if (g_file_test(path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free(path);
- if (r.result > 0.0) {
- b = bench_result_this_machine(benchmark, r);
- br_mi_add(&results, b, 1);
+ path = g_build_filename(params.path_data, "benchmark.json", NULL);
+ if (g_file_test(path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free(path);
+
+ return NULL;
+}
- temp = bench_result_benchmarkconf_line(b);
- printf("[%s]\n%s", benchmark, temp);
- g_free(temp); temp = NULL;
+struct bench_window {
+ int min, max;
+};
+
+static struct bench_window get_bench_window(GSList *result_list,
+ const bench_result *this_machine)
+{
+ struct bench_window window = {};
+ int size = params.max_bench_results;
+ int len = g_slist_length(result_list);
+
+ if (size == 0)
+ size = 1;
+ else if (size < 0)
+ size = len;
+
+ int loc = g_slist_index(result_list, this_machine); /* -1 if not found */
+ if (loc >= 0) {
+ window.min = loc - size / 2;
+ window.max = window.min + size;
+ if (window.min < 0) {
+ window.min = 0;
+ window.max = MIN(size, len);
+ } else if (window.max > len) {
+ window.max = len;
+ window.min = MAX(len - size, 0);
+ }
+ } else {
+ window.min = 0;
+ window.max = len;
}
- conf = g_key_file_new();
+ DEBUG("...len: %d, loc: %d, win_size: %d, win: [%d..%d]\n", len, loc, size,
+ window.min, window.max - 1);
+
+ return window;
+}
+
+static gboolean is_in_bench_window(const struct bench_window *window, int i)
+{
+ return i >= window->min && i < window->max;
+}
- path = g_build_filename(g_get_home_dir(), ".hardinfo", "benchmark.conf", NULL);
- if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
- DEBUG("local benchmark.conf not found, trying system-wide");
- g_free(path);
- path = g_build_filename(params.path_data, "benchmark.conf", NULL);
+static gchar *benchmark_include_results_internal(bench_value this_machine_value,
+ const gchar *benchmark,
+ ShellOrderType order_type)
+{
+ bench_result *this_machine;
+ GSList *result_list, *li;
+ gchar *results = g_strdup("");
+ gchar *output;
+ gchar *path;
+ gint i;
+
+ path = find_benchmark_conf();
+ if (path) {
+ result_list = benchmark_include_results_json(
+ path, this_machine_value, benchmark);
}
- g_key_file_load_from_file(conf, path, 0, NULL);
- g_key_file_set_list_separator(conf, '|');
+ /* this result */
+ if (this_machine_value.result > 0.0) {
+ this_machine = bench_result_this_machine(benchmark, this_machine_value);
+ result_list = g_slist_prepend(result_list, this_machine);
+ } else {
+ this_machine = NULL;
+ }
- machines = g_key_file_get_keys(conf, benchmark, NULL, NULL);
- for (i = 0; machines && machines[i]; i++) {
- gchar **values;
- bench_result *sbr;
+ /* sort */
+ result_list = g_slist_sort(result_list, bench_result_sort);
+ if (order_type == SHELL_ORDER_DESCENDING)
+ result_list = g_slist_reverse(result_list);
- values = g_key_file_get_string_list(conf, benchmark, machines[i], NULL, NULL);
+ /* prepare for shell */
+ moreinfo_del_with_prefix("BENCH");
+
+ const struct bench_window window =
+ get_bench_window(result_list, this_machine);
+ for (i = 0, li = result_list; li; li = g_slist_next(li), i++) {
+ bench_result *br = li->data;
- sbr = bench_result_benchmarkconf(benchmark, machines[i], values);
- br_mi_add(&results, sbr, 0);
+ if (is_in_bench_window(&window, i))
+ br_mi_add(&results, br, br == this_machine);
- bench_result_free(sbr);
- g_strfreev(values);
+ bench_result_free(br); /* no longer needed */
}
+ g_slist_free(result_list);
+
+ output = g_strdup_printf("[$ShellParam$]\n"
+ "Zebra=1\n"
+ "OrderType=%d\n"
+ "ViewType=4\n"
+ "ColumnTitle$Extra1=%s\n" /* CPU Clock */
+ "ColumnTitle$Progress=%s\n" /* Results */
+ "ColumnTitle$TextValue=%s\n" /* CPU */
+ "ShowColumnHeaders=true\n"
+ "[%s]\n%s",
+ order_type, _("CPU Config"), _("Results"),
+ _("CPU"), benchmark, results);
- g_strfreev(machines);
g_free(path);
- g_key_file_free(conf);
-
- return_value = g_strdup_printf("[$ShellParam$]\n"
- "Zebra=1\n"
- "OrderType=%d\n"
- "ViewType=4\n"
- "ColumnTitle$Extra1=%s\n" /* CPU Clock */
- "ColumnTitle$Progress=%s\n" /* Results */
- "ColumnTitle$TextValue=%s\n" /* CPU */
- "ShowColumnHeaders=true\n"
- "[%s]\n%s",
- order_type,
- _("CPU Config"), _("Results"), _("CPU"),
- benchmark, results);
-
- bench_result_free(b);
- return return_value;
+ g_free(results);
+
+ return output;
}
-static gchar *benchmark_include_results_reverse(bench_value result, const gchar * benchmark)
+static gchar *benchmark_include_results_reverse(bench_value result,
+ const gchar *benchmark)
{
- return __benchmark_include_results(result, benchmark, SHELL_ORDER_DESCENDING);
+ return benchmark_include_results_internal(result, benchmark,
+ SHELL_ORDER_DESCENDING);
}
-static gchar *benchmark_include_results(bench_value result, const gchar * benchmark)
+static gchar *benchmark_include_results(bench_value result,
+ const gchar *benchmark)
{
- return __benchmark_include_results(result, benchmark, SHELL_ORDER_ASCENDING);
+ return benchmark_include_results_internal(result, benchmark,
+ SHELL_ORDER_ASCENDING);
}
typedef struct _BenchmarkDialog BenchmarkDialog;
@@ -414,11 +596,10 @@ struct _BenchmarkDialog {
bench_value r;
};
-static gboolean do_benchmark_handler(GIOChannel *source,
- GIOCondition condition,
- gpointer data)
+static gboolean
+do_benchmark_handler(GIOChannel *source, GIOCondition condition, gpointer data)
{
- BenchmarkDialog *bench_dialog = (BenchmarkDialog*)data;
+ BenchmarkDialog *bench_dialog = (BenchmarkDialog *)data;
GIOStatus status;
gchar *result;
bench_value r = EMPTY_BENCH_VALUE;
@@ -433,6 +614,9 @@ static gboolean do_benchmark_handler(GIOChannel *source,
}
r = bench_value_from_str(result);
+ /* attach a user note */
+ if (params.bench_user_note)
+ strncpy(r.user_note, params.bench_user_note, 255);
bench_dialog->r = r;
gtk_widget_destroy(bench_dialog->dialog);
@@ -445,118 +629,127 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
{
int old_priority = 0;
- if (params.gui_running && !sending_benchmark_results) {
- gchar *argv[] = { params.argv0, "-b", entries[entry].name,
- "-m", "benchmark.so", "-a", NULL };
- GPid bench_pid;
- gint bench_stdout;
- GtkWidget *bench_dialog;
- GtkWidget *bench_image;
- BenchmarkDialog *benchmark_dialog;
- GSpawnFlags spawn_flags = G_SPAWN_STDERR_TO_DEV_NULL;
- gchar *bench_status;
-
- bench_value r = EMPTY_BENCH_VALUE;
- bench_results[entry] = r;
-
- bench_status = g_strdup_printf(_("Benchmarking: <b>%s</b>."), entries[entry].name);
-
- shell_view_set_enabled(FALSE);
- shell_status_update(bench_status);
-
- g_free(bench_status);
-
- bench_image = icon_cache_get_image("benchmark.png");
- gtk_widget_show(bench_image);
-
-#if GTK_CHECK_VERSION(3, 0, 0)
- GtkWidget *button;
- GtkWidget *content_area;
- GtkWidget *hbox;
- GtkWidget *label;
-
- bench_dialog = gtk_dialog_new_with_buttons("",
- NULL,
- GTK_DIALOG_MODAL,
- _("Cancel"),
- GTK_RESPONSE_ACCEPT,
- NULL);
- content_area = gtk_dialog_get_content_area(GTK_DIALOG(bench_dialog));
- label = gtk_label_new(_("Benchmarking. Please do not move your mouse " \
- "or press any keys."));
- hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
- gtk_box_pack_start(GTK_BOX(hbox), bench_image, TRUE, TRUE, 5);
- gtk_box_pack_end(GTK_BOX(hbox), label, TRUE, TRUE, 5);
- gtk_container_add(GTK_CONTAINER (content_area), hbox);
- gtk_widget_show_all(bench_dialog);
+ if (params.skip_benchmarks)
+ return;
+
+ if (params.gui_running) {
+ gchar *argv[] = {params.argv0, "-b", entries[entry].name,
+ "-m", "benchmark.so", "-a",
+ NULL};
+ GPid bench_pid;
+ gint bench_stdout;
+ GtkWidget *bench_dialog;
+ GtkWidget *bench_image;
+ BenchmarkDialog *benchmark_dialog;
+ GSpawnFlags spawn_flags = G_SPAWN_STDERR_TO_DEV_NULL;
+ gchar *bench_status;
+ GtkWidget *content_area, *box, *label;
+ bench_value r = EMPTY_BENCH_VALUE;
+ bench_results[entry] = r;
+
+ bench_status =
+ g_strdup_printf(_("Benchmarking: <b>%s</b>."), entries[entry].name);
+
+ shell_view_set_enabled(FALSE);
+ shell_status_update(bench_status);
+
+ g_free(bench_status);
+
+ bench_image = icon_cache_get_image("benchmark.png");
+
+ bench_dialog = gtk_dialog_new_with_buttons ("Benchmarking...",
+ GTK_WINDOW(shell_get_main_shell()->transient_dialog),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL,
+ "Stop",
+ GTK_BUTTONS_CLOSE,
+ NULL);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(shell_get_main_shell()->transient_dialog), FALSE);
+
+ content_area = gtk_dialog_get_content_area (GTK_DIALOG(bench_dialog));
+
+#if GTK_CHECK_VERSION(3,0,0)
+ box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 1);
#else
- bench_dialog = gtk_message_dialog_new(GTK_WINDOW(shell_get_main_shell()->window),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_INFO,
- GTK_BUTTONS_NONE,
- _("Benchmarking. Please do not move your mouse " \
- "or press any keys."));
- gtk_dialog_add_buttons(GTK_DIALOG(bench_dialog),
- _("Cancel"), GTK_RESPONSE_ACCEPT, NULL);
- gtk_message_dialog_set_image(GTK_MESSAGE_DIALOG(bench_dialog), bench_image);
+ box = gtk_hbox_new(FALSE, 1);
#endif
+ label = gtk_label_new ("Please do not move your mouse\n"
+ "or press any keys.");
- while (gtk_events_pending()) {
- gtk_main_iteration();
- }
+ gtk_widget_show (bench_image);
- benchmark_dialog = g_new0(BenchmarkDialog, 1);
- benchmark_dialog->dialog = bench_dialog;
- benchmark_dialog->r = r;
+#if GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_halign (bench_image, GTK_ALIGN_START);
+#else
+ gtk_misc_set_alignment(GTK_MISC(bench_image), 0.0, 0.0);
+#endif
+
+ g_signal_connect_swapped (bench_dialog,
+ "response",
+ G_CALLBACK (gtk_widget_destroy),
+ bench_dialog);
- if (!g_path_is_absolute(params.argv0)) {
- spawn_flags |= G_SPAWN_SEARCH_PATH;
- }
+ gtk_box_pack_start (GTK_BOX(box), bench_image, TRUE, TRUE, 10);
+ gtk_box_pack_start (GTK_BOX(box), label, TRUE, TRUE, 10);
+ gtk_container_add (GTK_CONTAINER(content_area), box);
- if (g_spawn_async_with_pipes(NULL,
- argv, NULL,
- spawn_flags,
- NULL, NULL,
- &bench_pid,
- NULL, &bench_stdout, NULL,
- NULL)) {
- GIOChannel *channel;
- guint watch_id;
+ gtk_window_set_deletable(GTK_WINDOW(bench_dialog), FALSE);
+ gtk_widget_show_all (bench_dialog);
- DEBUG("spawning benchmark; pid=%d", bench_pid);
+ while (gtk_events_pending()) {
+ gtk_main_iteration();
+ }
- channel = g_io_channel_unix_new(bench_stdout);
- watch_id = g_io_add_watch(channel, G_IO_IN, do_benchmark_handler,
- benchmark_dialog);
+ benchmark_dialog = g_new0(BenchmarkDialog, 1);
+ benchmark_dialog->dialog = bench_dialog;
+ benchmark_dialog->r = r;
- switch (gtk_dialog_run(GTK_DIALOG(bench_dialog))) {
+ if (!g_path_is_absolute(params.argv0)) {
+ spawn_flags |= G_SPAWN_SEARCH_PATH;
+ }
+
+ if (g_spawn_async_with_pipes(NULL, argv, NULL, spawn_flags, NULL, NULL,
+ &bench_pid, NULL, &bench_stdout, NULL,
+ NULL)) {
+ GIOChannel *channel;
+ guint watch_id;
+
+ DEBUG("spawning benchmark; pid=%d", bench_pid);
+
+ channel = g_io_channel_unix_new(bench_stdout);
+ watch_id = g_io_add_watch(channel, G_IO_IN, do_benchmark_handler,
+ benchmark_dialog);
+
+ switch (gtk_dialog_run(GTK_DIALOG(bench_dialog))) {
case GTK_RESPONSE_NONE:
- DEBUG("benchmark finished");
- break;
+ DEBUG("benchmark finished");
+ break;
case GTK_RESPONSE_ACCEPT:
- DEBUG("cancelling benchmark");
+ DEBUG("cancelling benchmark");
- gtk_widget_destroy(bench_dialog);
- g_source_remove(watch_id);
- kill(bench_pid, SIGINT);
- }
+ gtk_widget_destroy(bench_dialog);
+ g_source_remove(watch_id);
+ kill(bench_pid, SIGINT);
+ }
- bench_results[entry] = benchmark_dialog->r;
+ bench_results[entry] = benchmark_dialog->r;
- g_io_channel_unref(channel);
- shell_view_set_enabled(TRUE);
- shell_status_set_enabled(TRUE);
- g_free(benchmark_dialog);
+ g_io_channel_unref(channel);
+ shell_view_set_enabled(TRUE);
+ shell_status_set_enabled(TRUE);
+ gtk_widget_set_sensitive(
+ GTK_WIDGET(shell_get_main_shell()->transient_dialog), TRUE);
+ g_free(benchmark_dialog);
- shell_status_update(_("Done."));
+ shell_status_update(_("Done."));
- return;
- }
+ return;
+ }
- gtk_widget_destroy(bench_dialog);
- g_free(benchmark_dialog);
- shell_status_set_enabled(TRUE);
- shell_status_update(_("Done."));
+ gtk_widget_destroy(bench_dialog);
+ g_free(benchmark_dialog);
+ shell_status_set_enabled(TRUE);
+ shell_status_update(_("Done."));
}
setpriority(PRIO_PROCESS, 0, -20);
@@ -564,79 +757,113 @@ static void do_benchmark(void (*benchmark_function)(void), int entry)
setpriority(PRIO_PROCESS, 0, old_priority);
}
-gchar *hi_module_get_name(void)
-{
- return g_strdup(_("Benchmarks"));
-}
+gchar *hi_module_get_name(void) { return g_strdup(_("Benchmarks")); }
-guchar hi_module_get_weight(void)
-{
- return 240;
-}
+guchar hi_module_get_weight(void) { return 240; }
-ModuleEntry *hi_module_get_entries(void)
-{
- return entries;
-}
+ModuleEntry *hi_module_get_entries(void) { return entries; }
-ModuleAbout *hi_module_get_about(void)
+const ModuleAbout *hi_module_get_about(void)
{
- static ModuleAbout ma[] = {
- {
- .author = "Leandro A. F. Pereira",
- .description = N_("Perform tasks and compare with other systems"),
- .version = VERSION,
- .license = "GNU GPL version 2"}
+ static const ModuleAbout ma = {
+ .author = "L. A. F. Pereira",
+ .description = N_("Perform tasks and compare with other systems"),
+ .version = VERSION,
+ .license = "GNU GPL version 2 or later.",
};
- return ma;
+ return &ma;
}
-static gchar *get_benchmark_results()
+static gchar *get_benchmark_results(gsize *len)
{
- gint i;
- void (*scan_callback) (gboolean rescan);
-
- sending_benchmark_results = TRUE;
-
- gchar *machine = module_call_method("devices::getProcessorName");
- gchar *machineclock = module_call_method("devices::getProcessorFrequency");
- gchar *machineram = module_call_method("devices::getMemoryTotal");
- gchar *result = g_strdup_printf("[param]\n"
- "machine=%s\n"
- "machineclock=%s\n"
- "machineram=%s\n"
- "nbenchmarks=%zu\n",
- machine,
- machineclock,
- machineram,
- G_N_ELEMENTS(entries) - 1);
+ void (*scan_callback)(gboolean);
+ JsonBuilder *builder;
+ JsonGenerator *generator;
+ JsonNode *root;
+ bench_machine *this_machine;
+ gchar *out;
+ guint i;
+
for (i = 0; i < G_N_ELEMENTS(entries); i++) {
- scan_callback = entries[i].scan_callback;
- if (!scan_callback)
+ if (!entries[i].name || !entries[i].scan_callback)
+ continue;
+ if (entries[i].flags & MODULE_FLAG_HIDE)
continue;
+ scan_callback = entries[i].scan_callback;
+ if (scan_callback)
+ scan_callback(bench_results[i].result < 0.0);
+ }
+
+ this_machine = bench_machine_this();
+ builder = json_builder_new();
+ json_builder_begin_object(builder);
+ for (i = 0; i < G_N_ELEMENTS(entries); i++) {
+ if (!entries[i].name || entries[i].flags & MODULE_FLAG_HIDE)
+ continue;
if (bench_results[i].result < 0.0) {
- /* benchmark was cancelled */
- scan_callback(TRUE);
- } else {
- scan_callback(FALSE);
+ /* Benchmark failed? */
+ continue;
}
- result = h_strdup_cprintf("[bench%d]\n"
- "name=%s\n"
- "value=%f\n",
- result,
- i, entries[i].name, bench_results[i]);
+ json_builder_set_member_name(builder, entries[i].name);
+
+ json_builder_begin_object(builder);
+
+#define ADD_JSON_VALUE(type, name, value) \
+ do { \
+ json_builder_set_member_name(builder, (name)); \
+ json_builder_add_##type##_value(builder, (value)); \
+ } while (0)
+
+ ADD_JSON_VALUE(string, "Board", this_machine->board);
+ ADD_JSON_VALUE(int, "MemoryInKiB", this_machine->memory_kiB);
+ ADD_JSON_VALUE(string, "CpuName", this_machine->cpu_name);
+ ADD_JSON_VALUE(string, "CpuDesc", this_machine->cpu_desc);
+ ADD_JSON_VALUE(string, "CpuConfig", this_machine->cpu_config);
+ ADD_JSON_VALUE(string, "CpuConfig", this_machine->cpu_config);
+ ADD_JSON_VALUE(string, "OpenGlRenderer", this_machine->ogl_renderer);
+ ADD_JSON_VALUE(string, "GpuDesc", this_machine->gpu_desc);
+ ADD_JSON_VALUE(int, "NumCpus", this_machine->processors);
+ ADD_JSON_VALUE(int, "NumCores", this_machine->cores);
+ ADD_JSON_VALUE(int, "NumNodes", this_machine->nodes);
+ ADD_JSON_VALUE(int, "NumThreads", this_machine->threads);
+ ADD_JSON_VALUE(string, "MachineId", this_machine->mid);
+ ADD_JSON_VALUE(int, "PointerBits", this_machine->ptr_bits);
+ ADD_JSON_VALUE(boolean, "DataFromSuperUser", this_machine->is_su_data);
+ ADD_JSON_VALUE(int, "PhysicalMemoryInMiB",
+ this_machine->memory_phys_MiB);
+ ADD_JSON_VALUE(string, "MemoryTypes", this_machine->ram_types);
+ ADD_JSON_VALUE(int, "MachineDataVersion",
+ this_machine->machine_data_version);
+ ADD_JSON_VALUE(string, "MachineType", this_machine->machine_type);
+
+ ADD_JSON_VALUE(boolean, "Legacy", FALSE);
+ ADD_JSON_VALUE(string, "ExtraInfo", bench_results[i].extra);
+ ADD_JSON_VALUE(string, "UserNote", bench_results[i].user_note);
+ ADD_JSON_VALUE(double, "BenchmarkResult", bench_results[i].result);
+ ADD_JSON_VALUE(double, "ElapsedTime", bench_results[i].elapsed_time);
+ ADD_JSON_VALUE(int, "UsedThreads", bench_results[i].threads_used);
+ ADD_JSON_VALUE(int, "BenchmarkVersion", bench_results[i].revision);
+
+#undef ADD_JSON_VALUE
+
+ json_builder_end_object(builder);
}
+ json_builder_end_object(builder);
+
+ generator = json_generator_new();
+ json_generator_set_root(generator, json_builder_get_root(builder));
+ json_generator_set_pretty(generator, TRUE);
- g_free(machine);
- g_free(machineclock);
- g_free(machineram);
+ out = json_generator_to_data(generator, len);
- sending_benchmark_results = FALSE;
+ g_object_unref(generator);
+ g_object_unref(builder);
+ bench_machine_free(this_machine);
- return result;
+ return out;
}
static gchar *run_benchmark(gchar *name)
@@ -646,42 +873,44 @@ static gchar *run_benchmark(gchar *name)
DEBUG("name = %s", name);
for (i = 0; entries[i].name; i++) {
- if (g_str_equal(entries[i].name, name)) {
- void (*scan_callback)(gboolean rescan);
-
- if ((scan_callback = entries[i].scan_callback)) {
- scan_callback(FALSE);
-
-#define CHK_RESULT_FORMAT(F) (params.result_format && strcmp(params.result_format, F) == 0)
-
- if (params.run_benchmark) {
- if (CHK_RESULT_FORMAT("conf") ) {
- bench_result *b = bench_result_this_machine(name, bench_results[i]);
- char *temp = bench_result_benchmarkconf_line(b);
- bench_result_free(b);
- return temp;
- } else if (CHK_RESULT_FORMAT("shell") ) {
- bench_result *b = bench_result_this_machine(name, bench_results[i]);
- char *temp = bench_result_more_info_complete(b);
- bench_result_free(b);
- return temp;
+ if (g_str_equal(entries[i].name, name)) {
+ void (*scan_callback)(gboolean rescan);
+
+ if ((scan_callback = entries[i].scan_callback)) {
+ scan_callback(FALSE);
+
+#define CHK_RESULT_FORMAT(F) \
+ (params.result_format && strcmp(params.result_format, F) == 0)
+
+ if (params.run_benchmark) {
+ /* attach the user note */
+ if (params.bench_user_note)
+ strncpy(bench_results[i].user_note,
+ params.bench_user_note, 255);
+
+ if (CHK_RESULT_FORMAT("shell")) {
+ bench_result *b =
+ bench_result_this_machine(name, bench_results[i]);
+ char *temp = bench_result_more_info_complete(b);
+ bench_result_free(b);
+ return temp;
+ }
+ /* defaults to "short" which is below */
+ }
+
+ return bench_value_to_str(bench_results[i]);
}
- /* defaults to "short" which is below*/
- }
-
- return bench_value_to_str(bench_results[i]);
}
- }
}
return NULL;
}
-ShellModuleMethod *hi_exported_methods(void)
+const ShellModuleMethod *hi_exported_methods(void)
{
- static ShellModuleMethod m[] = {
+ static const ShellModuleMethod m[] = {
{"runBenchmark", run_benchmark},
- {NULL}
+ {NULL},
};
return m;
@@ -690,31 +919,28 @@ ShellModuleMethod *hi_exported_methods(void)
void hi_module_init(void)
{
static SyncEntry se[] = {
- {
- .fancy_name = N_("Send benchmark results"),
- .name = "SendBenchmarkResults",
- .save_to = NULL,
- .get_data = get_benchmark_results},
- {
- .fancy_name = N_("Receive benchmark results"),
- .name = "RecvBenchmarkResults",
- .save_to = "benchmark.conf",
- .get_data = NULL}
+ {
+ .name = N_("Send benchmark results"),
+ .file_name = "benchmark.json",
+ .generate_contents_for_upload = get_benchmark_results,
+ },
+ {
+ .name = N_("Receive benchmark results"),
+ .file_name = "benchmark.json",
+ },
};
sync_manager_add_entry(&se[0]);
sync_manager_add_entry(&se[1]);
- bench_value er = EMPTY_BENCH_VALUE;
- int i;
- for (i = 0; i < G_N_ELEMENTS(entries) - 1; i++) {
- bench_results[i] = er;
- }
+ guint i;
+ for (i = 0; i < G_N_ELEMENTS(entries) - 1 /* account for NULL */; i++)
+ bench_results[i] = (bench_value)EMPTY_BENCH_VALUE;
}
gchar **hi_module_get_dependencies(void)
{
- static gchar *deps[] = { "devices.so", NULL };
+ static gchar *deps[] = {"devices.so", NULL};
return deps;
}