mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Irina Tirdea <irina.tirdea@gmail.com>
To: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>,
	Ingo Molnar <mingo@kernel.org>,
	Steven Rostedt <rostedt@goodmis.org>,
	Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: LKML <linux-kernel@vger.kernel.org>,
	Paul Mackerras <paulus@samba.org>,
	David Ahern <dsahern@gmail.com>,
	Namhyung Kim <namhyung@kernel.org>,
	Pekka Enberg <penberg@kernel.org>, Jiri Olsa <jolsa@redhat.com>,
	Irina Tirdea <irina.tirdea@intel.com>
Subject: [PATCH v2 1/1] perf stat: implement --big-num grouping
Date: Mon, 24 Sep 2012 00:48:13 +0300	[thread overview]
Message-ID: <1348436893-4307-1-git-send-email-irina.tirdea@gmail.com> (raw)
In-Reply-To: <1347574063-22521-3-git-send-email-irina.tirdea@intel.com>

From: Irina Tirdea <irina.tirdea@intel.com>

In glibc, printf supports ' to group numbers with thousands' grouping
characters. Bionic does not support ' for printf.

Implement thousands's grouping for numbers according to locale.
The implementation uses the algorithm from glibc
(http://www.gnu.org/software/libc/).

Bionic does not implement locales, so we need to add a configuration
option NO_LOCALE. If NO_LOCALE is defined, default values for thousands
separator and grouping are used.

Signed-off-by: Irina Tirdea <irina.tirdea@intel.com>
---

Changes in v2:
This is a rewrite of http://lkml.org/lkml/2012/9/13/574
Instead of disabling big num for Android, I added the implementation in perf
(as Ingo suggested).

 tools/perf/Makefile                 |    8 +++
 tools/perf/builtin-stat.c           |  112 ++++++++++++++++++++++++++++++++---
 tools/perf/config/feature-tests.mak |   18 ++++++
 3 files changed, 131 insertions(+), 7 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 5077f8e..74e21cf 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -769,6 +769,14 @@ else
        endif
 endif
 
+ifdef NO_LOCALE
+	BASIC_CFLAGS += -DNO_LOCALE
+else
+	ifneq ($(call try-cc,$(SOURCE_LOCALE),),y)
+		BASIC_CFLAGS += -DNO_LOCALE
+	endif
+endif
+
 ifdef ASCIIDOC8
 	export ASCIIDOC8
 endif
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e0f65fe..cb8b399 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -60,6 +60,8 @@
 #include <sys/prctl.h>
 #include <locale.h>
 
+/* max double number have E+308 + \0 + sign */
+#define MAX_NR_STR 310
 #define DEFAULT_SEPARATOR	" "
 #define CNTR_NOT_SUPPORTED	"<not supported>"
 #define CNTR_NOT_COUNTED	"<not counted>"
@@ -744,18 +746,112 @@ static void print_ll_cache_misses(int cpu,
 	fprintf(output, " of all LL-cache hits   ");
 }
 
+/* Group the digits according to the grouping rules of the current locale.
+   The interpretation of GROUPING is as in `struct lconv' from <locale.h>.  */
+static int group_number_locale(char *number, char **gnumber)
+{
+	const char *thousands_sep = NULL, *grouping = NULL;
+	int glen, tlen, dest_alloc_size, src_size, ret = 0, cnt;
+	char *dest_alloc_ptr, *dest_end, *src_start, *src_end;
+
+#ifdef NO_LOCALE
+	thousands_sep = ",";
+	grouping = "\x3";
+#else
+	struct lconv *lc = localeconv();
+	if (lc != NULL) {
+		thousands_sep = lc->thousands_sep;
+		grouping = lc->grouping;
+	}
+#endif
+
+	*gnumber = NULL;
+	/* No grouping */
+	if (thousands_sep == NULL || grouping == NULL ||
+	    *thousands_sep == '\0' || *grouping == CHAR_MAX || *grouping <= 0) {
+		*gnumber = strdup(number);
+		if (*gnumber == NULL)
+			ret = -ENOMEM;
+		goto out;
+	}
+
+	glen = *grouping++;
+	tlen = strlen(thousands_sep);
+
+	src_size = strlen(number);
+	/* Worst case scenario we have 1-character grouping */
+	dest_alloc_size = (src_size + src_size * tlen) * sizeof(char);
+	dest_alloc_ptr = zalloc(dest_alloc_size);
+	if (dest_alloc_ptr == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	/* -1 for '\0' */
+	dest_end = dest_alloc_ptr + dest_alloc_size - 1;
+
+	src_start = number;
+	src_end = number + src_size;
+
+	while (src_end > src_start) {
+		*--dest_end = *--src_end;
+		if (--glen == 0 && src_end > src_start) {
+			/* A new group */
+			cnt = tlen;
+			do
+				*--dest_end = thousands_sep[--cnt];
+			while (cnt > 0);
+
+			if (*grouping == CHAR_MAX || *grouping < 0) {
+				/* No further grouping to be done.
+				   Copy the rest of the number. */
+				do
+					*--dest_end = *--src_end;
+				while (src_end > src_start);
+				break;
+			} else if (*grouping != '\0') {
+				glen = *grouping++;
+			} else {
+				/* The previous grouping repeats ad infinitum */
+				glen = grouping[-1];
+			}
+		}
+	}
+
+	/* Make a copy with the exact needed size of the grouped number */
+	*gnumber = strdup(dest_end);
+	if (*gnumber == NULL) {
+		ret = -ENOMEM;
+		goto out_free_dest;
+	}
+
+	/* fall through */
+out_free_dest:
+	free(dest_alloc_ptr);
+out:
+	return ret;
+}
+
 static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
 {
 	double total, ratio = 0.0;
 	char cpustr[16] = { '\0', };
 	const char *fmt;
+	char avgstr[MAX_NR_STR], *pavgstr;
+	int ret;
 
-	if (csv_output)
-		fmt = "%s%.0f%s%s";
-	else if (big_num)
-		fmt = "%s%'18.0f%s%-25s";
-	else
-		fmt = "%s%18.0f%s%-25s";
+	sprintf(avgstr, "%.0f", avg);
+	pavgstr = avgstr;
+
+	if (csv_output) {
+		fmt = "%s%s%s%s";
+	} else {
+		fmt = "%s%18s%s%-25s";
+		if (big_num) {
+			ret = group_number_locale(avgstr, &pavgstr);
+			if (ret < 0)
+				pavgstr = avgstr;
+		}
+	}
 
 	if (no_aggr)
 		sprintf(cpustr, "CPU%*d%s",
@@ -764,7 +860,9 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
 	else
 		cpu = 0;
 
-	fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
+	fprintf(output, fmt, cpustr, pavgstr, csv_sep, perf_evsel__name(evsel));
+	if (pavgstr != avgstr)
+		free(pavgstr);
 
 	if (evsel->cgrp)
 		fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 116690a..7e5c005 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -193,3 +193,21 @@ int main(void)
 }
 endef
 endif
+
+ifndef NO_LOCALE
+define SOURCE_LOCALE
+#include <locale.h>
+
+int main(void)
+{
+	char *thousands_sep, *grouping;
+
+	struct lconv *lc = localeconv();
+	if (lc != NULL) {
+		thousands_sep = lc->thousands_sep;
+		grouping = lc->grouping;
+	}
+	return 0;
+}
+endef
+endif
-- 
1.7.9.5


  parent reply	other threads:[~2012-09-23 21:48 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-09-13 22:07 [PATCH 0/4] perf tools: runtime fixes for Android Irina Tirdea
2012-09-13 22:07 ` [PATCH 1/4] perf tools: remove sscanf extension %as Irina Tirdea
2012-09-14  1:54   ` Namhyung Kim
2012-09-19  3:20     ` Masami Hiramatsu
2012-09-20 19:13       ` Irina Tirdea
2012-09-20 20:37   ` [PATCH v2 1/1] " irina.tirdea
2012-09-21 15:29     ` Arnaldo Carvalho de Melo
2012-09-24  7:13     ` Masami Hiramatsu
2012-09-27  5:35     ` [tip:perf/core] " tip-bot for Irina Tirdea
2012-09-13 22:07 ` [PATCH 2/4] perf stat: add compile-time option to disable --big-num Irina Tirdea
2012-09-14  5:40   ` Ingo Molnar
2012-09-20 19:17     ` Irina Tirdea
2012-09-23 21:48   ` Irina Tirdea [this message]
2012-09-13 22:07 ` [PATCH 3/4] perf archive: remove -f from the rm command Irina Tirdea
2012-09-19 15:19   ` [tip:perf/core] perf archive: Remove " tip-bot for Irina Tirdea
2012-09-13 22:07 ` [PATCH 4/4] perf archive: make f the last parameter for tar Irina Tirdea
2012-09-19 15:20   ` [tip:perf/core] perf archive: Make 'f' " tip-bot for Irina Tirdea

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1348436893-4307-1-git-send-email-irina.tirdea@gmail.com \
    --to=irina.tirdea@gmail.com \
    --cc=a.p.zijlstra@chello.nl \
    --cc=acme@ghostprotocols.net \
    --cc=dsahern@gmail.com \
    --cc=irina.tirdea@intel.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=namhyung@kernel.org \
    --cc=paulus@samba.org \
    --cc=penberg@kernel.org \
    --cc=rostedt@goodmis.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome