From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13808 invoked by alias); 10 Oct 2009 22:26:10 -0000 Received: (qmail 13788 invoked by uid 22791); 10 Oct 2009 22:26:09 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mail-fx0-f225.google.com (HELO mail-fx0-f225.google.com) (209.85.220.225) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 10 Oct 2009 22:26:04 +0000 Received: by fxm25 with SMTP id 25so7228898fxm.0 for ; Sat, 10 Oct 2009 15:26:01 -0700 (PDT) Received: by 10.103.84.25 with SMTP id m25mr1744931mul.111.1255213561352; Sat, 10 Oct 2009 15:26:01 -0700 (PDT) Received: from debian (chello089079179132.chello.pl [89.79.179.132]) by mx.google.com with ESMTPS id y6sm5438319mug.10.2009.10.10.15.25.59 (version=TLSv1/SSLv3 cipher=RC4-MD5); Sat, 10 Oct 2009 15:26:00 -0700 (PDT) From: Przemyslaw Pawelczyk Date: Sat, 10 Oct 2009 22:26:00 -0000 Subject: [PATCH broken] PR10257: Add support for sprint[ln](@hist_*). MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit To: systemtap@sourceware.org Message-Id: <1255213558.128114.24766@debian> X-IsSubscribed: yes Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2009-q4/txt/msg00118.txt.bz2 Currently this patch doesn't work, because tmpvar added in sprint case in c_unparser::visit_print_format() doesn't increase number of __tmp variables available in struct probe_XYZ_locals that is generated by c_unparser::emit_common_header(). I certainly missed sth, but what? Any help will be appreciated. Reviews are also welcomed. $ stap -e 'global f; probe begin { f <<< 1 } probe end { a = sprint(@hist_log(f)); println(a) }' /tmp/stapKpTfn5/stap_24131.c: In function ‘probe_1846’: /tmp/stapKpTfn5/stap_24131.c:209: error: ‘struct probe_1846_locals’ has no member named ‘__tmp4’ /tmp/stapKpTfn5/stap_24131.c:210: error: ‘struct probe_1846_locals’ has no member named ‘__tmp4’ * parse.cxx (parser::parse_symbol): Add sprint[ln] to @hist_* hack. * runtime/stat-common.c: Add _stp_stat_print_histogram_buf and reprint_buf functions. * translate.cxx (c_unparser::visit_print_format): Add sprint case. --- parse.cxx | 3 +- runtime/stat-common.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++ translate.cxx | 14 ++++- 3 files changed, 185 insertions(+), 3 deletions(-) diff --git a/parse.cxx b/parse.cxx index b88ef7f..025824e 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2422,7 +2422,8 @@ parser::parse_symbol () fmt->print_char = pf_char; expect_op("("); - if ((name == "print" || name == "println") && + if ((name == "print" || name == "println" || + name == "sprint" || name == "sprintln") && (peek_kw("@hist_linear") || peek_kw("@hist_log"))) { // We have a special case where we recognize diff --git a/runtime/stat-common.c b/runtime/stat-common.c index 7dabe70..df5522f 100644 --- a/runtime/stat-common.c +++ b/runtime/stat-common.c @@ -61,6 +61,16 @@ static void reprint (int num, char *s) } } +static int reprint_buf(char *buf, size_t size, int num, char *s) +{ + char *cur_buf = buf; + while (num > 0) { + cur_buf += _stp_snprintf(cur_buf, buf + size - cur_buf, s); + num--; + } + return cur_buf - buf; +} + /* Given a bucket number for a log histogram, return the value. */ static int64_t _stp_bucket_to_val(int num) { @@ -299,6 +309,167 @@ static void _stp_stat_print_histogram (Hist st, stat *sd) _stp_print_flush(); } +static void _stp_stat_print_histogram_buf(char *buf, Hist st, stat *sd) +{ + int scale, i, j, val_space, cnt_space; + int low_bucket = -1, high_bucket = 0, over = 0, under = 0; + int64_t val, v, max = 0; + int eliding = 0; + char *cur_buf = buf; + + if (st->type != HIST_LOG && st->type != HIST_LINEAR) + return; + + /* Get the maximum value, for scaling. Also calculate the low + and high values to bound the reporting range. */ + for (i = 0; i < st->buckets; i++) { + if (sd->histogram[i] > 0 && low_bucket == -1) + low_bucket = i; + if (sd->histogram[i] > 0) + high_bucket = i; + if (sd->histogram[i] > max) + max = sd->histogram[i]; + } + + /* Touch up the bucket margin to show up to two zero-slots on + either side of the data range, seems aesthetically pleasant. */ + for (i = 0; i < 2; i++) { + if (st->type == HIST_LOG) { + /* For log histograms, don't go negative */ + /* unless there are negative values. */ + if (low_bucket != HIST_LOG_BUCKET0 && low_bucket > 0) + low_bucket--; + } else { + if (low_bucket > 0) + low_bucket--; + } + if (high_bucket < (st->buckets-1)) + high_bucket++; + } + if (st->type == HIST_LINEAR) { + /* Don't include under or overflow if they are 0. */ + if (low_bucket == 0 && sd->histogram[0] == 0) + low_bucket++; + if (high_bucket == st->buckets-1 && sd->histogram[high_bucket] == 0) + high_bucket--; + if (low_bucket == 0) + under = 1; + if (high_bucket == st->buckets-1) + over = 1; + } + + if (max <= HIST_WIDTH) + scale = 1; + else { + int64_t tmp = max; + int rem = do_div(tmp, HIST_WIDTH); + scale = tmp; + if (rem) scale++; + } + + /* count space */ + cnt_space = needed_space(max); + + /* Compute value space */ + if (st->type == HIST_LINEAR) { + i = needed_space(st->start) + under; + val_space = needed_space(st->start + st->interval * high_bucket) + over; + } else { + i = needed_space(_stp_bucket_to_val(high_bucket)); + val_space = needed_space(_stp_bucket_to_val(low_bucket)); + } + if (i > val_space) + val_space = i; + + + /* print header */ + j = 0; + if (val_space > 5) /* 5 = sizeof("value") */ + j = val_space - 5; + else + val_space = 5; + for ( i = 0; i < j; i++) + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, " "); + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, "value |"); + cur_buf += reprint_buf(cur_buf, buf + MAXSTRINGLEN - cur_buf, HIST_WIDTH, "-"); + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, " count\n"); + + eliding = 0; + for (i = low_bucket; i <= high_bucket; i++) { + int over_under = 0; + + /* Elide consecutive zero buckets. Specifically, skip + this row if it is zero and some of its nearest + neighbours are also zero. Don't elide zero buckets + if HIST_ELISION is negative */ + if ((long)HIST_ELISION >= 0) { + int k, elide = 1; + /* Can't elide more than the total # of buckets */ + int max_elide = min_t(long, HIST_ELISION, st->buckets); + int min_bucket = low_bucket; + int max_bucket = high_bucket; + + if (i - max_elide > min_bucket) + min_bucket = i - max_elide; + if (i + max_elide < max_bucket) + max_bucket = i + max_elide; + for (k = min_bucket; k <= max_bucket; k++) { + if (sd->histogram[k] != 0) + elide = 0; + } + if (elide) { + eliding = 1; + continue; + } + + /* State change: we have elided some rows, but now are + about to print a new one. So let's print a mark on + the vertical axis to represent the missing rows. */ + if (eliding) { + cur_buf += reprint_buf(cur_buf, buf + MAXSTRINGLEN - cur_buf, val_space, " "); + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, " ~\n"); + eliding = 0; + } + } + + if (st->type == HIST_LINEAR) { + if (i == 0) { + /* underflow */ + val = st->start; + over_under = 1; + } else if (i == st->buckets-1) { + /* overflow */ + val = st->start + (i - 2) * st->interval; + over_under = 1; + } else + val = st->start + (i - 1) * st->interval; + } else + val = _stp_bucket_to_val(i); + + cur_buf += reprint_buf(cur_buf, buf + MAXSTRINGLEN - cur_buf, val_space - needed_space(val) - over_under, " "); + + if (over_under) { + if (i == 0) + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, "<%lld", val); + else if (i == st->buckets-1) + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, ">%lld", val); + else + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, "%lld", val); + } else + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, "%lld", val); + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, " |"); + + /* v = s->histogram[i] / scale; */ + v = sd->histogram[i]; + do_div(v, scale); + + cur_buf += reprint_buf(cur_buf, buf + MAXSTRINGLEN - cur_buf, v, "@"); + cur_buf += reprint_buf(cur_buf, buf + MAXSTRINGLEN - cur_buf, HIST_WIDTH - v + 1 + cnt_space - needed_space(sd->histogram[i]), " "); + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, "%lld\n", sd->histogram[i]); + } + cur_buf += _stp_snprintf(cur_buf, buf + MAXSTRINGLEN - cur_buf, "\n"); +} + static void __stp_stat_add (Hist st, stat *sd, int64_t val) { int n; diff --git a/translate.cxx b/translate.cxx index a3246d9..5470190 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4142,8 +4142,18 @@ c_unparser::visit_print_format (print_format* e) o->newline() << "c->last_stmt = " << lex_cast_qstring(*e->tok) << ";"; o->newline() << "goto out;"; o->newline(-1) << "} else"; - o->newline(1) << "_stp_stat_print_histogram (" << v->hist() << ", " << agg.value() << ");"; - o->indent(-1); + if (e->print_to_stream) + { + o->newline(1) << "_stp_stat_print_histogram (" << v->hist() << ", " << agg.value() << ");"; + o->indent(-1); + } + else + { + exp_type ty = pe_string; + tmpvar res = gensym (ty); + o->newline(1) << "_stp_stat_print_histogram_buf (" << res.value() << ", " << v->hist() << ", " << agg.value() << ");"; + o->newline(-1) << res.value() << ";"; + } } delete v; -- 1.5.6.5