This is an automated email from Gerrit. "Richard Allen <rsa...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8739
-- gerrit commit 7dd7db6b6d31173a5fcd6125711f34e45d8d97d6 Author: Richard Allen <rsa...@gmail.com> 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 <rsa...@gmail.com> diff --git a/src/target/target.c b/src/target/target.c index f47d061903..9db32f8b63 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4210,13 +4210,13 @@ typedef unsigned char UNIT[2]; /* unit of profiling */ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char *filename, struct target *target, uint32_t duration_ms) { - uint32_t i; - if (!sample_num) { LOG_WARNING("no samples to write"); return; } + float sample_rate = sample_num / (duration_ms / 1000.0); + FILE *f = fopen(filename, "wb"); if (!f) return; @@ -4226,47 +4226,49 @@ static void write_gmon(const uint32_t *samples, uint32_t sample_num, const char 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]; - /* max should be (largest sample + 1) - * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ - uint32_t max = samples[sample_num-1] + 1; - 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; - - /* 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, sample_rate, target); - write_string(f, "seconds"); - for (i = 0; i < (15-strlen("seconds")); i++) + while (sample_num) { + /* figure out bucket size */ + uint32_t min = samples[0]; + uint32_t max = samples[0]; + uint32_t this_pass = 1; + while (this_pass < sample_num && samples[this_pass] - max < 32) { + max = samples[this_pass++]; + } + + /* max should be (largest sample + 1) + * Refer to binutils/gprof/hist.c (find_histogram_for_pc) */ + max++; + uint32_t address_space = max - min; + + uint8_t zero = 0; /* GMON_TAG_TIME_HIST */ write_data(f, &zero, 1); - write_string(f, "s"); - - /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ - uint32_t bidx; - for (i = 0, bidx = 0; bidx < num_buckets; ++bidx) { - int val = 0; - long long bmax = min + (long long)address_space * (bidx + 1) / num_buckets; - for ( ; i < sample_num && samples[i] < bmax; ++i) - if (val < 65535) - val++; - - uint8_t data[2]; - data[0] = val & 0xff; - data[1] = (val >> 8) & 0xff; - write_data(f, data, 2); + + /* 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, address_space, target); /* # of buckets */ + write_long(f, sample_rate, target); + write_string(f, "seconds"); + for (uint32_t i = 0; i < (15-strlen("seconds")); i++) + write_data(f, &zero, 1); + write_string(f, "s"); + + /*append binary memory gmon.out profile_hist_data (profile_hist_data + profile_hist_hdr.hist_size) */ + for (uint32_t i = 0, bidx = 0; bidx < address_space; ++bidx) { + int val = 0; + long long bmax = min + bidx; + for ( ; i < this_pass && samples[i] <= bmax; ++i) + if (val < 65535) + val++; + + uint8_t data[2]; + data[0] = val & 0xff; + data[1] = (val >> 8) & 0xff; + write_data(f, data, 2); + } + + samples += this_pass; + sample_num -= this_pass; } fclose(f); --