From patchwork Mon Sep 5 20:19:32 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eugeni Dodonov X-Patchwork-Id: 1125442 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter2.kernel.org (8.14.4/8.14.4) with ESMTP id p85KNG1o014313 for ; Mon, 5 Sep 2011 20:23:51 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 21B3C9F612 for ; Mon, 5 Sep 2011 13:23:15 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from oproxy9.bluehost.com (oproxy9.bluehost.com [69.89.24.6]) by gabe.freedesktop.org (Postfix) with SMTP id 0BB11A093A for ; Mon, 5 Sep 2011 13:20:38 -0700 (PDT) Received: (qmail 30097 invoked by uid 0); 5 Sep 2011 20:20:38 -0000 Received: from unknown (HELO box335.bluehost.com) (69.89.31.135) by oproxy9.bluehost.com with SMTP; 5 Sep 2011 20:20:38 -0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=dodonov.net; s=default; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=xcxy3W8J62GIb9OiS1ERHnP3V4eMQKCBOw9sPq912WU=; b=D0LMTLwFgbKVllmWhlIC81DSu51tQjmWY6kmiUrTFrG9sxb9zP4oVJBiPTGqmG8dz7n7G52xMA13mB+AISw7KopVdOfYGmEvtv+qnJpboz8Ru6xMD2k+6tpTdtX/Jn+3; Received: from 200.188.217.18.dedicated.neoviatelecom.com.br ([200.188.217.18] helo=localhost.localdomain) by box335.bluehost.com with esmtpsa (TLSv1:AES256-SHA:256) (Exim 4.76) (envelope-from ) id 1R0feo-0007ag-1D; Mon, 05 Sep 2011 14:20:38 -0600 From: Eugeni Dodonov To: intel-gfx@lists.freedesktop.org Date: Mon, 5 Sep 2011 17:19:32 -0300 Message-Id: <1315253973-18950-6-git-send-email-eugeni@dodonov.net> X-Mailer: git-send-email 1.7.6.1 In-Reply-To: <1315253973-18950-1-git-send-email-eugeni@dodonov.net> References: <1315253973-18950-1-git-send-email-eugeni@dodonov.net> X-Identified-User: {669:box335.bluehost.com:dodonovn:dodonov.net} {sentby:smtp auth 200.188.217.18 authed with eugeni@dodonov.net} Cc: Eugeni Dodonov Subject: [Intel-gfx] [PATCH 5/6] intel_gpu_top: support non-interactive mode X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter2.kernel.org [140.211.167.43]); Mon, 05 Sep 2011 20:23:51 +0000 (UTC) From: Eugeni Dodonov This patch adds support for non-interactive mode, invoked by running with '-o output' switch. In this case, no interactive output is being performed, but the execution statistics are being saved into the output file. The output file is generated in both human and gnuplot-readable format. Unlike interactive mode, where non-supported pipes and non-active registers are skipped, the content of such pipes and registers is recorded into the log file to simplify parsing and standardize the list of columns. Also, unlike interactive mode, the registers are not sorted according to the usage - this way, their variation over time can be analysed offline. Signed-off-by: Eugeni Dodonov --- man/intel_gpu_top.1 | 3 + tools/intel_gpu_top.c | 150 +++++++++++++++++++++++++++++++++++------------- 2 files changed, 112 insertions(+), 41 deletions(-) diff --git a/man/intel_gpu_top.1 b/man/intel_gpu_top.1 index 2cbbec9..bca83f0 100644 --- a/man/intel_gpu_top.1 +++ b/man/intel_gpu_top.1 @@ -16,6 +16,9 @@ privilege to map the graphics device. .B -s [samples per second] number of samples to acquire per second .TP +.B -o [output file] +run non-interactively and collect usage statistics to [file] +.TP .B -h show usage notes .PP diff --git a/tools/intel_gpu_top.c b/tools/intel_gpu_top.c index e2dd173..88f7157 100644 --- a/tools/intel_gpu_top.c +++ b/tools/intel_gpu_top.c @@ -373,24 +373,39 @@ static void ring_sample(struct ring *ring) ring->full += full; } +static void ring_print_header(FILE *out, struct ring *ring) +{ + fprintf(out, "%.6s%%\tops\t", + ring->name + ); +} + static void ring_print(struct ring *ring, unsigned long samples_per_sec, FILE *output) { int samples_to_percent_ratio, percent, len; - if (!ring->size) - return; - /* Calculate current value of samples_to_percent_ratio */ samples_to_percent_ratio = (ring->idle * 100) / samples_per_sec; percent = 100 - samples_to_percent_ratio; - len = fprintf(output, "%25s busy: %3d%%: ", ring->name, percent); - print_percentage_bar (percent, len); - fprintf(output, "%24s space: %d/%d (%d%%)\n", - ring->name, - (int)(ring->full / samples_per_sec), - ring->size, - (int)((ring->full / samples_to_percent_ratio) / ring->size)); + + if (output == stdout) { + if (!ring->size) + return; + + len = fprintf(output, "%25s busy: %3d%%: ", ring->name, percent); + print_percentage_bar (percent, len); + fprintf(output, "%24s space: %d/%d (%d%%)\n", + ring->name, + (int)(ring->full / samples_per_sec), + ring->size, + (int)((ring->full / samples_to_percent_ratio) / ring->size)); + } else { + fprintf(output, "%3d\t%d\t", + (ring->size) ? 100 - ring->idle / samples_to_percent_ratio : -1, + (ring->size) ? (int)(ring->full / samples_per_sec) : -1 + ); + } } static void @@ -402,6 +417,7 @@ usage(const char *appname) "\n" "The following parameters apply:\n" "[-s ] samples per seconds (default %d)\n" + "[-o ] output to file (default to stdio)\n" "[-h] show this help screen\n" "\n", appname, @@ -429,9 +445,11 @@ int main(int argc, char **argv) int i, ch; int samples_per_sec = SAMPLES_PER_SEC; FILE *output = stdout; + double elapsed_time=0; + int print_headers=1; /* Parse options? */ - while ((ch = getopt(argc, argv, "s:h")) != -1) + while ((ch = getopt(argc, argv, "s:o:h")) != -1) { switch (ch) { @@ -441,6 +459,13 @@ int main(int argc, char **argv) exit(1); } break; + case 'o': output = fopen(optarg, "w"); + if (!output) + { + perror("fopen"); + exit(1); + } + break; case 'h': usage(argv[0]); exit(0); @@ -493,7 +518,7 @@ int main(int argc, char **argv) for (;;) { int j; - unsigned long long t1, ti, tf; + unsigned long long t1, ti, tf, t2; unsigned long long def_sleep = 1000000 / samples_per_sec; unsigned long long last_samples_per_sec = samples_per_sec; char clear_screen[] = {0x1b, '[', 'H', @@ -564,39 +589,82 @@ int main(int argc, char **argv) if (max_lines >= num_instdone_bits) max_lines = num_instdone_bits; - fprintf(output, "%s", clear_screen); - - print_clock_info(pci_dev); - - ring_print(&render_ring, last_samples_per_sec, output); - ring_print(&bsd_ring, last_samples_per_sec, output); - ring_print(&bsd6_ring, last_samples_per_sec, output); - ring_print(&blt_ring, last_samples_per_sec, output); - - fprintf(output, "\n%30s %s\n", "task", "percent busy"); - for (i = 0; i < max_lines; i++) { - if (top_bits_sorted[i]->count > 0) { - percent = (top_bits_sorted[i]->count * 100) / - last_samples_per_sec; - len = fprintf(output, "%30s: %3d%%: ", - top_bits_sorted[i]->bit->name, - percent); - print_percentage_bar (percent, len); - } else { - fprintf(output, "%*s", PERCENTAGE_BAR_END, ""); + t2 = gettime(); + elapsed_time += (t2 - t1) / 1000000.0; + + if (output == stdout) { + fprintf(output, "%s", clear_screen); + print_clock_info(pci_dev); + + ring_print(&render_ring, last_samples_per_sec, output); + ring_print(&bsd_ring, last_samples_per_sec, output); + ring_print(&bsd6_ring, last_samples_per_sec, output); + ring_print(&blt_ring, last_samples_per_sec, output); + + fprintf(output, "\n%30s %s\n", "task", "percent busy"); + for (i = 0; i < max_lines; i++) { + if (top_bits_sorted[i]->count > 0) { + percent = (top_bits_sorted[i]->count * 100) / + last_samples_per_sec; + len = fprintf(output, "%30s: %3d%%: ", + top_bits_sorted[i]->bit->name, + percent); + print_percentage_bar (percent, len); + } else { + fprintf(output, "%*s", PERCENTAGE_BAR_END, ""); + } + + if (i < STATS_COUNT && HAS_STATS_REGS(devid)) { + fprintf(output, "%13s: %llu (%lld/sec)", + stats_reg_names[i], + stats[i], + stats[i] - last_stats[i]); + last_stats[i] = stats[i]; + } else { + if (!top_bits_sorted[i]->count) + break; + } + fprintf(output, "\n"); + } + } else { + /* Print headers for columns at first run */ + if (print_headers) { + fprintf(output, "# time\t"); + ring_print_header(output, &render_ring); + ring_print_header(output, &bsd_ring); + ring_print_header(output, &bsd6_ring); + ring_print_header(output, &blt_ring); + for (i = 0; i < MAX_NUM_TOP_BITS; i++) { + if (i < STATS_COUNT && HAS_STATS_REGS(devid)) { + fprintf(output, "%.6s\t", + stats_reg_names[i] + ); + } + if (!top_bits[i].count) + continue; + } + fprintf(output, "\n"); + print_headers = 0; } - if (i < STATS_COUNT && HAS_STATS_REGS(devid)) { - fprintf(output, "%13s: %llu (%lld/sec)", - stats_reg_names[i], - stats[i], - stats[i] - last_stats[i]); - last_stats[i] = stats[i]; - } else { - if (!top_bits_sorted[i]->count) - break; + /* Print statistics */ + fprintf(output, "%.2f\t", elapsed_time); + ring_print(&render_ring, last_samples_per_sec, output); + ring_print(&bsd_ring, last_samples_per_sec, output); + ring_print(&bsd6_ring, last_samples_per_sec, output); + ring_print(&blt_ring, last_samples_per_sec, output); + + for (i = 0; i < MAX_NUM_TOP_BITS; i++) { + if (i < STATS_COUNT && HAS_STATS_REGS(devid)) { + fprintf(output, "%lu\t", + stats[i] - last_stats[i]); + last_stats[i] = stats[i]; + } + if (!top_bits[i].count) + continue; } fprintf(output, "\n"); + fflush(output); } for (i = 0; i < num_instdone_bits; i++) {