llvm.org GIT mirror llvm / 29d9e6a
[pdb] Add -type-stats and sort stats by descending size Summary: It prints this on chromium browser_tests.exe.pdb: Types Total: 5647475 entries ( 371,897,512 bytes, 65.85 avg) -------------------------------------------------------------------------- LF_CLASS: 397894 entries ( 119,537,780 bytes, 300.43 avg) LF_STRUCTURE: 236351 entries ( 83,208,084 bytes, 352.05 avg) LF_FIELDLIST: 291003 entries ( 66,087,920 bytes, 227.10 avg) LF_MFUNCTION: 1884176 entries ( 52,756,928 bytes, 28.00 avg) LF_POINTER: 1149030 entries ( 13,877,344 bytes, 12.08 avg) LF_ARGLIST: 789980 entries ( 12,436,752 bytes, 15.74 avg) LF_METHODLIST: 361498 entries ( 8,351,008 bytes, 23.10 avg) LF_ENUM: 16069 entries ( 6,108,340 bytes, 380.13 avg) LF_PROCEDURE: 269374 entries ( 4,309,984 bytes, 16.00 avg) LF_MODIFIER: 235602 entries ( 2,827,224 bytes, 12.00 avg) LF_UNION: 9131 entries ( 2,072,168 bytes, 226.94 avg) LF_VFTABLE: 323 entries ( 207,784 bytes, 643.29 avg) LF_ARRAY: 6639 entries ( 106,380 bytes, 16.02 avg) LF_VTSHAPE: 126 entries ( 6,472 bytes, 51.37 avg) LF_BITFIELD: 278 entries ( 3,336 bytes, 12.00 avg) LF_LABEL: 1 entries ( 8 bytes, 8.00 avg) The PDB is overall 1.9GB, so the LF_CLASS and LF_STRUCTURE declarations account for about 10% of the overall file size. I was surprised to find that on average LF_FIELDLIST records are short. Maybe this is because there are many more types with short member lists than there are instantiations with lots of members, like std::vector. Reviewers: aganea, zturner Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D59672 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@356813 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 5 months ago
7 changed file(s) with 117 addition(s) and 31 deletion(s). Raw diff Collapse all Expand all
55 ALL: Symbols
66 ALL-NEXT: Total: 6 entries ( 204 bytes)
77 ALL-NEXT: --------------------------------------------------------------------------
8 ALL-NEXT: S_COMPILE3: 1 entries ( 60 bytes)
9 ALL-NEXT: S_OBJNAME: 1 entries ( 56 bytes)
810 ALL-NEXT: S_GPROC32: 1 entries ( 44 bytes)
911 ALL-NEXT: S_FRAMEPROC: 1 entries ( 32 bytes)
12 ALL-NEXT: S_BUILDINFO: 1 entries ( 8 bytes)
1013 ALL-NEXT: S_END: 1 entries ( 4 bytes)
11 ALL-NEXT: S_OBJNAME: 1 entries ( 56 bytes)
12 ALL-NEXT: S_COMPILE3: 1 entries ( 60 bytes)
13 ALL-NEXT: S_BUILDINFO: 1 entries ( 8 bytes)
1414 ALL: Chunks
1515 ALL-NEXT: Total: 2 entries ( 88 bytes)
1616 ALL-NEXT: --------------------------------------------------------------------------
17 ALL-NEXT: DEBUG_S_LINES: 1 entries ( 56 bytes)
1718 ALL-NEXT: DEBUG_S_FILECHKSMS: 1 entries ( 32 bytes)
18 ALL-NEXT: DEBUG_S_LINES: 1 entries ( 56 bytes)
1919 ALL-NEXT: Mod 0001 | `* Linker *`:
2020 ALL-NEXT: Stream 14, 520 bytes
2121 ALL: Symbols
2222 ALL-NEXT: Total: 13 entries ( 512 bytes)
2323 ALL-NEXT: --------------------------------------------------------------------------
24 ALL-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
25 ALL-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
2426 ALL-NEXT: S_SECTION: 4 entries ( 112 bytes)
25 ALL-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
27 ALL-NEXT: S_COMPILE3: 1 entries ( 48 bytes)
2628 ALL-NEXT: S_TRAMPOLINE: 1 entries ( 20 bytes)
2729 ALL-NEXT: S_OBJNAME: 1 entries ( 20 bytes)
28 ALL-NEXT: S_COMPILE3: 1 entries ( 48 bytes)
29 ALL-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
3030 ALL: Chunks
3131 ALL-NEXT: Total: 0 entries ( 0 bytes)
3232 ALL-NEXT: --------------------------------------------------------------------------
3434 ALL: Symbols
3535 ALL-NEXT: Total: 19 entries ( 716 bytes)
3636 ALL-NEXT: --------------------------------------------------------------------------
37 ALL-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
38 ALL-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
3739 ALL-NEXT: S_SECTION: 4 entries ( 112 bytes)
40 ALL-NEXT: S_COMPILE3: 2 entries ( 108 bytes)
41 ALL-NEXT: S_OBJNAME: 2 entries ( 76 bytes)
3842 ALL-NEXT: S_GPROC32: 1 entries ( 44 bytes)
39 ALL-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
4043 ALL-NEXT: S_FRAMEPROC: 1 entries ( 32 bytes)
4144 ALL-NEXT: S_TRAMPOLINE: 1 entries ( 20 bytes)
45 ALL-NEXT: S_BUILDINFO: 1 entries ( 8 bytes)
4246 ALL-NEXT: S_END: 1 entries ( 4 bytes)
43 ALL-NEXT: S_OBJNAME: 2 entries ( 76 bytes)
44 ALL-NEXT: S_COMPILE3: 2 entries ( 108 bytes)
45 ALL-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
46 ALL-NEXT: S_BUILDINFO: 1 entries ( 8 bytes)
4747 ALL: Chunks
4848 ALL-NEXT: Total: 2 entries ( 88 bytes)
4949 ALL-NEXT: --------------------------------------------------------------------------
50 ALL-NEXT: DEBUG_S_LINES: 1 entries ( 56 bytes)
5051 ALL-NEXT: DEBUG_S_FILECHKSMS: 1 entries ( 32 bytes)
51 ALL-NEXT: DEBUG_S_LINES: 1 entries ( 56 bytes)
5252
5353 ONE-NOT: Mod 0000
5454 ONE: Mod 0001 | `* Linker *`:
5656 ONE: Symbols
5757 ONE-NEXT: Total: 13 entries ( 512 bytes)
5858 ONE-NEXT: --------------------------------------------------------------------------
59 ONE-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
60 ONE-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
5961 ONE-NEXT: S_SECTION: 4 entries ( 112 bytes)
60 ONE-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
62 ONE-NEXT: S_COMPILE3: 1 entries ( 48 bytes)
6163 ONE-NEXT: S_TRAMPOLINE: 1 entries ( 20 bytes)
6264 ONE-NEXT: S_OBJNAME: 1 entries ( 20 bytes)
63 ONE-NEXT: S_COMPILE3: 1 entries ( 48 bytes)
64 ONE-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
6565 ONE: Chunks
6666 ONE-NEXT: Total: 0 entries ( 0 bytes)
6767 ONE-NEXT: --------------------------------------------------------------------------
6969 ONE: Symbols
7070 ONE-NEXT: Total: 13 entries ( 512 bytes)
7171 ONE-NEXT: --------------------------------------------------------------------------
72 ONE-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
73 ONE-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
7274 ONE-NEXT: S_SECTION: 4 entries ( 112 bytes)
73 ONE-NEXT: S_ENVBLOCK: 1 entries ( 172 bytes)
75 ONE-NEXT: S_COMPILE3: 1 entries ( 48 bytes)
7476 ONE-NEXT: S_TRAMPOLINE: 1 entries ( 20 bytes)
7577 ONE-NEXT: S_OBJNAME: 1 entries ( 20 bytes)
76 ONE-NEXT: S_COMPILE3: 1 entries ( 48 bytes)
77 ONE-NEXT: S_COFFGROUP: 5 entries ( 140 bytes)
7878 ONE: Chunks
7979 ONE-NEXT: Total: 0 entries ( 0 bytes)
8080 ONE-NEXT: --------------------------------------------------------------------------
0 ; RUN: llvm-pdbutil dump -type-stats %p/Inputs/empty.pdb | FileCheck --check-prefix=ALL %s
1
2 ALL: Type Record Stats
3 ALL-NEXT: ============================================================
4
5 ALL: Types
6 ALL-NEXT: Total: 75 entries ( 5,336 bytes, 71.15 avg)
7 ALL-NEXT: --------------------------------------------------------------------------
8 ALL-NEXT: LF_FIELDLIST: 14 entries ( 1,956 bytes, 139.71 avg)
9 ALL-NEXT: LF_STRUCTURE: 14 entries ( 1,584 bytes, 113.14 avg)
10 ALL-NEXT: LF_ENUM: 8 entries ( 988 bytes, 123.50 avg)
11 ALL-NEXT: LF_MFUNCTION: 14 entries ( 392 bytes, 28.00 avg)
12 ALL-NEXT: LF_ARGLIST: 10 entries ( 176 bytes, 17.60 avg)
13 ALL-NEXT: LF_METHODLIST: 5 entries ( 116 bytes, 23.20 avg)
14 ALL-NEXT: LF_POINTER: 8 entries ( 96 bytes, 12.00 avg)
15 ALL-NEXT: LF_PROCEDURE: 1 entries ( 16 bytes, 16.00 avg)
16 ALL-NEXT: LF_MODIFIER: 1 entries ( 12 bytes, 12.00 avg)
33 CHECK-NEXT: ============================================================
44 CHECK: Record Kind | Count Size
55 CHECK-NEXT: -----------------------------
6 CHECK-NEXT: LF_STRUCTURE | 27 1,788
7 CHECK-NEXT: LF_POINTER | 39 468
68 CHECK-NEXT: LF_ENUM | 3 188
7 CHECK-NEXT: LF_POINTER | 39 468
89 CHECK-NEXT: LF_UNION | 1 52
10 CHECK-NEXT: LF_PROCEDURE | 1 16
911 CHECK-NEXT: | 43 0
10 CHECK-NEXT: LF_PROCEDURE | 1 16
11 CHECK-NEXT: LF_STRUCTURE | 27 1,788
1212 CHECK-NEXT: -----------------------------
1313 CHECK-NEXT: Total (S_UDT) | 114 2,604
1414 CHECK-NEXT: -----------------------------
109109 P.NewLine();
110110 }
111111
112 if (opts::dump::DumpTypeStats) {
113 if (auto EC = dumpTypeStats())
114 return EC;
115 P.NewLine();
116 }
117
112118 if (opts::dump::DumpNamedStreams) {
113119 if (auto EC = dumpNamedStreams())
114120 return EC;
306312 return formatSymbolKind(K);
307313 }
308314
315 // Get the stats sorted by size, descending.
316 std::vector
317 StatCollection::getStatsSortedBySize() const {
318 std::vector SortedStats(Individual.begin(), Individual.end());
319 std::stable_sort(SortedStats.begin(), SortedStats.end(),
320 [](const KindAndStat &LHS, const KindAndStat &RHS) {
321 return LHS.second.Size > RHS.second.Size;
322 });
323 return SortedStats;
324 }
325
309326 template
310327 static void printModuleDetailStats(LinePrinter &P, StringRef Label,
311328 const StatCollection &Stats) {
312329 P.NewLine();
313330 P.formatLine(" {0}", Label);
314331 AutoIndent Indent(P);
315 P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", "Total",
332 P.formatLine("{0,40}: {1,7} entries ({2,12:N} bytes)", "Total",
316333 Stats.Totals.Count, Stats.Totals.Size);
317334 P.formatLine("{0}", fmt_repeat('-', 74));
318 for (const auto &K : Stats.Individual) {
335
336 for (const auto &K : Stats.getStatsSortedBySize()) {
319337 std::string KindName = formatModuleDetailKind(Kind(K.first));
320 P.formatLine("{0,40}: {1,7} entries ({2,8} bytes)", KindName,
338 P.formatLine("{0,40}: {1,7} entries ({2,12:N} bytes)", KindName,
321339 K.second.Count, K.second.Size);
322340 }
323341 }
675693 return Error::success();
676694 }
677695
696 Error DumpOutputStyle::dumpTypeStats() {
697 printHeader(P, "Type Record Stats");
698
699 // Iterate the types, categorize by kind, accumulate size stats.
700 StatCollection TypeStats;
701 LazyRandomTypeCollection &Types = File.types();
702 for (Optional TI = Types.getFirst(); TI; TI = Types.getNext(*TI)) {
703 CVType Type = Types.getType(*TI);
704 TypeStats.update(uint32_t(Type.kind()), Type.length());
705 }
706
707 P.NewLine();
708 P.formatLine(" Types");
709 AutoIndent Indent(P);
710 P.formatLine("{0,14}: {1,7} entries ({2,12:N} bytes, {3,7} avg)", "Total",
711 TypeStats.Totals.Count, TypeStats.Totals.Size,
712 (double)TypeStats.Totals.Size / TypeStats.Totals.Count);
713 P.formatLine("{0}", fmt_repeat('-', 74));
714
715 for (const auto &K : TypeStats.getStatsSortedBySize()) {
716 P.formatLine("{0,14}: {1,7} entries ({2,12:N} bytes, {3,7} avg)",
717 formatTypeLeafKind(TypeLeafKind(K.first)), K.second.Count,
718 K.second.Size, (double)K.second.Size / K.second.Count);
719 }
720
721
722 return Error::success();
723 }
724
678725 static bool isValidNamespaceIdentifier(StringRef S) {
679726 if (S.empty())
680727 return false;
819866 fmt_align(SizeHeader, AlignStyle::Right, SD));
820867
821868 P.formatLine("{0}", fmt_repeat('-', TableWidth));
822 for (const auto &Stat : UdtTargetStats.Individual) {
869 for (const auto &Stat : UdtTargetStats.getStatsSortedBySize()) {
823870 StringRef Label = getUdtStatLabel(Stat.first);
824871 P.formatLine("{0} | {1:N} {2:N}",
825872 fmt_align(Label, AlignStyle::Right, FieldWidth),
832879 fmt_align(UdtStats.Totals.Count, AlignStyle::Right, CD),
833880 fmt_align(UdtStats.Totals.Size, AlignStyle::Right, SD));
834881 P.formatLine("{0}", fmt_repeat('-', TableWidth));
835 for (const auto &Stat : NamespacedStats) {
836 std::string Label = formatv("namespace '{0}'", Stat.getKey());
882 struct StrAndStat {
883 StringRef Key;
884 StatCollection::Stat Stat;
885 };
886
887 // Print namespace stats in descending order of size.
888 std::vector NamespacedStatsSorted;
889 for (const auto &Stat : NamespacedStats)
890 NamespacedStatsSorted.push_back({Stat.getKey(), Stat.second});
891 std::stable_sort(NamespacedStatsSorted.begin(), NamespacedStatsSorted.end(),
892 [](const StrAndStat &L, const StrAndStat &R) {
893 return L.Stat.Size > R.Stat.Size;
894 });
895 for (const auto &Stat : NamespacedStatsSorted) {
896 std::string Label = formatv("namespace '{0}'", Stat.Key);
837897 P.formatLine("{0} | {1:N} {2:N}",
838898 fmt_align(Label, AlignStyle::Right, FieldWidth),
839 fmt_align(Stat.second.Count, AlignStyle::Right, CD),
840 fmt_align(Stat.second.Size, AlignStyle::Right, SD));
899 fmt_align(Stat.Stat.Count, AlignStyle::Right, CD),
900 fmt_align(Stat.Stat.Size, AlignStyle::Right, SD));
841901 }
842902 return Error::success();
843903 }
4848 }
4949 };
5050
51 using KindAndStat = std::pair;
52
5153 void update(uint32_t Kind, uint32_t RecordSize) {
5254 Totals.update(RecordSize);
5355 auto Iter = Individual.try_emplace(Kind, 1, RecordSize);
5658 }
5759 Stat Totals;
5860 DenseMap Individual;
61
62 std::vector getStatsSortedBySize() const;
5963 };
6064
6165 class DumpOutputStyle : public OutputStyle {
7781 Error dumpStreamSummary();
7882 Error dumpSymbolStats();
7983 Error dumpUdtStats();
84 Error dumpTypeStats();
8085 Error dumpNamedStreams();
8186 Error dumpStringTable();
8287 Error dumpStringTableFromPdb();
461461 "sym-stats",
462462 cl::desc("Dump a detailed breakdown of symbol usage/size for each module"),
463463 cl::cat(MsfOptions), cl::sub(DumpSubcommand));
464
464 cl::opt DumpTypeStats(
465 "type-stats",
466 cl::desc("Dump a detailed breakdown of type usage/size"),
467 cl::cat(MsfOptions), cl::sub(DumpSubcommand));
465468 cl::opt DumpUdtStats(
466469 "udt-stats",
467470 cl::desc("Dump a detailed breakdown of S_UDT record usage / stats"),
139139 extern llvm::cl::opt DumpFpm;
140140 extern llvm::cl::opt DumpStreams;
141141 extern llvm::cl::opt DumpSymbolStats;
142 extern llvm::cl::opt DumpTypeStats;
142143 extern llvm::cl::opt DumpUdtStats;
143144 extern llvm::cl::opt DumpStreamBlocks;
144145