Build a synthetic graph (nodes Functions across packages, random CALLS * edges) and return the wall ms of the "boundaries" aspect. Returns -1 on * setup/query failure. */
| 408 | * edges) and return the wall ms of the "boundaries" aspect. Returns -1 on |
| 409 | * setup/query failure. */ |
| 410 | static double timed_boundaries_ms(int n_nodes, int n_edges, int n_pkgs) { |
| 411 | cbm_store_t *s = cbm_store_open_memory(); |
| 412 | if (!s) { |
| 413 | return -1; |
| 414 | } |
| 415 | cbm_store_upsert_project(s, "perf", "/tmp/perf"); |
| 416 | |
| 417 | cbm_store_begin(s); |
| 418 | int64_t *ids = malloc((size_t)n_nodes * sizeof(int64_t)); |
| 419 | if (!ids) { |
| 420 | cbm_store_close(s); |
| 421 | return -1; |
| 422 | } |
| 423 | for (int i = 0; i < n_nodes; i++) { |
| 424 | char name[32], qn[64]; |
| 425 | snprintf(name, sizeof(name), "fn%d", i); |
| 426 | snprintf(qn, sizeof(qn), "perf.pkg%d.fn%d", i % n_pkgs, i); |
| 427 | cbm_node_t n = {.project = "perf", |
| 428 | .label = "Function", |
| 429 | .name = name, |
| 430 | .qualified_name = qn, |
| 431 | .file_path = "f.c"}; |
| 432 | ids[i] = cbm_store_upsert_node(s, &n); |
| 433 | } |
| 434 | uint64_t rng = 42; |
| 435 | for (int i = 0; i < n_edges; i++) { |
| 436 | rng = rng * 6364136223846793005ULL + 1442695040888963407ULL; |
| 437 | int a = (int)((rng >> 33) % (uint64_t)n_nodes); |
| 438 | rng = rng * 6364136223846793005ULL + 1442695040888963407ULL; |
| 439 | int b = (int)((rng >> 33) % (uint64_t)n_nodes); |
| 440 | cbm_edge_t e = { |
| 441 | .project = "perf", .source_id = ids[a], .target_id = ids[b], .type = "CALLS"}; |
| 442 | cbm_store_insert_edge(s, &e); |
| 443 | } |
| 444 | cbm_store_commit(s); |
| 445 | free(ids); |
| 446 | |
| 447 | cbm_architecture_info_t info; |
| 448 | memset(&info, 0, sizeof(info)); |
| 449 | const char *aspects[] = {"boundaries"}; |
| 450 | struct timespec t0, t1; |
| 451 | clock_gettime(CLOCK_MONOTONIC, &t0); |
| 452 | int rc = cbm_store_get_architecture(s, "perf", NULL, aspects, 1, &info); |
| 453 | clock_gettime(CLOCK_MONOTONIC, &t1); |
| 454 | double ms = |
| 455 | (double)(t1.tv_sec - t0.tv_sec) * 1000.0 + (double)(t1.tv_nsec - t0.tv_nsec) / 1000000.0; |
| 456 | int bcount = info.boundary_count; |
| 457 | cbm_store_architecture_free(&info); |
| 458 | cbm_store_close(s); |
| 459 | if (rc != CBM_STORE_OK || bcount <= 0) { |
| 460 | return -1; |
| 461 | } |
| 462 | return ms; |
| 463 | } |
| 464 | |
| 465 | /* arch_boundaries used a LINEAR SCAN over all def nodes for EVERY CALLS edge |
| 466 | * (lookup_pkg over parallel arrays) — O(E×N). On the Linux kernel graph |
no test coverage detected