{ "$schema": "http://json-schema.org/draft-07/schema#", "title": "BenchmarkSummary", "description": "The `BenchmarkSummary` containing all the information of a single benchmark run\n\nThis includes produced files, recorded callgrind events, performance regressions ...", "type": "object", "required": [ "benchmark_exe", "benchmark_file", "function_name", "kind", "module_path", "package_dir", "project_root", "tool_summaries", "version" ], "properties": { "benchmark_exe": { "description": "The path to the binary which is executed by valgrind. In case of a library benchmark this is the compiled benchmark file. In case of a binary benchmark this is the path to the command.", "type": "string" }, "benchmark_file": { "description": "The path to the benchmark file", "type": "string" }, "callgrind_summary": { "description": "The summary of the callgrind run", "anyOf": [ { "$ref": "#/definitions/CallgrindSummary" }, { "type": "null" } ] }, "details": { "description": "More details describing this benchmark run", "type": ["string", "null"] }, "function_name": { "description": "The name of the function under test", "type": "string" }, "id": { "description": "The user provided id of this benchmark", "type": ["string", "null"] }, "kind": { "description": "Whether this summary describes a library or binary benchmark", "allOf": [ { "$ref": "#/definitions/BenchmarkKind" } ] }, "module_path": { "description": "The rust path in the form `bench_file::group::bench`", "type": "string" }, "package_dir": { "description": "The directory of the package", "type": "string" }, "project_root": { "description": "The project's root directory", "type": "string" }, "summary_output": { "description": "The destination and kind of the summary file", "anyOf": [ { "$ref": "#/definitions/SummaryOutput" }, { "type": "null" } ] }, "tool_summaries": { "description": "The summary of other valgrind tool runs", "type": "array", "items": { "$ref": "#/definitions/ToolSummary" } }, "version": { "description": "The version of this format. Only backwards incompatible changes cause an increase of the version", "type": "string" } }, "definitions": { "Baseline": { "description": "A `Baseline` depending on the [`BaselineKind`] which points to the corresponding path\n\nThis baseline is used for comparisons with the new output of valgrind tools.", "type": "object", "required": ["kind", "path"], "properties": { "kind": { "description": "The kind of the `Baseline`", "allOf": [ { "$ref": "#/definitions/BaselineKind" } ] }, "path": { "description": "The path to the file which is used to compare against the new output", "type": "string" } } }, "BaselineKind": { "description": "The `BaselineKind` describing the baseline", "oneOf": [ { "description": "Compare new against `*.old` output files", "type": "string", "enum": ["Old"] }, { "description": "Compare new against a named baseline", "type": "object", "required": ["Name"], "properties": { "Name": { "$ref": "#/definitions/BaselineName" } }, "additionalProperties": false } ] }, "BaselineName": { "type": "string" }, "BenchmarkKind": { "description": "The `BenchmarkKind`, differentiating between library and binary benchmarks", "oneOf": [ { "description": "A library benchmark", "type": "string", "enum": ["LibraryBenchmark"] }, { "description": "A binary benchmark", "type": "string", "enum": ["BinaryBenchmark"] } ] }, "CallgrindRegression": { "description": "The `CallgrindRegression` describing a single event based performance regression", "type": "object", "required": ["diff_pct", "event_kind", "limit", "new", "old"], "properties": { "diff_pct": { "description": "The difference between new and old in percent. Serialized as string to preserve infinity values and avoid null in json.", "type": "string" }, "event_kind": { "description": "The [`EventKind`] which is affected by a performance regression", "allOf": [ { "$ref": "#/definitions/EventKind" } ] }, "limit": { "description": "The value of the limit which was exceeded to cause a performance regression. Serialized as string to preserve infinity values and avoid null in json.", "type": "string" }, "new": { "description": "The value of the new benchmark run", "type": "integer", "format": "uint64", "minimum": 0.0 }, "old": { "description": "The value of the old benchmark run", "type": "integer", "format": "uint64", "minimum": 0.0 } } }, "CallgrindRun": { "description": "The `CallgrindRun` contains all `CallgrindRunSegments` and their total costs in a `CallgrindTotal`.", "type": "object", "required": ["segments", "total"], "properties": { "segments": { "description": "All `CallgrindRunSummary`s", "type": "array", "items": { "$ref": "#/definitions/CallgrindRunSegment" } }, "total": { "description": "The total costs of all `CallgrindRunSummary`s in this `CallgrindRunSummaries`", "allOf": [ { "$ref": "#/definitions/CallgrindTotal" } ] } } }, "CallgrindRunSegment": { "description": "The `CallgrindRunSegment` containing the metric differences, performance regressions of a callgrind run segment.\n\nA segment can be a part (caused by options like `--dump-every-bb=xxx`), a thread (caused by `--separate-threads`) or a pid (possibly caused by `--trace-children`). A segment is a summary over a single file which contains the costs of that part, thread and/or pid.", "type": "object", "required": ["command", "events", "regressions"], "properties": { "baseline": { "description": "If present, the `Baseline` used to compare the new with the old output", "anyOf": [ { "$ref": "#/definitions/Baseline" }, { "type": "null" } ] }, "command": { "description": "The executed command extracted from Valgrind output", "type": "string" }, "events": { "description": "All recorded metrics for the `EventKinds`", "allOf": [ { "$ref": "#/definitions/MetricsSummary_for_EventKind" } ] }, "regressions": { "description": "All detected performance regressions per callgrind run", "type": "array", "items": { "$ref": "#/definitions/CallgrindRegression" } } } }, "CallgrindSummary": { "description": "The `CallgrindSummary` contains the callgrind run, flamegraph paths and other paths to the segments of the callgrind run.", "type": "object", "required": ["callgrind_run", "flamegraphs", "log_paths", "out_paths"], "properties": { "callgrind_run": { "description": "The summary of all callgrind segments is a `CallgrindRun`", "allOf": [ { "$ref": "#/definitions/CallgrindRun" } ] }, "flamegraphs": { "description": "The summaries of possibly created flamegraphs", "type": "array", "items": { "$ref": "#/definitions/FlamegraphSummary" } }, "log_paths": { "description": "The paths to the `*.log` files", "type": "array", "items": { "type": "string" } }, "out_paths": { "description": "The paths to the `*.out` files", "type": "array", "items": { "type": "string" } } } }, "CallgrindTotal": { "description": "The total callgrind costs over the `CallgrindRunSegments` and all detected regressions for the total", "type": "object", "required": ["regressions", "summary"], "properties": { "regressions": { "description": "All detected regressions for the total metrics", "type": "array", "items": { "$ref": "#/definitions/CallgrindRegression" } }, "summary": { "description": "The total over the segment metrics", "allOf": [ { "$ref": "#/definitions/MetricsSummary_for_EventKind" } ] } } }, "Diffs": { "description": "The differences between two `Metrics` as percentage and factor", "type": "object", "required": ["diff_pct", "factor"], "properties": { "diff_pct": { "description": "The percentage of the difference between two `Metrics` serialized as string to preserve infinity values and avoid `null` in json", "type": "string" }, "factor": { "description": "The factor of the difference between two `Metrics` serialized as string to preserve infinity values and void `null` in json", "type": "string" } } }, "EitherOrBoth_for_SegmentDetails": { "description": "Either left or right or both can be present\n\nMost of the time, this enum is used to store (new, old) output, metrics, etc. Per convention left is `new` and right is `old`.", "oneOf": [ { "description": "The left or `new` value", "type": "object", "required": ["Left"], "properties": { "Left": { "$ref": "#/definitions/SegmentDetails" } }, "additionalProperties": false }, { "description": "The right or `old` value", "type": "object", "required": ["Right"], "properties": { "Right": { "$ref": "#/definitions/SegmentDetails" } }, "additionalProperties": false }, { "description": "Both values (`new` and `old`) are present", "type": "object", "required": ["Both"], "properties": { "Both": { "type": "array", "items": [ { "$ref": "#/definitions/SegmentDetails" }, { "$ref": "#/definitions/SegmentDetails" } ], "maxItems": 2, "minItems": 2 } }, "additionalProperties": false } ] }, "EitherOrBoth_for_uint64": { "description": "Either left or right or both can be present\n\nMost of the time, this enum is used to store (new, old) output, metrics, etc. Per convention left is `new` and right is `old`.", "oneOf": [ { "description": "The left or `new` value", "type": "object", "required": ["Left"], "properties": { "Left": { "type": "integer", "format": "uint64", "minimum": 0.0 } }, "additionalProperties": false }, { "description": "The right or `old` value", "type": "object", "required": ["Right"], "properties": { "Right": { "type": "integer", "format": "uint64", "minimum": 0.0 } }, "additionalProperties": false }, { "description": "Both values (`new` and `old`) are present", "type": "object", "required": ["Both"], "properties": { "Both": { "type": "array", "items": [ { "type": "integer", "format": "uint64", "minimum": 0.0 }, { "type": "integer", "format": "uint64", "minimum": 0.0 } ], "maxItems": 2, "minItems": 2 } }, "additionalProperties": false } ] }, "EventKind": { "description": "All `EventKind`s callgrind produces and additionally some derived events\n\nDepending on the options passed to Callgrind, these are the events that Callgrind can produce. See the [Callgrind documentation](https://valgrind.org/docs/manual/cl-manual.html#cl-manual.options) for details.", "oneOf": [ { "description": "The default event. I cache reads (which equals the number of instructions executed)", "type": "string", "enum": ["Ir"] }, { "description": "The number of system calls done (--collect-systime=yes)", "type": "string", "enum": ["SysCount"] }, { "description": "The elapsed time spent in system calls (--collect-systime=yes)", "type": "string", "enum": ["SysTime"] }, { "description": "The cpu time spent during system calls (--collect-systime=nsec)", "type": "string", "enum": ["SysCpuTime"] }, { "description": "The number of global bus events (--collect-bus=yes)", "type": "string", "enum": ["Ge"] }, { "description": "D Cache reads (which equals the number of memory reads) (--cache-sim=yes)", "type": "string", "enum": ["Dr"] }, { "description": "D Cache writes (which equals the number of memory writes) (--cache-sim=yes)", "type": "string", "enum": ["Dw"] }, { "description": "I1 cache read misses (--cache-sim=yes)", "type": "string", "enum": ["I1mr"] }, { "description": "D1 cache read misses (--cache-sim=yes)", "type": "string", "enum": ["D1mr"] }, { "description": "D1 cache write misses (--cache-sim=yes)", "type": "string", "enum": ["D1mw"] }, { "description": "LL cache instruction read misses (--cache-sim=yes)", "type": "string", "enum": ["ILmr"] }, { "description": "LL cache data read misses (--cache-sim=yes)", "type": "string", "enum": ["DLmr"] }, { "description": "LL cache data write misses (--cache-sim=yes)", "type": "string", "enum": ["DLmw"] }, { "description": "Derived event showing the L1 hits (--cache-sim=yes)", "type": "string", "enum": ["L1hits"] }, { "description": "Derived event showing the LL hits (--cache-sim=yes)", "type": "string", "enum": ["LLhits"] }, { "description": "Derived event showing the RAM hits (--cache-sim=yes)", "type": "string", "enum": ["RamHits"] }, { "description": "Derived event showing the total amount of cache reads and writes (--cache-sim=yes)", "type": "string", "enum": ["TotalRW"] }, { "description": "Derived event showing estimated CPU cycles (--cache-sim=yes)", "type": "string", "enum": ["EstimatedCycles"] }, { "description": "Conditional branches executed (--branch-sim=yes)", "type": "string", "enum": ["Bc"] }, { "description": "Conditional branches mispredicted (--branch-sim=yes)", "type": "string", "enum": ["Bcm"] }, { "description": "Indirect branches executed (--branch-sim=yes)", "type": "string", "enum": ["Bi"] }, { "description": "Indirect branches mispredicted (--branch-sim=yes)", "type": "string", "enum": ["Bim"] }, { "description": "Dirty miss because of instruction read (--simulate-wb=yes)", "type": "string", "enum": ["ILdmr"] }, { "description": "Dirty miss because of data read (--simulate-wb=yes)", "type": "string", "enum": ["DLdmr"] }, { "description": "Dirty miss because of data write (--simulate-wb=yes)", "type": "string", "enum": ["DLdmw"] }, { "description": "Counter showing bad temporal locality for L1 caches (--cachuse=yes)", "type": "string", "enum": ["AcCost1"] }, { "description": "Counter showing bad temporal locality for LL caches (--cachuse=yes)", "type": "string", "enum": ["AcCost2"] }, { "description": "Counter showing bad spatial locality for L1 caches (--cachuse=yes)", "type": "string", "enum": ["SpLoss1"] }, { "description": "Counter showing bad spatial locality for LL caches (--cachuse=yes)", "type": "string", "enum": ["SpLoss2"] } ] }, "FlamegraphSummary": { "description": "The callgrind `FlamegraphSummary` records all created paths for an [`EventKind`] specific flamegraph\n\nEither the `regular_path`, `old_path` or the `diff_path` are present. Never can all of them be absent.", "type": "object", "required": ["event_kind"], "properties": { "base_path": { "description": "If present, the path to the file of the old regular (non-differential) flamegraph", "type": ["string", "null"] }, "diff_path": { "description": "If present, the path to the file of the differential flamegraph", "type": ["string", "null"] }, "event_kind": { "description": "The `EventKind` of the flamegraph", "allOf": [ { "$ref": "#/definitions/EventKind" } ] }, "regular_path": { "description": "If present, the path to the file of the regular (non-differential) flamegraph", "type": ["string", "null"] } } }, "MetricsDiff": { "description": "The `MetricsDiff` describes the difference between a `new` and `old` metric as percentage and factor.\n\nOnly if both metrics are present there is also a `Diffs` present. Otherwise, it just stores the `new` or `old` metric.", "type": "object", "required": ["metrics"], "properties": { "diffs": { "description": "If both metrics are present there is also a `Diffs` present", "anyOf": [ { "$ref": "#/definitions/Diffs" }, { "type": "null" } ] }, "metrics": { "description": "Either the `new`, `old` or both metrics", "allOf": [ { "$ref": "#/definitions/EitherOrBoth_for_uint64" } ] } } }, "MetricsSummary_for_DhatMetricKind": { "description": "The `MetricsSummary` contains all differences between two tool run segments", "type": "object", "additionalProperties": { "$ref": "#/definitions/MetricsDiff" } }, "MetricsSummary_for_ErrorMetricKind": { "description": "The `MetricsSummary` contains all differences between two tool run segments", "type": "object", "additionalProperties": { "$ref": "#/definitions/MetricsDiff" } }, "MetricsSummary_for_EventKind": { "description": "The `MetricsSummary` contains all differences between two tool run segments", "type": "object", "additionalProperties": { "$ref": "#/definitions/MetricsDiff" } }, "SegmentDetails": { "description": "Some additional and necessary information about the tool run segment", "type": "object", "required": ["command", "path", "pid"], "properties": { "command": { "description": "The executed command extracted from Valgrind output", "type": "string" }, "details": { "description": "More details for example from the logging output of the tool run", "type": ["string", "null"] }, "parent_pid": { "description": "The parent pid of this process", "type": ["integer", "null"], "format": "int32" }, "part": { "description": "The part of this tool run (only callgrind)", "type": ["integer", "null"], "format": "uint64", "minimum": 0.0 }, "path": { "description": "The path to the file from the tool run", "type": "string" }, "pid": { "description": "The pid of this process", "type": "integer", "format": "int32" }, "thread": { "description": "The thread of this tool run (only callgrind)", "type": ["integer", "null"], "format": "uint", "minimum": 0.0 } } }, "SummaryFormat": { "description": "The format (json, ...) in which the summary file should be saved or printed", "oneOf": [ { "description": "The format in a space optimal json representation without newlines", "type": "string", "enum": ["Json"] }, { "description": "The format in pretty printed json", "type": "string", "enum": ["PrettyJson"] } ] }, "SummaryOutput": { "description": "Manage the summary output file with this `SummaryOutput`", "type": "object", "required": ["format", "path"], "properties": { "format": { "description": "The [`SummaryFormat`]", "allOf": [ { "$ref": "#/definitions/SummaryFormat" } ] }, "path": { "description": "The path to the destination file of this summary", "type": "string" } } }, "ToolMetricSummary": { "description": "The `ToolMetricSummary` contains the `MetricsSummary` distinguished by tool and metric kinds", "oneOf": [ { "description": "If there are no metrics extracted (currently massif, bbv)", "type": "string", "enum": ["None"] }, { "description": "The error summary of tools which reports errors (memcheck, helgrind, drd)", "type": "object", "required": ["ErrorSummary"], "properties": { "ErrorSummary": { "$ref": "#/definitions/MetricsSummary_for_ErrorMetricKind" } }, "additionalProperties": false }, { "description": "The dhat summary", "type": "object", "required": ["DhatSummary"], "properties": { "DhatSummary": { "$ref": "#/definitions/MetricsSummary_for_DhatMetricKind" } }, "additionalProperties": false }, { "description": "The callgrind summary", "type": "object", "required": ["CallgrindSummary"], "properties": { "CallgrindSummary": { "$ref": "#/definitions/MetricsSummary_for_EventKind" } }, "additionalProperties": false } ] }, "ToolRun": { "description": "The `ToolRun` contains all information about a single tool run with possibly multiple segments\n\nThe total is always present and summarizes all tool run segments. In the special case of a single tool run segment, the total equals the metrics of this segment.", "type": "object", "required": ["segments", "total"], "properties": { "segments": { "description": "All `ToolRunSegment`s", "type": "array", "items": { "$ref": "#/definitions/ToolRunSegment" } }, "total": { "description": "The total over the `ToolRunSegment`s", "allOf": [ { "$ref": "#/definitions/ToolMetricSummary" } ] } } }, "ToolRunSegment": { "description": "A single segment of a tool run and if present the comparison with the \"old\" segment\n\nA tool run can produce multiple segments, for example for each process and subprocess with (--trace-children).", "type": "object", "required": ["details", "metrics_summary"], "properties": { "details": { "description": "The details (like command, thread number etc.) about the segment(s)", "allOf": [ { "$ref": "#/definitions/EitherOrBoth_for_SegmentDetails" } ] }, "metrics_summary": { "description": "The `ToolMetricSummary`", "allOf": [ { "$ref": "#/definitions/ToolMetricSummary" } ] } } }, "ToolSummary": { "description": "The `ToolSummary` containing all information about a valgrind tool run", "type": "object", "required": ["log_paths", "out_paths", "summaries", "tool"], "properties": { "log_paths": { "description": "The paths to the `*.log` files. All tools produce at least one log file", "type": "array", "items": { "type": "string" } }, "out_paths": { "description": "The paths to the `*.out` files. Not all tools produce an output in addition to the log files", "type": "array", "items": { "type": "string" } }, "summaries": { "description": "The metrics and details about the tool run", "allOf": [ { "$ref": "#/definitions/ToolRun" } ] }, "tool": { "description": "The Valgrind tool like `DHAT`, `Memcheck` etc.", "allOf": [ { "$ref": "#/definitions/ValgrindTool" } ] } } }, "ValgrindTool": { "description": "All currently available valgrind tools", "type": "string", "enum": [ "Callgrind", "Memcheck", "Helgrind", "DRD", "Massif", "DHAT", "BBV" ] } } }