Add new key/value pairs to the module statistics for "statistics dump".
authorGreg Clayton <gclayton@fb.com>
Tue, 26 Oct 2021 01:03:06 +0000 (18:03 -0700)
committerGreg Clayton <gclayton@fb.com>
Tue, 26 Oct 2021 22:09:31 +0000 (15:09 -0700)
The new key/value pairs that are added to each module's stats are:
"debugInfoByteSize": The size in bytes of debug info for each module.
"debugInfoIndexTime": The time in seconds that it took to index the debug info.
"debugInfoParseTime": The time in seconds that debug info had to be parsed.

At the top level we add up all of the debug info size, parse time and index time with the following keys:
"totalDebugInfoByteSize": The size in bytes of all debug info in all modules.
"totalDebugInfoIndexTime": The time in seconds that it took to index all debug info if it was indexed for all modules.
"totalDebugInfoParseTime": The time in seconds that debug info was parsed for all modules.

Differential Revision: https://reviews.llvm.org/D112501

18 files changed:
lldb/include/lldb/Core/Section.h
lldb/include/lldb/Symbol/SymbolFile.h
lldb/include/lldb/Target/Statistics.h
lldb/source/Core/Section.cpp
lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.cpp
lldb/source/Plugins/SymbolFile/Breakpad/SymbolFileBreakpad.h
lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
lldb/source/Symbol/SymbolFile.cpp
lldb/source/Target/Statistics.cpp
lldb/test/API/commands/statistics/basic/TestStats.py

index 3d4ab15..8a9fea3 100644 (file)
@@ -89,6 +89,12 @@ public:
 
   void Clear() { m_sections.clear(); }
 
+  /// Get the debug information size from all sections that contain debug
+  /// information. Symbol tables are not considered part of the debug
+  /// information for this call, just known sections that contain debug
+  /// information.
+  uint64_t GetDebugInfoSize() const;
+
 protected:
   collection m_sections;
 };
@@ -236,6 +242,13 @@ public:
 
   void SetIsRelocated(bool b) { m_relocated = b; }
 
+  /// Returns true if this section contains debug information. Symbol tables
+  /// are not considered debug information since some symbols might contain
+  /// debug information (STABS, COFF) but not all symbols do, so to keep this
+  /// fast and simple only sections that contains only debug information should
+  /// return true.
+  bool ContainsOnlyDebugInfo() const;
+
 protected:
   ObjectFile *m_obj_file;   // The object file that data for this section should
                             // be read from
index ffdbdc6..9ab63ca 100644 (file)
@@ -19,6 +19,7 @@
 #include "lldb/Symbol/Type.h"
 #include "lldb/Symbol/TypeList.h"
 #include "lldb/Symbol/TypeSystem.h"
+#include "lldb/Target/Statistics.h"
 #include "lldb/Utility/XcodeSDK.h"
 #include "lldb/lldb-private.h"
 #include "llvm/ADT/DenseSet.h"
@@ -299,6 +300,38 @@ public:
 
   virtual void Dump(Stream &s);
 
+  /// Metrics gathering functions
+
+  /// Return the size in bytes of all debug information in the symbol file.
+  ///
+  /// If the debug information is contained in sections of an ObjectFile, then
+  /// this call should add the size of all sections that contain debug
+  /// information. Symbols the symbol tables are not considered debug
+  /// information for this call to make it easy and quick for this number to be
+  /// calculated. If the symbol file is all debug information, the size of the
+  /// entire file should be returned. The default implementation of this
+  /// function will iterate over all sections in a module and add up their
+  /// debug info only section byte sizes.
+  virtual uint64_t GetDebugInfoSize();
+
+  /// Return the time taken to parse the debug information.
+  ///
+  /// \returns 0.0 if no information has been parsed or if there is
+  /// no computational cost to parsing the debug information.
+  virtual StatsDuration GetDebugInfoParseTime() {
+    return StatsDuration(0.0);
+  }
+
+  /// Return the time it took to index the debug information in the object
+  /// file.
+  ///
+  /// \returns 0.0 if the file doesn't need to be indexed or if it
+  /// hasn't been indexed yet, or a valid duration if it has.
+  virtual StatsDuration GetDebugInfoIndexTime() {
+    return StatsDuration(0.0);
+  }
+
+
 protected:
   void AssertModuleLock();
   virtual uint32_t CalculateNumCompileUnits() = 0;
index 6bfc7a9..087fbee 100644 (file)
@@ -81,6 +81,9 @@ struct ModuleStats {
   std::string triple;
   double symtab_parse_time = 0.0;
   double symtab_index_time = 0.0;
+  double debug_parse_time = 0.0;
+  double debug_index_time = 0.0;
+  uint64_t debug_info_size = 0;
 };
 
 /// A class that represents statistics for a since lldb_private::Target.
index a5a1014..1660e3c 100644 (file)
@@ -396,6 +396,76 @@ lldb::offset_t Section::GetSectionData(DataExtractor &section_data) {
   return 0;
 }
 
+bool Section::ContainsOnlyDebugInfo() const {
+  switch (m_type) {
+  case eSectionTypeInvalid:
+  case eSectionTypeCode:
+  case eSectionTypeContainer:
+  case eSectionTypeData:
+  case eSectionTypeDataCString:
+  case eSectionTypeDataCStringPointers:
+  case eSectionTypeDataSymbolAddress:
+  case eSectionTypeData4:
+  case eSectionTypeData8:
+  case eSectionTypeData16:
+  case eSectionTypeDataPointers:
+  case eSectionTypeZeroFill:
+  case eSectionTypeDataObjCMessageRefs:
+  case eSectionTypeDataObjCCFStrings:
+  case eSectionTypeELFSymbolTable:
+  case eSectionTypeELFDynamicSymbols:
+  case eSectionTypeELFRelocationEntries:
+  case eSectionTypeELFDynamicLinkInfo:
+  case eSectionTypeEHFrame:
+  case eSectionTypeARMexidx:
+  case eSectionTypeARMextab:
+  case eSectionTypeCompactUnwind:
+  case eSectionTypeGoSymtab:
+  case eSectionTypeAbsoluteAddress:
+  case eSectionTypeOther:
+    return false;
+
+  case eSectionTypeDebug:
+  case eSectionTypeDWARFDebugAbbrev:
+  case eSectionTypeDWARFDebugAbbrevDwo:
+  case eSectionTypeDWARFDebugAddr:
+  case eSectionTypeDWARFDebugAranges:
+  case eSectionTypeDWARFDebugCuIndex:
+  case eSectionTypeDWARFDebugTuIndex:
+  case eSectionTypeDWARFDebugFrame:
+  case eSectionTypeDWARFDebugInfo:
+  case eSectionTypeDWARFDebugInfoDwo:
+  case eSectionTypeDWARFDebugLine:
+  case eSectionTypeDWARFDebugLineStr:
+  case eSectionTypeDWARFDebugLoc:
+  case eSectionTypeDWARFDebugLocDwo:
+  case eSectionTypeDWARFDebugLocLists:
+  case eSectionTypeDWARFDebugLocListsDwo:
+  case eSectionTypeDWARFDebugMacInfo:
+  case eSectionTypeDWARFDebugMacro:
+  case eSectionTypeDWARFDebugPubNames:
+  case eSectionTypeDWARFDebugPubTypes:
+  case eSectionTypeDWARFDebugRanges:
+  case eSectionTypeDWARFDebugRngLists:
+  case eSectionTypeDWARFDebugRngListsDwo:
+  case eSectionTypeDWARFDebugStr:
+  case eSectionTypeDWARFDebugStrDwo:
+  case eSectionTypeDWARFDebugStrOffsets:
+  case eSectionTypeDWARFDebugStrOffsetsDwo:
+  case eSectionTypeDWARFDebugTypes:
+  case eSectionTypeDWARFDebugTypesDwo:
+  case eSectionTypeDWARFDebugNames:
+  case eSectionTypeDWARFAppleNames:
+  case eSectionTypeDWARFAppleTypes:
+  case eSectionTypeDWARFAppleNamespaces:
+  case eSectionTypeDWARFAppleObjC:
+  case eSectionTypeDWARFGNUDebugAltLink:
+    return true;
+  }
+  return false;
+}
+
+
 #pragma mark SectionList
 
 SectionList &SectionList::operator=(const SectionList &rhs) {
@@ -599,3 +669,15 @@ size_t SectionList::Slide(addr_t slide_amount, bool slide_children) {
   }
   return count;
 }
+
+uint64_t SectionList::GetDebugInfoSize() const {
+  uint64_t debug_info_size = 0;
+  for (const auto &section : m_sections) {
+    const SectionList &sub_sections = section->GetChildren();
+    if (sub_sections.GetSize() > 0)
+      debug_info_size += sub_sections.GetDebugInfoSize();
+    else if (section->ContainsOnlyDebugInfo())
+      debug_info_size += section->GetFileSize();
+  }
+  return debug_info_size;
+}
index b815ebb..243af5e 100644 (file)
@@ -783,3 +783,9 @@ void SymbolFileBreakpad::ParseUnwindData() {
   }
   m_unwind_data->win.Sort();
 }
+
+uint64_t SymbolFileBreakpad::GetDebugInfoSize() {
+  // Breakpad files are all debug info.
+  return m_objfile_sp->GetByteSize();
+}
+
index 1013f6e..36ce536 100644 (file)
@@ -150,6 +150,8 @@ public:
     return GetPluginNameStatic().GetStringRef();
   }
 
+  uint64_t GetDebugInfoSize() override;
+
 private:
   // A class representing a position in the breakpad file. Useful for
   // remembering the position so we can go back to it later and parse more data.
index fac6c46..1d3d70d 100644 (file)
@@ -13,6 +13,8 @@
 #include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
 #include "Plugins/SymbolFile/DWARF/DWARFFormValue.h"
 
+#include "lldb/Target/Statistics.h"
+
 class DWARFDeclContext;
 class DWARFDIE;
 
@@ -62,8 +64,11 @@ public:
 
   virtual void Dump(Stream &s) = 0;
 
+  StatsDuration GetIndexTime() { return m_index_time; }
+
 protected:
   Module &m_module;
+  StatsDuration m_index_time{0.0};
 
   /// Helper function implementing common logic for processing function dies. If
   /// the function given by "ref" matches search criteria given by
index 0eafd62..5487f70 100644 (file)
@@ -49,6 +49,7 @@ void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() {
   if (m_first_die)
     return; // Already parsed
 
+  ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef());
   LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()",
                      GetOffset());
 
@@ -196,6 +197,7 @@ DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=(
 void DWARFUnit::ExtractDIEsRWLocked() {
   llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex);
 
+  ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef());
   LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset());
 
   // Set the offset to that of the first DIE and calculate the start of the
index 4d36ef9..ab10e9c 100644 (file)
@@ -30,6 +30,7 @@ void ManualDWARFIndex::Index() {
   SymbolFileDWARF &main_dwarf = *m_dwarf;
   m_dwarf = nullptr;
 
+  ElapsedTime elapsed(m_index_time);
   LLDB_SCOPED_TIMERF("%p", static_cast<void *>(&main_dwarf));
 
   DWARFDebugInfo &main_info = main_dwarf.DebugInfo();
index f871539..21f52f0 100644 (file)
@@ -1009,6 +1009,7 @@ bool SymbolFileDWARF::ParseSupportFiles(DWARFUnit &dwarf_cu,
   if (offset == DW_INVALID_OFFSET)
     return false;
 
+  ElapsedTime elapsed(m_parse_time);
   llvm::DWARFDebugLine::Prologue prologue;
   if (!ParseLLVMLineTablePrologue(m_context, prologue, offset,
                                   dwarf_cu.GetOffset()))
@@ -1057,6 +1058,7 @@ SymbolFileDWARF::GetTypeUnitSupportFiles(DWARFTypeUnit &tu) {
                      "SymbolFileDWARF::GetTypeUnitSupportFiles failed to parse "
                      "the line table prologue");
     };
+    ElapsedTime elapsed(m_parse_time);
     llvm::Error error = prologue.parse(data, &line_table_offset, report, ctx);
     if (error) {
       report(std::move(error));
@@ -1143,6 +1145,7 @@ bool SymbolFileDWARF::ParseLineTable(CompileUnit &comp_unit) {
   if (offset == DW_INVALID_OFFSET)
     return false;
 
+  ElapsedTime elapsed(m_parse_time);
   llvm::DWARFDebugLine line;
   const llvm::DWARFDebugLine::LineTable *line_table =
       ParseLLVMLineTable(m_context, line, offset, dwarf_cu->GetOffset());
@@ -1197,6 +1200,7 @@ SymbolFileDWARF::ParseDebugMacros(lldb::offset_t *offset) {
   if (iter != m_debug_macros_map.end())
     return iter->second;
 
+  ElapsedTime elapsed(m_parse_time);
   const DWARFDataExtractor &debug_macro_data = m_context.getOrLoadMacroData();
   if (debug_macro_data.GetByteSize() == 0)
     return DebugMacrosSP();
@@ -4096,3 +4100,9 @@ LanguageType SymbolFileDWARF::GetLanguageFamily(DWARFUnit &unit) {
     lang = DW_LANG_C_plus_plus;
   return LanguageTypeFromDWARF(lang);
 }
+
+StatsDuration SymbolFileDWARF::GetDebugInfoIndexTime() {
+  if (m_index)
+    return m_index->GetIndexTime();
+  return StatsDuration(0.0);
+}
index 8e50384..4d6fccd 100644 (file)
@@ -24,6 +24,7 @@
 #include "lldb/Symbol/DebugMacros.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Target/Statistics.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/Flags.h"
 #include "lldb/Utility/RangeMap.h"
@@ -320,6 +321,16 @@ public:
   /// Same as GetLanguage() but reports all C++ versions as C++ (no version).
   static lldb::LanguageType GetLanguageFamily(DWARFUnit &unit);
 
+  lldb_private::StatsDuration GetDebugInfoParseTime() override {
+    return m_parse_time;
+  }
+  lldb_private::StatsDuration GetDebugInfoIndexTime() override;
+
+  lldb_private::StatsDuration &GetDebugInfoParseTimeRef() {
+    return m_parse_time;
+  }
+
+
 protected:
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
       DIEToTypePtr;
@@ -550,6 +561,7 @@ protected:
   /// Try to filter out this debug info by comparing it to the lowest code
   /// address in the module.
   lldb::addr_t m_first_code_address = LLDB_INVALID_ADDRESS;
+  lldb_private::StatsDuration m_parse_time{0.0};
 };
 
 #endif // LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARF_H
index 884260f..a58696b 100644 (file)
@@ -1434,3 +1434,54 @@ SymbolFileDWARFDebugMap::AddOSOARanges(SymbolFileDWARF *dwarf2Data,
   }
   return num_line_entries_added;
 }
+
+uint64_t SymbolFileDWARFDebugMap::GetDebugInfoSize() {
+  uint64_t debug_info_size = 0;
+  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+    ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
+    if (!oso_objfile)
+      return false; // Keep iterating
+    ModuleSP module_sp = oso_objfile->GetModule();
+    if (!module_sp)
+      return false; // Keep iterating
+    SectionList *section_list = module_sp->GetSectionList();
+    if (section_list)
+      debug_info_size += section_list->GetDebugInfoSize();
+    return false; // Keep iterating
+  });
+  return debug_info_size;
+}
+
+StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoParseTime() {
+  StatsDuration elapsed(0.0);
+  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+    ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
+    if (oso_objfile) {
+      ModuleSP module_sp = oso_objfile->GetModule();
+      if (module_sp) {
+        SymbolFile *symfile = module_sp->GetSymbolFile();
+        if (symfile)
+          elapsed += symfile->GetDebugInfoParseTime();
+      }
+    }
+    return false; // Keep iterating
+  });
+  return elapsed;
+}
+
+StatsDuration SymbolFileDWARFDebugMap::GetDebugInfoIndexTime() {
+  StatsDuration elapsed(0.0);
+  ForEachSymbolFile([&](SymbolFileDWARF *oso_dwarf) -> bool {
+    ObjectFile *oso_objfile = oso_dwarf->GetObjectFile();
+    if (oso_objfile) {
+      ModuleSP module_sp = oso_objfile->GetModule();
+      if (module_sp) {
+        SymbolFile *symfile = module_sp->GetSymbolFile();
+        if (symfile)
+          elapsed += symfile->GetDebugInfoIndexTime();
+      }
+    }
+    return false; // Keep iterating
+  });
+  return elapsed;
+}
index a55bb3a..89da4e8 100644 (file)
@@ -144,6 +144,10 @@ public:
     return GetPluginNameStatic().GetStringRef();
   }
 
+  uint64_t GetDebugInfoSize() override;
+  lldb_private::StatsDuration GetDebugInfoParseTime() override;
+  lldb_private::StatsDuration GetDebugInfoIndexTime() override;
+
 protected:
   enum { kHaveInitializedOSOs = (1 << 0), kNumFlags };
 
index 8f0adaf..152d8f7 100644 (file)
@@ -1566,3 +1566,9 @@ SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) {
   }
   return type_system_or_err;
 }
+
+uint64_t SymbolFileNativePDB::GetDebugInfoSize() {
+  // PDB files are a separate file that contains all debug info.
+  return m_index->pdb().getFileSize();
+}
+
index acbf05f..c19875e 100644 (file)
@@ -75,6 +75,8 @@ public:
 
   void InitializeObject() override;
 
+  uint64_t GetDebugInfoSize() override;
+
   // Compile Unit function calls
 
   void
index 152bbe8..53f8dd6 100644 (file)
@@ -236,3 +236,15 @@ void SymbolFile::Dump(Stream &s) {
 }
 
 SymbolFile::RegisterInfoResolver::~RegisterInfoResolver() = default;
+
+uint64_t SymbolFile::GetDebugInfoSize() {
+  if (!m_objfile_sp)
+    return 0;
+  ModuleSP module_sp(m_objfile_sp->GetModule());
+  if (!module_sp)
+    return 0;
+  const SectionList *section_list = module_sp->GetSectionList();
+  if (section_list)
+    return section_list->GetDebugInfoSize();
+  return 0;
+}
index e1703d7..c4e9200 100644 (file)
@@ -50,6 +50,9 @@ json::Value ModuleStats::ToJSON() const {
   module.try_emplace("identifier", identifier);
   module.try_emplace("symbolTableParseTime", symtab_parse_time);
   module.try_emplace("symbolTableIndexTime", symtab_index_time);
+  module.try_emplace("debugInfoParseTime", debug_parse_time);
+  module.try_emplace("debugInfoIndexTime", debug_index_time);
+  module.try_emplace("debugInfoByteSize", (int64_t)debug_info_size);
   return module;
 }
 
@@ -109,6 +112,9 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
   json::Array json_modules;
   double symtab_parse_time = 0.0;
   double symtab_index_time = 0.0;
+  double debug_parse_time = 0.0;
+  double debug_index_time = 0.0;
+  uint64_t debug_info_size = 0;
   if (target) {
     json_targets.emplace_back(target->ReportStatistics());
   } else {
@@ -119,18 +125,31 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
   std::lock_guard<std::recursive_mutex> guard(
       Module::GetAllocationModuleCollectionMutex());
   const size_t num_modules = Module::GetNumberAllocatedModules();
-  ModuleSP module_sp;
   for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) {
     Module *module = Module::GetAllocatedModuleAtIndex(image_idx);
     ModuleStats module_stat;
     module_stat.identifier = (intptr_t)module;
     module_stat.path = module->GetFileSpec().GetPath();
+    if (ConstString object_name = module->GetObjectName()) {
+      module_stat.path.append(1, '(');
+      module_stat.path.append(object_name.GetStringRef().str());
+      module_stat.path.append(1, ')');
+    }
     module_stat.uuid = module->GetUUID().GetAsString();
     module_stat.triple = module->GetArchitecture().GetTriple().str();
     module_stat.symtab_parse_time = module->GetSymtabParseTime().count();
     module_stat.symtab_index_time = module->GetSymtabIndexTime().count();
+    SymbolFile *sym_file = module->GetSymbolFile();
+    if (sym_file) {
+      module_stat.debug_index_time = sym_file->GetDebugInfoIndexTime().count();
+      module_stat.debug_parse_time = sym_file->GetDebugInfoParseTime().count();
+      module_stat.debug_info_size = sym_file->GetDebugInfoSize();
+    }
     symtab_parse_time += module_stat.symtab_parse_time;
     symtab_index_time += module_stat.symtab_index_time;
+    debug_parse_time += module_stat.debug_parse_time;
+    debug_index_time += module_stat.debug_index_time;
+    debug_info_size += module_stat.debug_info_size;
     json_modules.emplace_back(module_stat.ToJSON());
   }
 
@@ -139,6 +158,9 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
       {"modules", std::move(json_modules)},
       {"totalSymbolTableParseTime", symtab_parse_time},
       {"totalSymbolTableIndexTime", symtab_index_time},
+      {"totalDebugInfoParseTime", debug_parse_time},
+      {"totalDebugInfoIndexTime", debug_index_time},
+      {"totalDebugInfoByteSize", debug_info_size},
   };
   return std::move(global_stats);
 }
index eda13c8..8fa5978 100644 (file)
@@ -144,6 +144,9 @@ class TestCase(TestBase):
                 "moduleIdentifiers": [...],
             }
           ],
+          "totalDebugInfoByteSize": 182522234,
+          "totalDebugInfoIndexTime": 2.33343,
+          "totalDebugInfoParseTime": 8.2121400240000071,
           "totalSymbolTableParseTime": 0.123,
           "totalSymbolTableIndexTime": 0.234,
         }
@@ -155,6 +158,9 @@ class TestCase(TestBase):
             'targets',
             'totalSymbolTableParseTime',
             'totalSymbolTableIndexTime',
+            'totalDebugInfoByteSize',
+            'totalDebugInfoIndexTime',
+            'totalDebugInfoParseTime',
         ]
         self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
         stats = debug_stats['targets'][0]
@@ -198,6 +204,9 @@ class TestCase(TestBase):
                     },
                 }
             ],
+            "totalDebugInfoByteSize": 182522234,
+            "totalDebugInfoIndexTime": 2.33343,
+            "totalDebugInfoParseTime": 8.2121400240000071,
             "totalSymbolTableParseTime": 0.123,
             "totalSymbolTableIndexTime": 0.234,
         }
@@ -212,6 +221,9 @@ class TestCase(TestBase):
             'targets',
             'totalSymbolTableParseTime',
             'totalSymbolTableIndexTime',
+            'totalDebugInfoByteSize',
+            'totalDebugInfoIndexTime',
+            'totalDebugInfoParseTime',
         ]
         self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
         stats = debug_stats['targets'][0]
@@ -247,6 +259,9 @@ class TestCase(TestBase):
             'targets',
             'totalSymbolTableParseTime',
             'totalSymbolTableIndexTime',
+            'totalDebugInfoParseTime',
+            'totalDebugInfoIndexTime',
+            'totalDebugInfoByteSize'
         ]
         self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
         stats = debug_stats['targets'][0]
@@ -256,6 +271,9 @@ class TestCase(TestBase):
         self.verify_keys(stats, '"stats"', keys_exist, None)
         exe_module = self.find_module_in_metrics(exe, debug_stats)
         module_keys = [
+            'debugInfoByteSize',
+            'debugInfoIndexTime',
+            'debugInfoParseTime',
             'identifier',
             'path',
             'symbolTableIndexTime',