Merge branch 'master' of https://github.com/google/bloaty
diff --git a/src/bloaty.cc b/src/bloaty.cc
index 017a25c..068de28 100644
--- a/src/bloaty.cc
+++ b/src/bloaty.cc
@@ -1493,6 +1493,10 @@
}
void ComputeRollup(Rollup* rollup) {
+ for (auto& map : maps_) {
+ map->vm_map.Compress();
+ map->file_map.Compress();
+ }
RangeMap::ComputeRollup(VmMaps(), [=](const std::vector<std::string>& keys,
uint64_t addr, uint64_t end) {
return rollup->AddSizes(keys, end - addr, true);
@@ -1506,14 +1510,17 @@
void PrintMaps(const std::vector<const RangeMap*> maps) {
uint64_t last = 0;
+ uint64_t max = maps[0]->GetMaxAddress();
+ int hex_digits = std::ceil(std::log2(max) / 4);
RangeMap::ComputeRollup(maps, [&](const std::vector<std::string>& keys,
uint64_t addr, uint64_t end) {
if (addr > last) {
- PrintMapRow("NO ENTRY", last, addr);
+ PrintMapRow("[-- Nothing mapped --]", last, addr, hex_digits);
}
- PrintMapRow(KeysToString(keys), addr, end);
+ PrintMapRow(KeysToString(keys), addr, end, hex_digits);
last = end;
});
+ printf("\n");
}
void PrintFileMaps() { PrintMaps(FileMaps()); }
@@ -1522,9 +1529,10 @@
std::string KeysToString(const std::vector<std::string>& keys) {
std::string ret;
- for (size_t i = 0; i < keys.size(); i++) {
- if (i > 0) {
- ret += ", ";
+ // Start at offset 1 to skip the base map.
+ for (size_t i = 1; i < keys.size(); i++) {
+ if (i > 1) {
+ ret += "\t";
}
ret += keys[i];
}
@@ -1532,9 +1540,10 @@
return ret;
}
- void PrintMapRow(string_view str, uint64_t start, uint64_t end) {
- printf("[%" PRIx64 ", %" PRIx64 "] %.*s\n", start, end, (int)str.size(),
- str.data());
+ void PrintMapRow(string_view str, uint64_t start, uint64_t end, int hex_digits) {
+ printf("%.*" PRIx64 "-%.*" PRIx64 "\t %s\t\t%.*s\n", hex_digits, start,
+ hex_digits, end, LeftPad(std::to_string(end - start), 10).c_str(),
+ (int)str.size(), str.data());
}
DualMap* base_map() { return maps_[0].get(); }
diff --git a/src/range_map.cc b/src/range_map.cc
index 29b0af7..2886bd7 100644
--- a/src/range_map.cc
+++ b/src/range_map.cc
@@ -288,6 +288,21 @@
return total_size == size;
}
+void RangeMap::Compress() {
+ auto prev = mappings_.begin();
+ auto it = prev;
+ while (it != mappings_.end()) {
+ if (prev->first + prev->second.size == it->first &&
+ prev->second.label == it->second.label) {
+ prev->second.size += it->second.size;
+ mappings_.erase(it++);
+ } else {
+ prev = it;
+ ++it;
+ }
+ }
+}
+
bool RangeMap::CoversRange(uint64_t addr, uint64_t size) const {
auto it = FindContaining(addr);
uint64_t end = addr + size;
@@ -304,4 +319,13 @@
}
}
+uint64_t RangeMap::GetMaxAddress() const {
+ if (mappings_.empty()) {
+ return 0;
+ } else {
+ auto& entry = *mappings_.rbegin();
+ return entry.first + entry.second.size;
+ }
+}
+
} // namespace bloaty
diff --git a/src/range_map.h b/src/range_map.h
index 9faa9e8..05a8edd 100644
--- a/src/range_map.h
+++ b/src/range_map.h
@@ -74,9 +74,21 @@
const RangeMap& translator, bool verbose,
RangeMap* other);
+ // Collapses adjacent ranges with the same label. This reduces memory usage
+ // and removes redundant noise from the output when dumping a full memory map
+ // (in normal Bloaty output it makes no difference, because all labels with
+ // the same name are added together).
+ //
+ // TODO(haberman): see if we can do this at insertion time instead, so it
+ // doesn't require a second pass.
+ void Compress();
+
// Returns whether this RangeMap fully covers the given range.
bool CoversRange(uint64_t addr, uint64_t size) const;
+ // Returns the maximum address contained in this map.
+ uint64_t GetMaxAddress() const;
+
// Translates |addr| into the other domain, returning |true| if this was
// successful.
bool Translate(uint64_t addr, uint64_t *translated) const;