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

perf test: Display number of active running tests

Before polling or sleeping to wait for a test to complete, print out
": Running (<num> active)" where the number of active tests is
determined by iterating over the tests and seeing which return false
for check_if_command_finished. The line erasing and printing out only
occur if the number of runnings tests changes to avoid the line
flickering excessively. Knowing tests are running allows a user to
know a test is running and in parallel mode how many of the tests are
waiting to complete. If color mode is disabled then avoid displaying
the "Running" message as deleting the line isn't reliable.

Tested-by: James Clark <james.clark@linaro.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Colin Ian King <colin.i.king@gmail.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Weilin Wang <weilin.wang@intel.com>
Cc: Ilya Leoshkevich <iii@linux.ibm.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Athira Jajeev <atrajeev@linux.vnet.ibm.com>
Cc: Michael Petlan <mpetlan@redhat.com>
Cc: Veronika Molnarova <vmolnaro@redhat.com>
Link: https://lore.kernel.org/r/20241025192109.132482-3-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>

authored by

Ian Rogers and committed by
Namhyung Kim
0e036dca 5ce42b5d

+63 -31
+62 -31
tools/perf/tests/builtin-test.c
··· 245 245 return -err; 246 246 } 247 247 248 - static int print_test_result(struct test_suite *t, int i, int subtest, int result, int width) 248 + #define TEST_RUNNING -3 249 + 250 + static int print_test_result(struct test_suite *t, int i, int subtest, int result, int width, 251 + int running) 249 252 { 250 253 if (has_subtests(t)) { 251 254 int subw = width > 2 ? width - 2 : width; ··· 258 255 pr_info("%3d: %-*s:", i + 1, width, test_description(t, subtest)); 259 256 260 257 switch (result) { 258 + case TEST_RUNNING: 259 + color_fprintf(stderr, PERF_COLOR_YELLOW, " Running (%d active)\n", running); 260 + break; 261 261 case TEST_OK: 262 262 pr_info(" Ok\n"); 263 263 break; ··· 282 276 return 0; 283 277 } 284 278 285 - static int finish_test(struct child_test *child_test, int width) 279 + static int finish_test(struct child_test **child_tests, int running_test, int child_test_num, 280 + int width) 286 281 { 282 + struct child_test *child_test = child_tests[running_test]; 287 283 struct test_suite *t = child_test->test; 288 284 int i = child_test->test_num; 289 285 int subi = child_test->subtest; 290 286 int err = child_test->process.err; 291 - bool err_done = err <= 0; 287 + bool err_done = false; 292 288 struct strbuf err_output = STRBUF_INIT; 289 + int last_running = -1; 293 290 int ret; 294 291 295 292 /* ··· 306 297 * Busy loop reading from the child's stdout/stderr that are set to be 307 298 * non-blocking until EOF. 308 299 */ 309 - if (!err_done) 300 + if (err > 0) 310 301 fcntl(err, F_SETFL, O_NONBLOCK); 311 302 if (verbose > 1) { 312 303 if (has_subtests(t)) ··· 320 311 .events = POLLIN | POLLERR | POLLHUP | POLLNVAL, 321 312 }, 322 313 }; 323 - char buf[512]; 324 - ssize_t len; 314 + if (perf_use_color_default) { 315 + int running = 0; 325 316 326 - /* Poll to avoid excessive spinning, timeout set for 100ms. */ 327 - poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100); 328 - if (!err_done && pfds[0].revents) { 329 - errno = 0; 330 - len = read(err, buf, sizeof(buf) - 1); 331 - 332 - if (len <= 0) { 333 - err_done = errno != EAGAIN; 334 - } else { 335 - buf[len] = '\0'; 336 - if (verbose > 1) 337 - fprintf(stdout, "%s", buf); 338 - else 339 - strbuf_addstr(&err_output, buf); 317 + for (int y = running_test; y < child_test_num; y++) { 318 + if (check_if_command_finished(&child_tests[y]->process) == 0) 319 + running++; 320 + } 321 + if (running != last_running) { 322 + if (last_running != -1) { 323 + /* 324 + * Erase "Running (.. active)" line 325 + * printed before poll/sleep. 326 + */ 327 + fprintf(debug_file(), PERF_COLOR_DELETE_LINE); 328 + } 329 + print_test_result(t, i, subi, TEST_RUNNING, width, running); 330 + last_running = running; 340 331 } 341 332 } 333 + 334 + err_done = true; 335 + if (err <= 0) { 336 + /* No child stderr to poll, sleep for 10ms for child to complete. */ 337 + usleep(10 * 1000); 338 + } else { 339 + /* Poll to avoid excessive spinning, timeout set for 100ms. */ 340 + poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100); 341 + if (pfds[0].revents) { 342 + char buf[512]; 343 + ssize_t len; 344 + 345 + len = read(err, buf, sizeof(buf) - 1); 346 + 347 + if (len > 0) { 348 + err_done = false; 349 + buf[len] = '\0'; 350 + strbuf_addstr(&err_output, buf); 351 + } 352 + } 353 + } 354 + if (err_done) 355 + err_done = check_if_command_finished(&child_test->process); 356 + } 357 + if (perf_use_color_default && last_running != -1) { 358 + /* Erase "Running (.. active)" line printed before poll/sleep. */ 359 + fprintf(debug_file(), PERF_COLOR_DELETE_LINE); 342 360 } 343 361 /* Clean up child process. */ 344 362 ret = finish_command(&child_test->process); 345 - if (verbose == 1 && ret == TEST_FAIL) { 346 - /* Add header for test that was skipped above. */ 347 - if (has_subtests(t)) 348 - pr_info("%3d.%1d: %s:\n", i + 1, subi + 1, test_description(t, subi)); 349 - else 350 - pr_info("%3d: %s:\n", i + 1, test_description(t, -1)); 363 + if (verbose > 1 || (verbose == 1 && ret == TEST_FAIL)) 351 364 fprintf(stderr, "%s", err_output.buf); 352 - } 365 + 353 366 strbuf_release(&err_output); 354 - print_test_result(t, i, subi, ret, width); 367 + print_test_result(t, i, subi, ret, width, /*running=*/0); 355 368 if (err > 0) 356 369 close(err); 357 370 return 0; ··· 389 358 pr_debug("--- start ---\n"); 390 359 err = test_function(test, subi)(test, subi); 391 360 pr_debug("---- end ----\n"); 392 - print_test_result(test, i, subi, err, width); 361 + print_test_result(test, i, subi, err, width, /*running=*/0); 393 362 return 0; 394 363 } 395 364 ··· 414 383 err = start_command(&(*child)->process); 415 384 if (err || !sequential) 416 385 return err; 417 - return finish_test(*child, width); 386 + return finish_test(child, /*running_test=*/0, /*child_test_num=*/1, width); 418 387 } 419 388 420 389 #define for_each_test(j, k, t) \ ··· 499 468 } 500 469 for (i = 0; i < child_test_num; i++) { 501 470 if (!sequential) { 502 - int ret = finish_test(child_tests[i], width); 471 + int ret = finish_test(child_tests, i, child_test_num, width); 503 472 504 473 if (ret) 505 474 return ret;
+1
tools/perf/util/color.h
··· 23 23 #define MIN_GREEN 0.5 24 24 #define MIN_RED 5.0 25 25 26 + #define PERF_COLOR_DELETE_LINE "\033[A\33[2K\r" 26 27 /* 27 28 * This variable stores the value of color.ui 28 29 */