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.

selftests/resctrl: Calculate resctrl FS derived mem bw over sleep(1) only

For MBM/MBA tests, measure_vals() calls get_mem_bw_imc() that performs
the measurement over a duration of sleep(1) call. The memory bandwidth
numbers from IMC are derived over this duration. The resctrl FS derived
memory bandwidth, however, is calculated inside measure_vals() and only
takes delta between the previous value and the current one which
besides the actual test, also samples inter-test noise.

Rework the logic in measure_vals() and get_mem_bw_imc() such that the
resctrl FS memory bandwidth section covers much shorter duration
closely matching that of the IMC perf counters to improve measurement
accuracy.

For the second read after rewind() to return a fresh value, also
newline has to be consumed by the fscanf().

Suggested-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Tested-by: Babu Moger <babu.moger@amd.com>
Reviewed-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>

authored by

Ilpo Järvinen and committed by
Shuah Khan
da50de0a c44000b6

+92 -51
+92 -51
tools/testing/selftests/resctrl/resctrl_val.c
··· 306 306 } 307 307 308 308 /* 309 - * get_mem_bw_imc: Memory band width as reported by iMC counters 310 - * @cpu_no: CPU number that the benchmark PID is binded to 311 - * @bw_report: Bandwidth report type (reads, writes) 312 - * 313 - * Memory B/W utilized by a process on a socket can be calculated using 314 - * iMC counters. Perf events are used to read these counters. 309 + * perf_open_imc_mem_bw - Open perf fds for IMCs 310 + * @cpu_no: CPU number that the benchmark PID is bound to 315 311 * 316 312 * Return: = 0 on success. < 0 on failure. 317 313 */ 318 - static int get_mem_bw_imc(int cpu_no, char *bw_report, float *bw_imc) 314 + static int perf_open_imc_mem_bw(int cpu_no) 319 315 { 320 - float reads, writes, of_mul_read, of_mul_write; 321 316 int imc, ret; 322 317 323 318 for (imc = 0; imc < imcs; imc++) { ··· 320 325 imc_counters_config[imc][WRITE].fd = -1; 321 326 } 322 327 323 - /* Start all iMC counters to log values (both read and write) */ 324 - reads = 0, writes = 0, of_mul_read = 1, of_mul_write = 1; 325 328 for (imc = 0; imc < imcs; imc++) { 326 329 ret = open_perf_event(imc, cpu_no, READ); 327 330 if (ret) ··· 327 334 ret = open_perf_event(imc, cpu_no, WRITE); 328 335 if (ret) 329 336 goto close_fds; 337 + } 330 338 339 + return 0; 340 + 341 + close_fds: 342 + perf_close_imc_mem_bw(); 343 + return -1; 344 + } 345 + 346 + /* 347 + * do_mem_bw_test - Perform memory bandwidth test 348 + * 349 + * Runs memory bandwidth test over one second period. Also, handles starting 350 + * and stopping of the IMC perf counters around the test. 351 + */ 352 + static void do_imc_mem_bw_test(void) 353 + { 354 + int imc; 355 + 356 + for (imc = 0; imc < imcs; imc++) { 331 357 membw_ioctl_perf_event_ioc_reset_enable(imc, READ); 332 358 membw_ioctl_perf_event_ioc_reset_enable(imc, WRITE); 333 359 } ··· 358 346 membw_ioctl_perf_event_ioc_disable(imc, READ); 359 347 membw_ioctl_perf_event_ioc_disable(imc, WRITE); 360 348 } 349 + } 350 + 351 + /* 352 + * get_mem_bw_imc - Memory band width as reported by iMC counters 353 + * @bw_report: Bandwidth report type (reads, writes) 354 + * 355 + * Memory B/W utilized by a process on a socket can be calculated using 356 + * iMC counters. Perf events are used to read these counters. 357 + * 358 + * Return: = 0 on success. < 0 on failure. 359 + */ 360 + static int get_mem_bw_imc(char *bw_report, float *bw_imc) 361 + { 362 + float reads, writes, of_mul_read, of_mul_write; 363 + int imc; 364 + 365 + /* Start all iMC counters to log values (both read and write) */ 366 + reads = 0, writes = 0, of_mul_read = 1, of_mul_write = 1; 361 367 362 368 /* 363 369 * Get results which are stored in struct type imc_counter_config ··· 390 360 if (read(r->fd, &r->return_value, 391 361 sizeof(struct membw_read_format)) == -1) { 392 362 ksft_perror("Couldn't get read b/w through iMC"); 393 - goto close_fds; 363 + return -1; 394 364 } 395 365 396 366 if (read(w->fd, &w->return_value, 397 367 sizeof(struct membw_read_format)) == -1) { 398 368 ksft_perror("Couldn't get write bw through iMC"); 399 - goto close_fds; 369 + return -1; 400 370 } 401 371 402 372 __u64 r_time_enabled = r->return_value.time_enabled; ··· 416 386 writes += w->return_value.value * of_mul_write * SCALE; 417 387 } 418 388 419 - perf_close_imc_mem_bw(); 420 - 421 389 if (strcmp(bw_report, "reads") == 0) { 422 390 *bw_imc = reads; 423 391 return 0; ··· 428 400 429 401 *bw_imc = reads + writes; 430 402 return 0; 431 - 432 - close_fds: 433 - perf_close_imc_mem_bw(); 434 - return -1; 435 403 } 436 404 437 405 void set_mbm_path(const char *ctrlgrp, const char *mongrp, int domain_id) ··· 486 462 * 1. If con_mon grp is given, then read from it 487 463 * 2. If con_mon grp is not given, then read from root con_mon grp 488 464 */ 489 - static int get_mem_bw_resctrl(unsigned long *mbm_total) 465 + static FILE *open_mem_bw_resctrl(const char *mbm_bw_file) 490 466 { 491 467 FILE *fp; 492 468 493 - fp = fopen(mbm_total_path, "r"); 494 - if (!fp) { 469 + fp = fopen(mbm_bw_file, "r"); 470 + if (!fp) 495 471 ksft_perror("Failed to open total bw file"); 496 472 473 + return fp; 474 + } 475 + 476 + static int get_mem_bw_resctrl(FILE *fp, unsigned long *mbm_total) 477 + { 478 + if (fscanf(fp, "%lu\n", mbm_total) <= 0) { 479 + ksft_perror("Could not get MBM local bytes"); 497 480 return -1; 498 481 } 499 - if (fscanf(fp, "%lu", mbm_total) <= 0) { 500 - ksft_perror("Could not get mbm local bytes"); 501 - fclose(fp); 502 - 503 - return -1; 504 - } 505 - fclose(fp); 506 - 507 482 return 0; 508 483 } 509 484 ··· 638 615 set_cmt_path(ctrlgrp, mongrp, domain_id); 639 616 } 640 617 618 + /* 619 + * Measure memory bandwidth from resctrl and from another source which is 620 + * perf imc value or could be something else if perf imc event is not 621 + * available. Compare the two values to validate resctrl value. It takes 622 + * 1 sec to measure the data. 623 + */ 641 624 static int measure_vals(const struct user_params *uparams, 642 - struct resctrl_val_param *param, 643 - unsigned long *bw_resc_start) 625 + struct resctrl_val_param *param) 644 626 { 645 - unsigned long bw_resc, bw_resc_end; 627 + unsigned long bw_resc, bw_resc_start, bw_resc_end; 628 + FILE *mem_bw_fp; 646 629 float bw_imc; 647 630 int ret; 648 631 649 - /* 650 - * Measure memory bandwidth from resctrl and from 651 - * another source which is perf imc value or could 652 - * be something else if perf imc event is not available. 653 - * Compare the two values to validate resctrl value. 654 - * It takes 1sec to measure the data. 655 - */ 656 - ret = get_mem_bw_imc(uparams->cpu, param->bw_report, &bw_imc); 632 + mem_bw_fp = open_mem_bw_resctrl(mbm_total_path); 633 + if (!mem_bw_fp) 634 + return -1; 635 + 636 + ret = perf_open_imc_mem_bw(uparams->cpu); 657 637 if (ret < 0) 658 - return ret; 638 + goto close_fp; 659 639 660 - ret = get_mem_bw_resctrl(&bw_resc_end); 640 + ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_start); 661 641 if (ret < 0) 662 - return ret; 642 + goto close_imc; 663 643 664 - bw_resc = (bw_resc_end - *bw_resc_start) / MB; 665 - ret = print_results_bw(param->filename, bm_pid, bw_imc, bw_resc); 666 - if (ret) 667 - return ret; 644 + rewind(mem_bw_fp); 668 645 669 - *bw_resc_start = bw_resc_end; 646 + do_imc_mem_bw_test(); 670 647 671 - return 0; 648 + ret = get_mem_bw_resctrl(mem_bw_fp, &bw_resc_end); 649 + if (ret < 0) 650 + goto close_imc; 651 + 652 + ret = get_mem_bw_imc(param->bw_report, &bw_imc); 653 + if (ret < 0) 654 + goto close_imc; 655 + 656 + perf_close_imc_mem_bw(); 657 + fclose(mem_bw_fp); 658 + 659 + bw_resc = (bw_resc_end - bw_resc_start) / MB; 660 + 661 + return print_results_bw(param->filename, bm_pid, bw_imc, bw_resc); 662 + 663 + close_imc: 664 + perf_close_imc_mem_bw(); 665 + close_fp: 666 + fclose(mem_bw_fp); 667 + return ret; 672 668 } 673 669 674 670 /* ··· 761 719 struct resctrl_val_param *param) 762 720 { 763 721 char *resctrl_val = param->resctrl_val; 764 - unsigned long bw_resc_start = 0; 765 722 struct sigaction sigact; 766 723 int ret = 0, pipefd[2]; 767 724 char pipe_message = 0; ··· 902 861 903 862 if (!strncmp(resctrl_val, MBM_STR, sizeof(MBM_STR)) || 904 863 !strncmp(resctrl_val, MBA_STR, sizeof(MBA_STR))) { 905 - ret = measure_vals(uparams, param, &bw_resc_start); 864 + ret = measure_vals(uparams, param); 906 865 if (ret) 907 866 break; 908 867 } else if (!strncmp(resctrl_val, CMT_STR, sizeof(CMT_STR))) {