Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf pmu: Be lazy about loading event info files from sysfs

Event info is only needed when an event is parsed or when merging data
from an JSON and sysfs event. Be lazy in its loading to reduce file
accesses.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Gaosheng Cui <cuigaosheng1@huawei.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@arm.com>
Cc: Jing Zhang <renyu.zj@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Kajol Jain <kjain@linux.ibm.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@amd.com>
Cc: Rob Herring <robh@kernel.org>
Link: https://lore.kernel.org/r/20230824041330.266337-16-irogers@google.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Ian Rogers and committed by
Arnaldo Carvalho de Melo
7b723dbb 88ed9184

+83 -45
+83 -45
tools/perf/util/pmu.c
··· 58 58 struct list_head terms; 59 59 /** @list: List element of struct perf_pmu aliases. */ 60 60 struct list_head list; 61 + /** 62 + * @pmu_name: The name copied from the json struct pmu_event. This can 63 + * differ from the PMU name as it won't have suffixes. 64 + */ 65 + char *pmu_name; 61 66 /** @unit: Units for the event, such as bytes or cache lines. */ 62 67 char unit[UNIT_MAX_LEN+1]; 63 68 /** @scale: Value to scale read counter values by. */ ··· 84 79 * default. 85 80 */ 86 81 bool deprecated; 87 - /** 88 - * @pmu_name: The name copied from the json struct pmu_event. This can 89 - * differ from the PMU name as it won't have suffixes. 90 - */ 91 - char *pmu_name; 82 + /** @from_sysfs: Was the alias from sysfs or a json event? */ 83 + bool from_sysfs; 84 + /** @info_loaded: Have the scale, unit and other values been read from disk? */ 85 + bool info_loaded; 92 86 }; 93 87 94 88 /** ··· 284 280 return ret; 285 281 } 286 282 287 - static int perf_pmu__parse_scale(struct perf_pmu_alias *alias, int dirfd, const char *name) 283 + static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 288 284 { 289 285 struct stat st; 290 286 ssize_t sret; 287 + size_t len; 291 288 char scale[128]; 292 289 int fd, ret = -1; 293 290 char path[PATH_MAX]; 294 291 295 - scnprintf(path, PATH_MAX, "%s.scale", name); 292 + len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 293 + if (!len) 294 + return 0; 295 + scnprintf(path + len, sizeof(path) - len, "%s/%s.scale", pmu->name, alias->name); 296 296 297 - fd = openat(dirfd, path, O_RDONLY); 297 + fd = open(path, O_RDONLY); 298 298 if (fd == -1) 299 299 return -1; 300 300 ··· 320 312 return ret; 321 313 } 322 314 323 - static int perf_pmu__parse_unit(struct perf_pmu_alias *alias, int dirfd, const char *name) 315 + static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 324 316 { 325 317 char path[PATH_MAX]; 318 + size_t len; 326 319 ssize_t sret; 327 320 int fd; 328 321 329 - scnprintf(path, PATH_MAX, "%s.unit", name); 330 322 331 - fd = openat(dirfd, path, O_RDONLY); 323 + len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 324 + if (!len) 325 + return 0; 326 + scnprintf(path + len, sizeof(path) - len, "%s/%s.unit", pmu->name, alias->name); 327 + 328 + fd = open(path, O_RDONLY); 332 329 if (fd == -1) 333 330 return -1; 334 331 ··· 356 343 } 357 344 358 345 static int 359 - perf_pmu__parse_per_pkg(struct perf_pmu_alias *alias, int dirfd, const char *name) 346 + perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 360 347 { 361 348 char path[PATH_MAX]; 349 + size_t len; 362 350 int fd; 363 351 364 - scnprintf(path, PATH_MAX, "%s.per-pkg", name); 352 + len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 353 + if (!len) 354 + return 0; 355 + scnprintf(path + len, sizeof(path) - len, "%s/%s.per-pkg", pmu->name, alias->name); 365 356 366 - fd = openat(dirfd, path, O_RDONLY); 357 + fd = open(path, O_RDONLY); 367 358 if (fd == -1) 368 359 return -1; 369 360 ··· 377 360 return 0; 378 361 } 379 362 380 - static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias, 381 - int dirfd, const char *name) 363 + static int perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 382 364 { 383 365 char path[PATH_MAX]; 366 + size_t len; 384 367 int fd; 385 368 386 - scnprintf(path, PATH_MAX, "%s.snapshot", name); 369 + len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path)); 370 + if (!len) 371 + return 0; 372 + scnprintf(path + len, sizeof(path) - len, "%s/%s.snapshot", pmu->name, alias->name); 387 373 388 - fd = openat(dirfd, path, O_RDONLY); 374 + fd = open(path, O_RDONLY); 389 375 if (fd == -1) 390 376 return -1; 391 377 ··· 449 429 return true; 450 430 } 451 431 432 + static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias) 433 + { 434 + if (!alias->from_sysfs || alias->info_loaded) 435 + return; 436 + 437 + /* 438 + * load unit name and scale if available 439 + */ 440 + perf_pmu__parse_unit(pmu, alias); 441 + perf_pmu__parse_scale(pmu, alias); 442 + perf_pmu__parse_per_pkg(pmu, alias); 443 + perf_pmu__parse_snapshot(pmu, alias); 444 + } 445 + 446 + struct update_alias_data { 447 + struct perf_pmu *pmu; 448 + struct perf_pmu_alias *alias; 449 + }; 450 + 452 451 static int update_alias(const struct pmu_event *pe, 453 452 const struct pmu_events_table *table __maybe_unused, 454 453 void *vdata) 455 454 { 456 - struct perf_pmu_alias *alias = vdata; 455 + struct update_alias_data *data = vdata; 457 456 int ret = 0; 458 457 459 - assign_str(pe->name, "desc", &alias->desc, pe->desc); 460 - assign_str(pe->name, "long_desc", &alias->long_desc, pe->long_desc); 461 - assign_str(pe->name, "topic", &alias->topic, pe->topic); 462 - alias->per_pkg = pe->perpkg; 463 - if (assign_str(pe->name, "value", &alias->str, pe->event)) { 464 - parse_events_terms__purge(&alias->terms); 465 - ret = parse_events_terms(&alias->terms, pe->event, /*input=*/NULL); 458 + read_alias_info(data->pmu, data->alias); 459 + assign_str(pe->name, "desc", &data->alias->desc, pe->desc); 460 + assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc); 461 + assign_str(pe->name, "topic", &data->alias->topic, pe->topic); 462 + data->alias->per_pkg = pe->perpkg; 463 + if (assign_str(pe->name, "value", &data->alias->str, pe->event)) { 464 + parse_events_terms__purge(&data->alias->terms); 465 + ret = parse_events_terms(&data->alias->terms, pe->event, /*input=*/NULL); 466 466 } 467 467 if (!ret && pe->unit) { 468 468 char *unit; 469 469 470 - ret = perf_pmu__convert_scale(pe->unit, &unit, &alias->scale); 470 + ret = perf_pmu__convert_scale(pe->unit, &unit, &data->alias->scale); 471 471 if (!ret) 472 - snprintf(alias->unit, sizeof(alias->unit), "%s", unit); 472 + snprintf(data->alias->unit, sizeof(data->alias->unit), "%s", unit); 473 473 } 474 474 return ret; 475 475 } 476 476 477 - static int perf_pmu__new_alias(struct perf_pmu *pmu, int dirfd, const char *name, 477 + static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name, 478 478 const char *desc, const char *val, FILE *val_fd, 479 479 const struct pmu_event *pe) 480 480 { ··· 538 498 } 539 499 540 500 alias->name = strdup(name); 541 - if (dirfd >= 0) { 542 - /* 543 - * load unit name and scale if available 544 - */ 545 - perf_pmu__parse_unit(alias, dirfd, name); 546 - perf_pmu__parse_scale(alias, dirfd, name); 547 - perf_pmu__parse_per_pkg(alias, dirfd, name); 548 - perf_pmu__parse_snapshot(alias, dirfd, name); 549 - } 550 - 551 501 alias->desc = desc ? strdup(desc) : NULL; 552 502 alias->long_desc = long_desc ? strdup(long_desc) : 553 503 desc ? strdup(desc) : NULL; ··· 552 522 } 553 523 if (!pe) { 554 524 /* Update an event from sysfs with json data. */ 525 + struct update_alias_data data = { 526 + .pmu = pmu, 527 + .alias = alias, 528 + }; 529 + 530 + alias->from_sysfs = true; 555 531 if (pmu->events_table) { 556 532 if (pmu_events_table__find_event(pmu->events_table, pmu, name, 557 - update_alias, alias) == 0) 533 + update_alias, &data) == 0) 558 534 pmu->loaded_json_aliases++; 559 535 } 560 536 } ··· 648 612 continue; 649 613 } 650 614 651 - if (perf_pmu__new_alias(pmu, dirfd, name, /*desc=*/ NULL, 615 + if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL, 652 616 /*val=*/ NULL, file, /*pe=*/ NULL) < 0) 653 617 pr_debug("Cannot set up %s\n", name); 654 618 fclose(file); ··· 901 865 { 902 866 struct perf_pmu *pmu = vdata; 903 867 904 - perf_pmu__new_alias(pmu, -1, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe); 868 + perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ NULL, pe); 905 869 return 0; 906 870 } 907 871 ··· 937 901 938 902 if (!strcmp(pmu->id, pe->compat) && 939 903 pmu_uncore_alias_match(pe->pmu, pmu->name)) { 940 - perf_pmu__new_alias(pmu, -1, 904 + perf_pmu__new_alias(pmu, 941 905 pe->name, 942 906 pe->desc, 943 907 pe->event, ··· 1453 1417 } 1454 1418 1455 1419 1456 - static int check_info_data(struct perf_pmu_alias *alias, 1420 + static int check_info_data(struct perf_pmu *pmu, 1421 + struct perf_pmu_alias *alias, 1457 1422 struct perf_pmu_info *info, 1458 1423 struct parse_events_error *err, 1459 1424 int column) 1460 1425 { 1426 + read_alias_info(pmu, alias); 1461 1427 /* 1462 1428 * Only one term in event definition can 1463 1429 * define unit, scale and snapshot, fail ··· 1529 1491 return ret; 1530 1492 } 1531 1493 1532 - ret = check_info_data(alias, info, err, term->err_term); 1494 + ret = check_info_data(pmu, alias, info, err, term->err_term); 1533 1495 if (ret) 1534 1496 return ret; 1535 1497