Skip to content

Commit 0e036dc

Browse files
captain5050namhyung
authored andcommitted
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 <[email protected]> Signed-off-by: Ian Rogers <[email protected]> Cc: Colin Ian King <[email protected]> Cc: Howard Chu <[email protected]> Cc: Weilin Wang <[email protected]> Cc: Ilya Leoshkevich <[email protected]> Cc: Thomas Richter <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Dapeng Mi <[email protected]> Cc: Athira Jajeev <[email protected]> Cc: Michael Petlan <[email protected]> Cc: Veronika Molnarova <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Namhyung Kim <[email protected]>
1 parent 5ce42b5 commit 0e036dc

File tree

2 files changed

+63
-31
lines changed

2 files changed

+63
-31
lines changed

tools/perf/tests/builtin-test.c

Lines changed: 62 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,10 @@ static int run_test_child(struct child_process *process)
245245
return -err;
246246
}
247247

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)
249252
{
250253
if (has_subtests(t)) {
251254
int subw = width > 2 ? width - 2 : width;
@@ -255,6 +258,9 @@ static int print_test_result(struct test_suite *t, int i, int subtest, int resul
255258
pr_info("%3d: %-*s:", i + 1, width, test_description(t, subtest));
256259

257260
switch (result) {
261+
case TEST_RUNNING:
262+
color_fprintf(stderr, PERF_COLOR_YELLOW, " Running (%d active)\n", running);
263+
break;
258264
case TEST_OK:
259265
pr_info(" Ok\n");
260266
break;
@@ -276,14 +282,17 @@ static int print_test_result(struct test_suite *t, int i, int subtest, int resul
276282
return 0;
277283
}
278284

279-
static int finish_test(struct child_test *child_test, int width)
285+
static int finish_test(struct child_test **child_tests, int running_test, int child_test_num,
286+
int width)
280287
{
288+
struct child_test *child_test = child_tests[running_test];
281289
struct test_suite *t = child_test->test;
282290
int i = child_test->test_num;
283291
int subi = child_test->subtest;
284292
int err = child_test->process.err;
285-
bool err_done = err <= 0;
293+
bool err_done = false;
286294
struct strbuf err_output = STRBUF_INIT;
295+
int last_running = -1;
287296
int ret;
288297

289298
/*
@@ -297,7 +306,7 @@ static int finish_test(struct child_test *child_test, int width)
297306
* Busy loop reading from the child's stdout/stderr that are set to be
298307
* non-blocking until EOF.
299308
*/
300-
if (!err_done)
309+
if (err > 0)
301310
fcntl(err, F_SETFL, O_NONBLOCK);
302311
if (verbose > 1) {
303312
if (has_subtests(t))
@@ -311,38 +320,60 @@ static int finish_test(struct child_test *child_test, int width)
311320
.events = POLLIN | POLLERR | POLLHUP | POLLNVAL,
312321
},
313322
};
314-
char buf[512];
315-
ssize_t len;
316-
317-
/* Poll to avoid excessive spinning, timeout set for 100ms. */
318-
poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100);
319-
if (!err_done && pfds[0].revents) {
320-
errno = 0;
321-
len = read(err, buf, sizeof(buf) - 1);
322-
323-
if (len <= 0) {
324-
err_done = errno != EAGAIN;
325-
} else {
326-
buf[len] = '\0';
327-
if (verbose > 1)
328-
fprintf(stdout, "%s", buf);
329-
else
323+
if (perf_use_color_default) {
324+
int running = 0;
325+
326+
for (int y = running_test; y < child_test_num; y++) {
327+
if (check_if_command_finished(&child_tests[y]->process) == 0)
328+
running++;
329+
}
330+
if (running != last_running) {
331+
if (last_running != -1) {
332+
/*
333+
* Erase "Running (.. active)" line
334+
* printed before poll/sleep.
335+
*/
336+
fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
337+
}
338+
print_test_result(t, i, subi, TEST_RUNNING, width, running);
339+
last_running = running;
340+
}
341+
}
342+
343+
err_done = true;
344+
if (err <= 0) {
345+
/* No child stderr to poll, sleep for 10ms for child to complete. */
346+
usleep(10 * 1000);
347+
} else {
348+
/* Poll to avoid excessive spinning, timeout set for 100ms. */
349+
poll(pfds, ARRAY_SIZE(pfds), /*timeout=*/100);
350+
if (pfds[0].revents) {
351+
char buf[512];
352+
ssize_t len;
353+
354+
len = read(err, buf, sizeof(buf) - 1);
355+
356+
if (len > 0) {
357+
err_done = false;
358+
buf[len] = '\0';
330359
strbuf_addstr(&err_output, buf);
360+
}
331361
}
332362
}
363+
if (err_done)
364+
err_done = check_if_command_finished(&child_test->process);
365+
}
366+
if (perf_use_color_default && last_running != -1) {
367+
/* Erase "Running (.. active)" line printed before poll/sleep. */
368+
fprintf(debug_file(), PERF_COLOR_DELETE_LINE);
333369
}
334370
/* Clean up child process. */
335371
ret = finish_command(&child_test->process);
336-
if (verbose == 1 && ret == TEST_FAIL) {
337-
/* Add header for test that was skipped above. */
338-
if (has_subtests(t))
339-
pr_info("%3d.%1d: %s:\n", i + 1, subi + 1, test_description(t, subi));
340-
else
341-
pr_info("%3d: %s:\n", i + 1, test_description(t, -1));
372+
if (verbose > 1 || (verbose == 1 && ret == TEST_FAIL))
342373
fprintf(stderr, "%s", err_output.buf);
343-
}
374+
344375
strbuf_release(&err_output);
345-
print_test_result(t, i, subi, ret, width);
376+
print_test_result(t, i, subi, ret, width, /*running=*/0);
346377
if (err > 0)
347378
close(err);
348379
return 0;
@@ -358,7 +389,7 @@ static int start_test(struct test_suite *test, int i, int subi, struct child_tes
358389
pr_debug("--- start ---\n");
359390
err = test_function(test, subi)(test, subi);
360391
pr_debug("---- end ----\n");
361-
print_test_result(test, i, subi, err, width);
392+
print_test_result(test, i, subi, err, width, /*running=*/0);
362393
return 0;
363394
}
364395

@@ -383,7 +414,7 @@ static int start_test(struct test_suite *test, int i, int subi, struct child_tes
383414
err = start_command(&(*child)->process);
384415
if (err || !sequential)
385416
return err;
386-
return finish_test(*child, width);
417+
return finish_test(child, /*running_test=*/0, /*child_test_num=*/1, width);
387418
}
388419

389420
#define for_each_test(j, k, t) \
@@ -468,7 +499,7 @@ static int __cmd_test(int argc, const char *argv[], struct intlist *skiplist)
468499
}
469500
for (i = 0; i < child_test_num; i++) {
470501
if (!sequential) {
471-
int ret = finish_test(child_tests[i], width);
502+
int ret = finish_test(child_tests, i, child_test_num, width);
472503

473504
if (ret)
474505
return ret;

tools/perf/util/color.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define MIN_GREEN 0.5
2424
#define MIN_RED 5.0
2525

26+
#define PERF_COLOR_DELETE_LINE "\033[A\33[2K\r"
2627
/*
2728
* This variable stores the value of color.ui
2829
*/

0 commit comments

Comments
 (0)