This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH broken] PR10257: Add support for sprint[ln](@hist_*).


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]