|
From: openocd-gerrit <ope...@us...> - 2026-05-17 20:58:57
|
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Main OpenOCD repository".
The branch, master has been updated
via 8e87e2e026425f0f5bc5d2f7d541896fe5927c0b (commit)
from bad284fb653a78ad0daad5d1907f6e3d7eff4f06 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 8e87e2e026425f0f5bc5d2f7d541896fe5927c0b
Author: Richard Allen <rs...@gm...>
Date: Mon Feb 3 21:21:15 2025 -0600
target: multiple profiling histograms
Encode profiling data in multiple histograms.
This provides much smaller encoding for target
systems with sparse address maps.
Change-Id: I38276dd1be011ce5781b0264b7cbb09a3aa1a2b5
Signed-off-by: Richard Allen <rs...@gm...>
Reviewed-on: https://review.openocd.org/c/openocd/+/8739
Reviewed-by: Antonio Borneo <bor...@gm...>
Tested-by: jenkins
diff --git a/src/target/target.c b/src/target/target.c
index aa09cad08..4d8741238 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -4155,41 +4155,31 @@ static void write_string(FILE *f, char *s)
typedef unsigned char UNIT[2]; /* unit of profiling */
-/* Dump a gmon.out histogram file. */
-static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char *filename,
- struct target *target, uint32_t duration_ms)
+static void write_gmon_hist(FILE *f, const uint32_t *samples, uint32_t sample_num,
+ float sample_rate, struct target *target)
{
- FILE *f = fopen(filename, "wb");
- if (!f)
- return;
- write_string(f, "gmon");
- write_long(f, 0x00000001, target); /* Version */
- write_long(f, 0, target); /* padding */
- write_long(f, 0, target); /* padding */
- write_long(f, 0, target); /* padding */
-
- uint8_t zero = 0; /* GMON_TAG_TIME_HIST */
- write_data(f, &zero, 1);
-
- /* figure out bucket size */
uint32_t min = samples[0];
+ uint32_t max = samples[sample_num - 1];
+
/* max should be (largest sample + 1)
* Refer to binutils/gprof/hist.c (find_histogram_for_pc) */
- uint32_t max = samples[sample_num - 1] + 1;
+ max++;
+
+ /* The ratio ((double)((max - min) / 2) / num_buckets) must match across
+ * all histograms in this file. To avoid trunction in the /2, we must have
+ * an even length address space for compatibility with binutils <=2.44.
+ * Refer to binutils/gprof/hist.c (calculation of n_hist_scale)*/
+ if ((max - min) % 2)
+ max++;
uint32_t address_space = max - min;
- /* FIXME: What is the reasonable number of buckets?
- * The profiling result will be more accurate if there are enough buckets. */
- static const uint32_t max_buckets = 128 * 1024; /* maximum buckets. */
- uint32_t num_buckets = address_space / sizeof(UNIT);
- if (num_buckets > max_buckets)
- num_buckets = max_buckets;
+ uint8_t zero = 0; /* GMON_TAG_TIME_HIST */
+ write_data(f, &zero, 1);
/* append binary memory gmon.out &profile_hist_hdr ((char*)&profile_hist_hdr + sizeof(struct gmon_hist_hdr)) */
write_long(f, min, target); /* low_pc */
write_long(f, max, target); /* high_pc */
- write_long(f, num_buckets, target); /* # of buckets */
- float sample_rate = sample_num / (duration_ms / 1000.0);
+ write_long(f, address_space / sizeof(UNIT), target); /* # of buckets */
write_long(f, sample_rate, target);
write_string(f, "seconds");
for (size_t i = strlen("seconds"); i < 15; i++)
@@ -4198,12 +4188,13 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char
/*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */
bool saturated_once = false;
- for (uint32_t i = 0, bidx = 0; bidx < num_buckets; ++bidx) {
- long long bmax = min + (long long)address_space * (bidx + 1) / num_buckets;
+ for (uint32_t i = 0, bidx = 0; bidx < address_space; bidx += sizeof(UNIT)) {
uint32_t val = i;
- while (i < sample_num && samples[i] < bmax)
+ uint32_t bmax = min + bidx;
+ while (i < sample_num && samples[i] <= bmax)
++i;
val = i - val;
+
if (val > UINT16_MAX) {
val = UINT16_MAX;
if (!saturated_once)
@@ -4215,6 +4206,37 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char
h_u16_to_le(data, val);
write_data(f, data, 2);
}
+}
+
+/* Dump a gmon.out histogram file. */
+static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char *filename,
+ struct target *target, uint32_t duration_ms)
+{
+ float sample_rate = sample_num / (duration_ms / 1000.0);
+ FILE *f = fopen(filename, "wb");
+ if (!f)
+ return;
+ write_string(f, "gmon");
+ write_long(f, 0x00000001, target); /* Version */
+ write_long(f, 0, target); /* padding */
+ write_long(f, 0, target); /* padding */
+ write_long(f, 0, target); /* padding */
+
+ while (sample_num) {
+ /* if address gap exceeds this, make another histogram */
+ const uint32_t MAX_GAP = 32;
+
+ /* figure out bucket size */
+ uint32_t max = samples[0];
+ uint32_t this_pass = 1;
+ while (this_pass < sample_num && samples[this_pass] - max < MAX_GAP)
+ max = samples[this_pass++];
+
+ write_gmon_hist(f, samples, this_pass, sample_rate, target);
+
+ samples += this_pass;
+ sample_num -= this_pass;
+ }
fclose(f);
}
-----------------------------------------------------------------------
Summary of changes:
src/target/target.c | 78 ++++++++++++++++++++++++++++++++++-------------------
1 file changed, 50 insertions(+), 28 deletions(-)
hooks/post-receive
--
Main OpenOCD repository
|