Skip to content

Commit

Permalink
Add performance analysis tool (#167)
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Mior <[email protected]>
  • Loading branch information
michaelmior authored Nov 19, 2024
1 parent 8242eff commit 16b8531
Show file tree
Hide file tree
Showing 2 changed files with 229 additions and 0 deletions.
15 changes: 15 additions & 0 deletions contrib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,19 @@ if(BLAZE_COMPILER AND BLAZE_EVALUATOR)
PRIVATE sourcemeta::blaze::compiler)
target_link_libraries(sourcemeta_blaze_contrib_trace
PRIVATE sourcemeta::blaze::evaluator)

if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
add_executable(sourcemeta_blaze_contrib_perf perf.cc)
noa_add_default_options(PRIVATE sourcemeta_blaze_contrib_perf)
target_link_libraries(sourcemeta_blaze_contrib_perf
PRIVATE sourcemeta::jsontoolkit::json)
target_link_libraries(sourcemeta_blaze_contrib_perf
PRIVATE sourcemeta::jsontoolkit::jsonl)
target_link_libraries(sourcemeta_blaze_contrib_perf
PRIVATE sourcemeta::jsontoolkit::jsonschema)
target_link_libraries(sourcemeta_blaze_contrib_perf
PRIVATE sourcemeta::blaze::compiler)
target_link_libraries(sourcemeta_blaze_contrib_perf
PRIVATE sourcemeta::blaze::evaluator)
endif()
endif()
214 changes: 214 additions & 0 deletions contrib/perf.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#include <sourcemeta/jsontoolkit/json.h>
#include <sourcemeta/jsontoolkit/jsonl.h>
#include <sourcemeta/jsontoolkit/jsonschema.h>

#include <sourcemeta/blaze/compiler.h>
#include <sourcemeta/blaze/evaluator.h>

#include <linux/perf_event.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>

#include <algorithm> // std::sort, std::max
#include <cstdlib> // EXIT_SUCCESS, EXIT_FAILURE
#include <filesystem> // std::filesystem::path
#include <iostream> // std::cerr, std::cout
#include <map> // std::map
#include <utility> // std::pair
#include <vector> // std::vector

static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
int cpu, long group_fd, unsigned long flags) {
long fd = syscall(SYS_perf_event_open, hw_event, pid, cpu, group_fd, flags);
if (fd == -1) {
fprintf(stderr, "Error creating event");
exit(EXIT_FAILURE);
}

return fd;
}

struct record_t {
uint64_t value;
uint64_t id;
};

struct read_format {
uint64_t nr;
record_t values[6];
};

class PerfEvents {
private:
struct perf_event_attr pea;
unsigned long branch_predict_id;
long branch_predict_fd;
unsigned long branch_miss_id;
long branch_miss_fd;
unsigned long cache_access_id;
long cache_access_fd;
unsigned long cache_miss_id;
long cache_miss_fd;
unsigned long cycles_id;
long cycles_fd;
unsigned long instr_id;
long instr_fd;

void newHWEvent(struct perf_event_attr *newEvent, unsigned long type,
long *fd, long group_fd, unsigned long *id) {
memset(newEvent, 0, sizeof(struct perf_event_attr));
newEvent->type = PERF_TYPE_HARDWARE;
newEvent->size = sizeof(struct perf_event_attr);
newEvent->config = type;
newEvent->disabled = 1;
newEvent->exclude_kernel = 1;
newEvent->exclude_hv = 1;
newEvent->read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;
*fd = perf_event_open(newEvent, 0, -1, group_fd, 0);
ioctl(static_cast<int>(*fd), PERF_EVENT_IOC_ID, id);
}

public:
PerfEvents() {
newHWEvent(&pea, PERF_COUNT_HW_BRANCH_INSTRUCTIONS, &branch_predict_fd, -1,
&branch_predict_id);
newHWEvent(&pea, PERF_COUNT_HW_BRANCH_MISSES, &branch_miss_fd,
branch_predict_fd, &branch_miss_id);
newHWEvent(&pea, PERF_COUNT_HW_CACHE_REFERENCES, &cache_access_fd,
branch_predict_fd, &cache_access_id);
newHWEvent(&pea, PERF_COUNT_HW_CACHE_MISSES, &cache_miss_fd,
branch_predict_fd, &cache_miss_id);
newHWEvent(&pea, PERF_COUNT_HW_CPU_CYCLES, &cycles_fd, branch_predict_fd,
&cycles_id);
newHWEvent(&pea, PERF_COUNT_HW_INSTRUCTIONS, &instr_fd, branch_predict_fd,
&instr_id);
}

void start() {
ioctl(static_cast<int>(branch_predict_fd), PERF_EVENT_IOC_RESET,
PERF_IOC_FLAG_GROUP);
ioctl(static_cast<int>(branch_predict_fd), PERF_EVENT_IOC_ENABLE,
PERF_IOC_FLAG_GROUP);
}

void stop() {
ioctl(static_cast<int>(branch_predict_fd), PERF_EVENT_IOC_DISABLE,
PERF_IOC_FLAG_GROUP);
}

void print() {
char buf[4096];
struct read_format *rf = (struct read_format *)buf;
unsigned long branch_predicts = 0;
unsigned long branch_misses = 0;
unsigned long cache_accesses = 0;
unsigned long cache_misses = 0;
unsigned long cycles = 0;
unsigned long instructions = 0;

if (read(static_cast<int>(branch_predict_fd), buf, sizeof(buf)) <= 0) {
std::cerr << "Error reading performance counters\n";
return;
}
for (unsigned long i = 0; i < rf->nr; i++) {
if (rf->values[i].id == branch_predict_id) {
branch_predicts = rf->values[i].value;
} else if (rf->values[i].id == branch_miss_id) {
branch_misses = rf->values[i].value;
} else if (rf->values[i].id == cache_access_id) {
cache_accesses = rf->values[i].value;
} else if (rf->values[i].id == cache_miss_id) {
cache_misses = rf->values[i].value;
} else if (rf->values[i].id == cycles_id) {
cycles = rf->values[i].value;
} else if (rf->values[i].id == instr_id) {
instructions = rf->values[i].value;
}
}

std::cerr << " Cycles: " << cycles << "\n";
std::cerr << " Instructions: " << instructions << "\n";
std::cerr << " Cache misses: " << cache_misses << "/" << cache_accesses
<< " = "
<< (static_cast<double>(cache_misses) /
static_cast<double>(cache_accesses) * 100)
<< "%\n";
std::cerr << "Branch misses: " << branch_misses << "/" << branch_predicts
<< " = "
<< (static_cast<double>(branch_misses) /
static_cast<double>(branch_predicts) * 100)
<< "%\n";
}

~PerfEvents() {
close(static_cast<int>(branch_miss_fd));
close(static_cast<int>(cache_access_fd));
close(static_cast<int>(cache_miss_fd));
close(static_cast<int>(cycles_fd));
close(static_cast<int>(instr_fd));
close(static_cast<int>(branch_predict_fd));
}
};

bool validate_all(auto &context, const auto &instances,
const auto &schema_template) {
for (std::size_t num = 0; num < instances.size(); num++) {
context.prepare(instances[num]);
const auto result{sourcemeta::blaze::evaluate(schema_template, context)};
if (!result) {
std::cerr << "Error validating instance " << num << "\n";
return false;
}
}

return true;
}

auto main(int argc, char **argv) noexcept -> int {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <schema.json> <instances.jsonl>\n";
return EXIT_FAILURE;
}

const auto schema{sourcemeta::jsontoolkit::from_file(argv[1])};
const std::filesystem::path instance_path{argv[2]};
auto stream{sourcemeta::jsontoolkit::read_file(instance_path)};
std::vector<sourcemeta::jsontoolkit::JSON> instances;
for (const auto &instance : sourcemeta::jsontoolkit::JSONL{stream}) {
instances.push_back(instance);
}

const auto schema_template{sourcemeta::blaze::compile(
schema, sourcemeta::jsontoolkit::default_schema_walker,
sourcemeta::jsontoolkit::official_resolver,
sourcemeta::blaze::default_schema_compiler,
sourcemeta::blaze::Mode::FastValidation)};

sourcemeta::blaze::EvaluationContext context;
PerfEvents pe;

pe.start();
if (!validate_all(context, instances, schema_template)) {
return EXIT_FAILURE;
}
pe.stop();

std::cerr << "Cold\n==============================\n";
pe.print();
std::cerr << "\n";

for (int i = 0; i < 100; i++) {
validate_all(context, instances, schema_template);
}

pe.start();
validate_all(context, instances, schema_template);
pe.stop();

std::cerr << "Warm\n==============================\n";
pe.print();
std::cerr << "\n";

return EXIT_SUCCESS;
}

5 comments on commit 16b8531

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (macos/llvm)

Benchmark suite Current: 16b8531 Previous: 8242eff Ratio
Compiler_Draft6_AdaptiveCard 31512194750.00005 ns/iter 31291639375.000046 ns/iter 1.01
Compiler_2019_09_OMC_JSON_V2 6585593375.0000305 ns/iter 6571359332.999919 ns/iter 1.00
Evaluator_Draft4_Meta_1_No_Callback 479.1684987003558 ns/iter 484.9673193458705 ns/iter 0.99
Evaluator_Draft4_Required_Properties 530.2730714301177 ns/iter 539.0459458280483 ns/iter 0.98
Evaluator_Draft4_Many_Optional_Properties_Minimal_Match 94.86766141084178 ns/iter 94.8542922835574 ns/iter 1.00
Evaluator_Draft4_Few_Optional_Properties_Minimal_Match 63.695220379524685 ns/iter 61.880114629164865 ns/iter 1.03
Evaluator_Draft4_Items_Schema 1181.9031252032964 ns/iter 1180.3225593876352 ns/iter 1.00
Evaluator_Draft4_Nested_Object 19.798343068835166 ns/iter 19.261921241223035 ns/iter 1.03
Evaluator_Draft4_Properties_Triad_Optional 1141.3192397796433 ns/iter 1124.0000494062226 ns/iter 1.02
Evaluator_Draft4_Properties_Triad_Closed 818.2548161402127 ns/iter 814.875243466584 ns/iter 1.00
Evaluator_Draft4_Properties_Triad_Required 1106.6306291324545 ns/iter 1105.6933279017292 ns/iter 1.00
Evaluator_Draft4_Non_Recursive_Ref 47.02137830314189 ns/iter 46.72936390986542 ns/iter 1.01
Evaluator_Draft4_Pattern_Properties_True 1271.1302243511177 ns/iter 1267.4226914582648 ns/iter 1.00
Evaluator_Draft4_Ref_To_Single_Property 63.18889211938988 ns/iter 64.42907097513138 ns/iter 0.98
Evaluator_Draft4_Additional_Properties_Type 60.80882714524209 ns/iter 60.77650917744998 ns/iter 1.00
Evaluator_Draft4_Nested_Oneof 181.62786381163224 ns/iter 181.21706332367617 ns/iter 1.00
Evaluator_Draft6_Property_Names 511.6327356655807 ns/iter 476.4522744410623 ns/iter 1.07
Evaluator_Draft7_If_Then_Else 116.6369491746743 ns/iter 116.79004373154962 ns/iter 1.00
Evaluator_2019_09_Unevaluated_Properties 293.83587642238155 ns/iter 294.23217299040033 ns/iter 1.00
Evaluator_2019_09_OMC_JSON_V2_1 7691.997256047822 ns/iter 7832.185436145683 ns/iter 0.98
Evaluator_2020_12_Dynamic_Ref 1104.417952451438 ns/iter 1015.7972679089194 ns/iter 1.09

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/llvm)

Benchmark suite Current: 16b8531 Previous: 8242eff Ratio
Compiler_Draft6_AdaptiveCard 56790893003.00001 ns/iter 58656327284.000046 ns/iter 0.97
Compiler_2019_09_OMC_JSON_V2 10939867380.00001 ns/iter 11029887351.000013 ns/iter 0.99
Evaluator_Draft4_Meta_1_No_Callback 708.4443165252411 ns/iter 710.7231261966888 ns/iter 1.00
Evaluator_Draft4_Required_Properties 1092.3617405629136 ns/iter 1112.8009491637536 ns/iter 0.98
Evaluator_Draft4_Many_Optional_Properties_Minimal_Match 128.66303763236127 ns/iter 127.7140790304338 ns/iter 1.01
Evaluator_Draft4_Few_Optional_Properties_Minimal_Match 87.95189491608681 ns/iter 88.4862823693509 ns/iter 0.99
Evaluator_Draft4_Items_Schema 1920.4902560672708 ns/iter 1911.050461101069 ns/iter 1.00
Evaluator_Draft4_Nested_Object 28.777455469135777 ns/iter 29.578458001012798 ns/iter 0.97
Evaluator_Draft4_Properties_Triad_Optional 1582.206298108089 ns/iter 1599.6877331786256 ns/iter 0.99
Evaluator_Draft4_Properties_Triad_Closed 1282.2594556289112 ns/iter 1281.2071543018865 ns/iter 1.00
Evaluator_Draft4_Properties_Triad_Required 1536.1052152940413 ns/iter 1543.4118240099049 ns/iter 1.00
Evaluator_Draft4_Non_Recursive_Ref 79.72610094850961 ns/iter 77.55470151558609 ns/iter 1.03
Evaluator_Draft4_Pattern_Properties_True 2185.679805610496 ns/iter 2189.4378076971175 ns/iter 1.00
Evaluator_Draft4_Ref_To_Single_Property 87.86658750416937 ns/iter 88.80740605559598 ns/iter 0.99
Evaluator_Draft4_Additional_Properties_Type 100.87906860174596 ns/iter 101.26726209986977 ns/iter 1.00
Evaluator_Draft4_Nested_Oneof 270.21452092295823 ns/iter 267.99624630436705 ns/iter 1.01
Evaluator_Draft6_Property_Names 868.4738749663609 ns/iter 893.0530702017048 ns/iter 0.97
Evaluator_Draft7_If_Then_Else 156.684481012285 ns/iter 157.83150351213658 ns/iter 0.99
Evaluator_2019_09_Unevaluated_Properties 405.707624096159 ns/iter 381.6299097601865 ns/iter 1.06
Evaluator_2019_09_OMC_JSON_V2_1 11745.321912161859 ns/iter 11920.596438518918 ns/iter 0.99
Evaluator_2020_12_Dynamic_Ref 1370.8886737163166 ns/iter 1371.8075738365008 ns/iter 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (linux/gcc)

Benchmark suite Current: 16b8531 Previous: 8242eff Ratio
Evaluator_2020_12_Dynamic_Ref 1344.1606814875038 ns/iter 1318.1500423007574 ns/iter 1.02
Evaluator_2019_09_Unevaluated_Properties 405.4976934655142 ns/iter 404.693585570588 ns/iter 1.00
Evaluator_2019_09_OMC_JSON_V2_1 14011.34828874391 ns/iter 14251.693383130672 ns/iter 0.98
Evaluator_Draft7_If_Then_Else 147.00701287172322 ns/iter 146.22661436310665 ns/iter 1.01
Evaluator_Draft6_Property_Names 1549.9154636478509 ns/iter 1529.4874233370401 ns/iter 1.01
Evaluator_Draft4_Meta_1_No_Callback 765.984595110889 ns/iter 760.7858064613256 ns/iter 1.01
Evaluator_Draft4_Required_Properties 1979.3782391516186 ns/iter 1989.231567244302 ns/iter 1.00
Evaluator_Draft4_Many_Optional_Properties_Minimal_Match 137.50732488893286 ns/iter 132.06443705765284 ns/iter 1.04
Evaluator_Draft4_Few_Optional_Properties_Minimal_Match 101.9158988583964 ns/iter 97.01944931205378 ns/iter 1.05
Evaluator_Draft4_Items_Schema 1543.1457215451028 ns/iter 1578.0392720741252 ns/iter 0.98
Evaluator_Draft4_Nested_Object 26.532762130649374 ns/iter 26.284575160213535 ns/iter 1.01
Evaluator_Draft4_Properties_Triad_Optional 1576.4661976222112 ns/iter 1590.10073623296 ns/iter 0.99
Evaluator_Draft4_Properties_Triad_Closed 1276.2614857915337 ns/iter 1288.4176723249411 ns/iter 0.99
Evaluator_Draft4_Properties_Triad_Required 1611.566642539611 ns/iter 1627.5158728683743 ns/iter 0.99
Evaluator_Draft4_Non_Recursive_Ref 99.71594890373909 ns/iter 94.87291019850115 ns/iter 1.05
Evaluator_Draft4_Pattern_Properties_True 2233.591012781577 ns/iter 2235.2400302961555 ns/iter 1.00
Evaluator_Draft4_Ref_To_Single_Property 103.44113876053524 ns/iter 100.94591594000536 ns/iter 1.02
Evaluator_Draft4_Additional_Properties_Type 154.33849291780498 ns/iter 149.52410450289906 ns/iter 1.03
Evaluator_Draft4_Nested_Oneof 230.7571959791813 ns/iter 230.21273567899905 ns/iter 1.00
Compiler_2019_09_OMC_JSON_V2 11342681725.000034 ns/iter 11219970020.999994 ns/iter 1.01
Compiler_Draft6_AdaptiveCard 65464620907.00004 ns/iter 65180781747.000084 ns/iter 1.00

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (macos/gcc)

Benchmark suite Current: 16b8531 Previous: 8242eff Ratio
Compiler_Draft6_AdaptiveCard 46922742128.37219 ns/iter 47036839008.3313 ns/iter 1.00
Compiler_2019_09_OMC_JSON_V2 8682300090.789795 ns/iter 8476594924.926758 ns/iter 1.02
Evaluator_Draft4_Meta_1_No_Callback 538.7234763086497 ns/iter 569.0227235350648 ns/iter 0.95
Evaluator_Draft4_Required_Properties 698.6922035595182 ns/iter 717.9275369612184 ns/iter 0.97
Evaluator_Draft4_Many_Optional_Properties_Minimal_Match 118.96387949943826 ns/iter 120.25284606693224 ns/iter 0.99
Evaluator_Draft4_Few_Optional_Properties_Minimal_Match 85.16968636525901 ns/iter 77.67931911630862 ns/iter 1.10
Evaluator_Draft4_Items_Schema 1480.822805467645 ns/iter 1281.0423439448111 ns/iter 1.16
Evaluator_Draft4_Nested_Object 25.850546284402498 ns/iter 25.957688501326025 ns/iter 1.00
Evaluator_Draft4_Properties_Triad_Optional 1444.3984107481813 ns/iter 1407.342136951041 ns/iter 1.03
Evaluator_Draft4_Properties_Triad_Closed 1207.8554077321808 ns/iter 1217.9130513485698 ns/iter 0.99
Evaluator_Draft4_Properties_Triad_Required 1321.6423781004469 ns/iter 1326.2886692967925 ns/iter 1.00
Evaluator_Draft4_Non_Recursive_Ref 65.25831147803784 ns/iter 64.81134443170322 ns/iter 1.01
Evaluator_Draft4_Pattern_Properties_True 1816.1310844520062 ns/iter 1736.4175322710178 ns/iter 1.05
Evaluator_Draft4_Ref_To_Single_Property 80.99254078185204 ns/iter 82.12192422407297 ns/iter 0.99
Evaluator_Draft4_Additional_Properties_Type 80.13360809045443 ns/iter 78.85375325367309 ns/iter 1.02
Evaluator_Draft4_Nested_Oneof 206.55504730128118 ns/iter 206.2100502897471 ns/iter 1.00
Evaluator_Draft6_Property_Names 646.4913459780602 ns/iter 658.8780703121685 ns/iter 0.98
Evaluator_Draft7_If_Then_Else 134.49424217709515 ns/iter 127.54048709705796 ns/iter 1.05
Evaluator_2019_09_Unevaluated_Properties 349.05206879172823 ns/iter 357.12492685689654 ns/iter 0.98
Evaluator_2019_09_OMC_JSON_V2_1 8131.000411906226 ns/iter 8122.096170701714 ns/iter 1.00
Evaluator_2020_12_Dynamic_Ref 1188.9650883391766 ns/iter 1201.3678142356707 ns/iter 0.99

This comment was automatically generated by workflow using github-action-benchmark.

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmark (windows/msvc)

Benchmark suite Current: 16b8531 Previous: 8242eff Ratio
Compiler_Draft6_AdaptiveCard 119554981099.99985 ns/iter 120297761299.99982 ns/iter 0.99
Compiler_2019_09_OMC_JSON_V2 25187896599.99993 ns/iter 25351995300 ns/iter 0.99
Evaluator_Draft4_Meta_1_No_Callback 1485.9815017942667 ns/iter 1489.2087053571652 ns/iter 1.00
Evaluator_Draft4_Required_Properties 1472.102624061446 ns/iter 1460.889955357203 ns/iter 1.01
Evaluator_Draft4_Many_Optional_Properties_Minimal_Match 353.4558014935187 ns/iter 361.4998104464673 ns/iter 0.98
Evaluator_Draft4_Few_Optional_Properties_Minimal_Match 243.78141490089942 ns/iter 244.88160213375423 ns/iter 1.00
Evaluator_Draft4_Items_Schema 3281.1004392195073 ns/iter 3197.3524958640774 ns/iter 1.03
Evaluator_Draft4_Nested_Object 110.70003124999062 ns/iter 111.81003124999478 ns/iter 0.99
Evaluator_Draft4_Properties_Triad_Optional 5168.441071428934 ns/iter 5183.61428571471 ns/iter 1.00
Evaluator_Draft4_Properties_Triad_Closed 4192.753396092088 ns/iter 4224.37713197426 ns/iter 0.99
Evaluator_Draft4_Properties_Triad_Required 5135.4959999980565 ns/iter 5160.114285715167 ns/iter 1.00
Evaluator_Draft4_Non_Recursive_Ref 250.66546428571914 ns/iter 252.65964285714355 ns/iter 0.99
Evaluator_Draft4_Pattern_Properties_True 8138.133311903805 ns/iter 8195.38216347032 ns/iter 0.99
Evaluator_Draft4_Ref_To_Single_Property 246.23328571424608 ns/iter 247.46239285710607 ns/iter 1.00
Evaluator_Draft4_Additional_Properties_Type 335.49188054564263 ns/iter 337.81745306830015 ns/iter 0.99
Evaluator_Draft4_Nested_Oneof 558.7333035714031 ns/iter 562.9029464285752 ns/iter 0.99
Evaluator_Draft6_Property_Names 1534.4743303573289 ns/iter 1535.709693879318 ns/iter 1.00
Evaluator_Draft7_If_Then_Else 371.3410051176826 ns/iter 374.8181652110928 ns/iter 0.99
Evaluator_2019_09_Unevaluated_Properties 957.7372510102197 ns/iter 935.5809216156622 ns/iter 1.02
Evaluator_2019_09_OMC_JSON_V2_1 16923.797480785342 ns/iter 16963.599086602462 ns/iter 1.00
Evaluator_2020_12_Dynamic_Ref 3147.303125000381 ns/iter 3117.904464285662 ns/iter 1.01

This comment was automatically generated by workflow using github-action-benchmark.

Please sign in to comment.