aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeandro Pereira <leandro@hardinfo.org>2020-05-09 12:25:01 -0700
committerLeandro Pereira <leandro@hardinfo.org>2020-05-09 13:14:31 -0700
commit3038c80308b93394f7a9178d9b7adc7a5e0c28d6 (patch)
treed5bcb200a4b90be2fd9e19edeb223b374423574d
parenta14313aec10633f6c3a16eb2e80a73e406ca5a01 (diff)
Load benchmark results from JSON files
-rw-r--r--modules/benchmark.c195
-rw-r--r--modules/benchmark/bench_results.c100
-rwxr-xr-xtools/benchmark-conf-to-json.py2
3 files changed, 242 insertions, 55 deletions
diff --git a/modules/benchmark.c b/modules/benchmark.c
index 27803e11..ccdef342 100644
--- a/modules/benchmark.c
+++ b/modules/benchmark.c
@@ -345,13 +345,17 @@ 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;
- this_marker =
- format_with_ansi_color(_("This Machine"), "0;30;43", params.fmt_opts);
+ if (select) {
+ this_marker = format_with_ansi_color(_("This Machine"), "0;30;43",
+ params.fmt_opts);
+ } else {
+ this_marker = "";
+ }
rkey = g_strdup_printf("%s__%d", b->machine->mid, ri++);
- lbl = g_strdup_printf("%s%s%s%s", select ? this_marker : "",
- select ? " " : "", b->machine->cpu_name,
+ lbl = g_strdup_printf("%s%s%s%s", this_marker, select ? " " : "",
+ b->machine->cpu_name,
b->legacy ? problem_marker() : "");
elbl = key_label_escape(lbl);
@@ -364,9 +368,9 @@ static void br_mi_add(char **results_list, bench_result *b, gboolean select)
g_free(lbl);
g_free(elbl);
g_free(rkey);
- g_free(this_marker);
+ if (*this_marker)
+ g_free(this_marker);
}
-
gint bench_result_sort(gconstpointer a, gconstpointer b)
{
bench_result *A = (bench_result *)a, *B = (bench_result *)b;
@@ -377,28 +381,18 @@ gint bench_result_sort(gconstpointer a, gconstpointer b)
return 0;
}
-static gchar *benchmark_include_results_conf(const gchar *path,
- bench_value r,
- const gchar *benchmark,
- ShellOrderType order_type)
+static GSList *benchmark_include_results_conf(const gchar *path,
+ bench_value r,
+ const gchar *benchmark)
{
- bench_result *b = NULL;
GKeyFile *conf;
gchar **machines;
gchar *results = g_strdup("");
- int i, len, loc, win_min, win_max, win_size = params.max_bench_results;
-
- GSList *result_list = NULL, *li = NULL;
-
- moreinfo_del_with_prefix("BENCH");
+ GSList *result_list = NULL;
+ gint i;
- /* this result */
- if (r.result > 0.0) {
- b = bench_result_this_machine(benchmark, r);
- result_list = g_slist_append(result_list, b);
- }
+ DEBUG("Loading benchmark results from conf file %s", path);
- /* load saved results */
conf = g_key_file_new();
g_key_file_load_from_file(conf, path, 0, NULL);
@@ -420,6 +414,124 @@ static gchar *benchmark_include_results_conf(const gchar *path,
g_strfreev(machines);
g_key_file_free(conf);
+ return result_list;
+}
+
+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)
+{
+ struct append_machine_result_json_data *data = user_data;
+ GSList **result_list = 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 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;
+
+ DEBUG("Loading benchmark results from JSON file %s", path);
+
+ parser = json_parser_new();
+ if (!json_parser_load_from_file(parser, path, NULL))
+ goto out;
+
+ root = json_parser_get_root(parser);
+ if (json_node_get_node_type(root) != JSON_NODE_OBJECT) {
+ json_node_unref(root);
+ goto out;
+ }
+
+ JsonObject *results = json_node_get_object(root);
+ if (results) {
+ JsonArray *machines = json_object_get_array_member(results, benchmark);
+
+ 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);
+ }
+ }
+
+out:
+ g_object_unref(parser);
+
+ return result_list;
+}
+
+static gchar *find_benchmark_conf(void)
+{
+ const gchar *files[] = {"benchmark.json", "benchmark.conf", NULL};
+ const gchar *config_dir = g_get_user_config_dir();
+ gint i;
+
+ for (i = 0; files[i]; i++) {
+ gchar *path;
+
+ path = g_build_filename(config_dir, "hardinfo", files[i], NULL);
+ if (g_file_test(path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free(path);
+
+ path = g_build_filename(params.path_data, files[i], NULL);
+ if (g_file_test(path, G_FILE_TEST_EXISTS))
+ return path;
+ g_free(path);
+ }
+
+ return NULL;
+}
+
+static gchar *benchmark_include_results_internal(bench_value this_machine_value,
+ const gchar *benchmark,
+ ShellOrderType order_type)
+{
+ GSList *result_list;
+ GSList *li;
+ int i, len, loc, win_min, win_max, win_size = params.max_bench_results;
+ bench_result *this_machine = NULL;
+ gchar *results = g_strdup("");
+ gchar *output;
+ gchar *path;
+
+ moreinfo_del_with_prefix("BENCH");
+
+ path = find_benchmark_conf();
+
+ if (path) {
+ if (g_str_has_suffix(path, ".json"))
+ result_list = benchmark_include_results_json(
+ path, this_machine_value, benchmark);
+ else if (g_str_has_suffix(path, ".conf"))
+ result_list = benchmark_include_results_conf(
+ path, this_machine_value, benchmark);
+ else
+ g_assert_not_reached();
+ }
+
+ /* this result */
+ if (this_machine_value.result > 0.0) {
+ this_machine = bench_result_this_machine(benchmark, this_machine_value);
+ result_list = g_slist_append(result_list, this_machine);
+ }
+
/* sort */
result_list = g_slist_sort(result_list, bench_result_sort);
if (order_type == SHELL_ORDER_DESCENDING)
@@ -431,7 +543,7 @@ static gchar *benchmark_include_results_conf(const gchar *path,
win_size = 1;
if (win_size < 0)
win_size = len;
- loc = g_slist_index(result_list, b); /* -1 if not found */
+ loc = g_slist_index(result_list, this_machine); /* -1 if not found */
if (loc >= 0) {
win_min = loc - win_size / 2;
win_max = win_min + win_size;
@@ -451,41 +563,16 @@ static gchar *benchmark_include_results_conf(const gchar *path,
win_size, win_min, win_max - 1);
/* prepare for shell */
- i = 0;
- li = result_list;
- while (li) {
+ for (i = 0, li = result_list; li; li = g_slist_next(li), i++) {
bench_result *tr = (bench_result *)li->data;
+
if (i >= win_min && i < win_max)
- br_mi_add(&results, tr, (tr == b) ? 1 : 0);
+ br_mi_add(&results, tr, tr == this_machine);
+
bench_result_free(tr); /* no longer needed */
- i++;
- li = g_slist_next(li);
}
-
g_slist_free(result_list);
- return results;
-}
-
-static gchar *benchmark_include_results_internal(bench_value r,
- const gchar *benchmark,
- ShellOrderType order_type)
-{
- gchar *bench_results;
- gchar *output;
- gchar *path;
-
- path = g_build_filename(g_get_user_config_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);
- }
-
- bench_results =
- benchmark_include_results_conf(path, r, benchmark, order_type);
-
output = g_strdup_printf("[$ShellParam$]\n"
"Zebra=1\n"
"OrderType=%d\n"
@@ -496,10 +583,10 @@ static gchar *benchmark_include_results_internal(bench_value r,
"ShowColumnHeaders=true\n"
"[%s]\n%s",
order_type, _("CPU Config"), _("Results"),
- _("CPU"), benchmark, bench_results);
+ _("CPU"), benchmark, results);
g_free(path);
- g_free(bench_results);
+ g_free(results);
return output;
}
diff --git a/modules/benchmark/bench_results.c b/modules/benchmark/bench_results.c
index e305ee28..9a774433 100644
--- a/modules/benchmark/bench_results.c
+++ b/modules/benchmark/bench_results.c
@@ -1,6 +1,6 @@
/*
* HardInfo - Displays System Information
- * Copyright (C) 2003-2017 Leandro A. F. Pereira <leandro@hardinfo.org>
+ * Copyright (C) 2020 Leandro A. F. Pereira <leandro@hardinfo.org>
* This file:
* Copyright (C) 2017 Burt P. <pburt0@gmail.com>
*
@@ -18,6 +18,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <json-glib/json-glib.h>
#include <inttypes.h>
/* in dmi_memory.c */
@@ -279,6 +280,103 @@ static gboolean cpu_name_needs_cleanup(const char *cpu_name)
strstr(cpu_name, "VIA") || strstr(cpu_name, "Cyrix");
}
+static void filter_invalid_chars(gchar *str)
+{
+ gchar *p;
+
+ for (p = str; *p; p++) {
+ if (*p = '\n' || *p == ';' || *p == '|')
+ *p = '_';
+ }
+}
+
+static gboolean json_get_boolean(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return FALSE;
+ return json_object_get_boolean_member(obj, key);
+}
+
+static double json_get_double(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return 0;
+ return json_object_get_double_member(obj, key);
+}
+
+static int json_get_int(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return 0;
+ return json_object_get_int_member(obj, key);
+}
+
+static const gchar *json_get_string(JsonObject *obj, const gchar *key)
+{
+ if (!json_object_has_member(obj, key))
+ return "";
+ return json_object_get_string_member(obj, key);
+}
+
+static gchar *json_get_string_dup(JsonObject *obj, const gchar *key)
+{
+ return g_strdup(json_get_string(obj, key));
+}
+
+bench_result *bench_result_benchmarkjson(const gchar *bench_name, JsonNode *node)
+{
+ JsonObject *machine;
+ bench_result *b;
+ const gchar *cp;
+ gchar *p;
+
+ if (json_node_get_node_type(node) != JSON_NODE_OBJECT)
+ return NULL;
+
+ machine = json_node_get_object(node);
+
+ b = g_new0(bench_result, 1);
+ b->name = g_strdup(bench_name);
+ b->legacy = json_get_boolean(machine, "Legacy");
+
+ b->bvalue = (bench_value){
+ .result = json_get_double(machine, "BenchmarkResult"),
+ .elapsed_time = json_get_double(machine, "ElapsedTime"),
+ .threads_used = json_get_int(machine, "UsedThreads"),
+ .revision = json_get_int(machine, "BenchmarkRevision"),
+ };
+
+ cp = json_get_string(machine, "ExtraInfo");
+ snprintf(b->bvalue.extra, sizeof(b->bvalue.extra), "%s", cp ? cp : "");
+ filter_invalid_chars(b->bvalue.extra);
+
+ cp = json_get_string(machine, "UserNote");
+ snprintf(b->bvalue.user_note, sizeof(b->bvalue.user_note), "%s", cp ? cp : "");
+ filter_invalid_chars(b->bvalue.user_note);
+
+ b->machine = bench_machine_new();
+ *b->machine = (bench_machine) {
+ .board = json_get_string_dup(machine, "Board"),
+ .memory_kiB = json_get_int(machine, "MemoryInKiB"),
+ .cpu_name = json_get_string_dup(machine, "CpuName"),
+ .cpu_desc = json_get_string_dup(machine, "CpuDesc"),
+ .cpu_config = json_get_string_dup(machine, "CpuConfig"),
+ .ogl_renderer = json_get_string_dup(machine, "OpenGlRenderer"),
+ .gpu_desc = json_get_string_dup(machine, "GpuDesc"),
+ .processors = json_get_int(machine, "NumCpus"),
+ .cores = json_get_int(machine, "NumCores"),
+ .threads = json_get_int(machine, "NumThreads"),
+ .mid = json_get_string_dup(machine, "MachineId"),
+ .ptr_bits = json_get_int(machine, "PointerBits"),
+ .is_su_data = json_get_boolean(machine, "DataFromSuperUser"),
+ .memory_phys_MiB = json_get_int(machine, "PhysicalMemoryInMiB"),
+ .ram_types = json_get_string_dup(machine, "MemoryTypes"),
+ .machine_data_version = json_get_int(machine, "MachineDataVersion"),
+ };
+
+ return b;
+}
+
bench_result *
bench_result_benchmarkconf(const char *section, const char *key, char **values)
{
diff --git a/tools/benchmark-conf-to-json.py b/tools/benchmark-conf-to-json.py
index ce61ee4a..033a0f94 100755
--- a/tools/benchmark-conf-to-json.py
+++ b/tools/benchmark-conf-to-json.py
@@ -196,6 +196,7 @@ if __name__ == '__main__':
'NumCpus': int(values[7]),
'NumCores': int(values[8]),
'NumThreads': int(values[9]),
+ 'Legacy': False,
}
bench.update(parse_new_style_bench_value(values[0]))
if len(values) >= 11:
@@ -215,6 +216,7 @@ if __name__ == '__main__':
elif len(values) >= 2:
bench = {
'BenchmarkResult': float(values[0]),
+ 'Legacy': True,
}
cpu_info = parse_old_style_cpu_info(values[1].replace(",", "."), key, section)