unsigned num_unsaved_files,
struct CXUnsavedFile *unsaved_files,
unsigned options);
-
+
+/**
+ * \brief Categorizes how memory is being used by a translation unit.
+ */
+enum CXTUMemoryUsageKind {
+ CXTUMemoryUsage_AST = 1,
+ CXTUMemoryUsage_Identifiers = 2,
+ CXTUMemoryUsage_Selectors = 3,
+ CXTUMemoryUsage_First = CXTUMemoryUsage_AST,
+ CXTUMemoryUsage_Last = CXTUMemoryUsage_Selectors
+};
+
+/**
+ * \brief Returns the human-readable null-terminated C string that represents
+ * the name of the memory category.
+ */
+CINDEX_LINKAGE
+const char *clang_getTUMemoryUsageName(enum CXTUMemoryUsageKind kind);
+
+typedef struct CXTUMemoryUsageEntry {
+ /* \brief The memory usage category. */
+ enum CXTUMemoryUsageKind kind;
+ /* \brief Memory usage in bytes. */
+ unsigned long amount;
+} CXTUMemoryUsageEntry;
+
+/**
+ * \brief The memory usage of a CXTranslationUnit, broken into categories.
+ */
+typedef struct CXTUMemoryUsage {
+ /* \brief Private data member, used for queries. */
+ void *data;
+
+ /* \brief The number of entries in the 'entries' array. */
+ unsigned numEntries;
+
+ /* \brief An array of key-value pairs, representing the breakdown of memory
+ usage. */
+ CXTUMemoryUsageEntry *entries;
+
+} CXTUMemoryUsage;
+
+/**
+ * \brief Return the memory usage of a translation unit. This object
+ * should be released with clang_disposeCXTUMemoryUsage().
+ */
+CINDEX_LINKAGE CXTUMemoryUsage clang_getCXTUMemoryUsage(CXTranslationUnit TU);
+
+CINDEX_LINKAGE void clang_disposeCXTUMemoryUsage(CXTUMemoryUsage usage);
+
/**
* @}
*/
}
}
+void PrintMemoryUsage(CXTranslationUnit TU) {
+ CXTUMemoryUsage usage = clang_getCXTUMemoryUsage(TU);
+ fprintf(stderr, "Memory usage:\n");
+ unsigned long total = 0.0;
+ for (unsigned i = 0, n = usage.numEntries; i != n; ++i) {
+ const char *name = clang_getTUMemoryUsageName(usage.entries[i].kind);
+ unsigned long amount = usage.entries[i].amount;
+ total += amount;
+ fprintf(stderr, " %s : %ld bytes (%lf MBytes)\n", name, amount,
+ ((double) amount)/(1024*1024));
+ }
+ fprintf(stderr, " TOTAL = %ld bytes (%lf MBytes)\n", total,
+ ((double) total)/(1024*1024));
+ clang_disposeCXTUMemoryUsage(usage);
+}
+
/******************************************************************************/
/* Logic for testing traversal. */
/******************************************************************************/
return FilteredPrintingVisitor;
if (strcmp(s, "-usrs") == 0)
return USRVisitor;
+ if (strncmp(s, "-memory-usage", 13) == 0)
+ return GetVisitor(s + 13);
return NULL;
}
"[FileCheck prefix]\n"
" c-index-test -test-load-source <symbol filter> {<args>}*\n");
fprintf(stderr,
+ " c-index-test -test-load-source-memory-usage "
+ "<symbol filter> {<args>}*\n"
" c-index-test -test-load-source-reparse <trials> <symbol filter> "
" {<args>}*\n"
" c-index-test -test-load-source-usrs <symbol filter> {<args>}*\n"
+ " c-index-test -test-load-source-usrs-memory-usage "
+ "<symbol filter> {<args>}*\n"
" c-index-test -test-annotate-tokens=<range> {<args>}*\n"
" c-index-test -test-inclusion-stack-source {<args>}*\n"
" c-index-test -test-inclusion-stack-tu <AST file>\n"
- " c-index-test -test-print-linkage-source {<args>}*\n"
- " c-index-test -test-print-typekind {<args>}*\n"
- " c-index-test -print-usr [<CursorKind> {<args>}]*\n");
+ " c-index-test -test-print-linkage-source {<args>}*\n");
fprintf(stderr,
+ " c-index-test -test-print-typekind {<args>}*\n"
+ " c-index-test -print-usr [<CursorKind> {<args>}]*\n"
" c-index-test -print-usr-file <file>\n"
" c-index-test -write-pch <file> <compiler arguments>\n\n");
fprintf(stderr,
}
else if (argc >= 4 && strncmp(argv[1], "-test-load-source", 17) == 0) {
CXCursorVisitor I = GetVisitor(argv[1] + 17);
+
+ PostVisitTU postVisit = 0;
+ if (strstr(argv[1], "-memory-usage"))
+ postVisit = PrintMemoryUsage;
+
if (I)
- return perform_test_load_source(argc - 3, argv + 3, argv[2], I, NULL);
+ return perform_test_load_source(argc - 3, argv + 3, argv[2], I,
+ postVisit);
}
else if (argc >= 4 && strcmp(argv[1], "-test-file-scan") == 0)
return perform_file_scan(argv[2], argv[3],
}
} // end: extern "C"
+//===----------------------------------------------------------------------===//
+// Inspecting memory usage.
+//===----------------------------------------------------------------------===//
+
+typedef std::vector<CXTUMemoryUsageEntry> MemUsageEntries;
+
+static inline void createCXTUMemoryUsageEntry(MemUsageEntries &entries,
+ enum CXTUMemoryUsageKind k,
+ double amount) {
+ CXTUMemoryUsageEntry entry = { k, amount };
+ entries.push_back(entry);
+}
+
+extern "C" {
+
+const char *clang_getTUMemoryUsageName(CXTUMemoryUsageKind kind) {
+ const char *str = "";
+ switch (kind) {
+ case CXTUMemoryUsage_AST:
+ str = "ASTContext: expressions, declarations, and types";
+ break;
+ case CXTUMemoryUsage_Identifiers:
+ str = "ASTContext: identifiers";
+ break;
+ case CXTUMemoryUsage_Selectors:
+ str = "ASTContext: selectors";
+ }
+ return str;
+}
+
+CXTUMemoryUsage clang_getCXTUMemoryUsage(CXTranslationUnit TU) {
+ if (!TU) {
+ CXTUMemoryUsage usage = { (void*) 0, 0, 0 };
+ return usage;
+ }
+
+ ASTUnit *astUnit = static_cast<ASTUnit*>(TU->TUData);
+ llvm::OwningPtr<MemUsageEntries> entries(new MemUsageEntries());
+ ASTContext &astContext = astUnit->getASTContext();
+
+ // How much memory is used by AST nodes and types?
+ createCXTUMemoryUsageEntry(*entries, CXTUMemoryUsage_AST,
+ (unsigned long) astContext.getTotalAllocatedMemory());
+
+ // How much memory is used by identifiers?
+ createCXTUMemoryUsageEntry(*entries, CXTUMemoryUsage_Identifiers,
+ (unsigned long) astContext.Idents.getAllocator().getTotalMemory());
+
+ // How much memory is used for selectors?
+ createCXTUMemoryUsageEntry(*entries, CXTUMemoryUsage_Selectors,
+ (unsigned long) astContext.Selectors.getTotalMemory());
+
+ CXTUMemoryUsage usage = { (void*) entries.get(),
+ (unsigned) entries->size(),
+ entries->size() ? &(*entries)[0] : 0 };
+ entries.take();
+ return usage;
+}
+
+void clang_disposeCXTUMemoryUsage(CXTUMemoryUsage usage) {
+ if (usage.data)
+ delete (MemUsageEntries*) usage.data;
+}
+
+} // end extern "C"
+
//===----------------------------------------------------------------------===//
// Misc. utility functions.
//===----------------------------------------------------------------------===//
}
} // end: extern "C"
+
_clang_defaultReparseOptions
_clang_defaultSaveOptions
_clang_disposeCXCursorSet
+_clang_disposeCXTUMemoryUsage
_clang_disposeCodeCompleteResults
_clang_disposeDiagnostic
_clang_disposeIndex
_clang_executeOnThread
_clang_formatDiagnostic
_clang_getCString
+_clang_getCXTUMemoryUsage
_clang_getCXXAccessSpecifier
_clang_getCanonicalCursor
_clang_getCanonicalType
_clang_getResultType
_clang_getSpecializedCursorTemplate
_clang_getSpellingLocation
+_clang_getTUMemoryUsageName
_clang_getTemplateCursorKind
_clang_getTokenExtent
_clang_getTokenKind
clang_defaultReparseOptions
clang_defaultSaveOptions
clang_disposeCXCursorSet
+clang_disposeCXTUMemoryUsage
clang_disposeCodeCompleteResults
clang_disposeDiagnostic
clang_disposeIndex
clang_executeOnThread
clang_formatDiagnostic
clang_getCString
+clang_getCXTUMemoryUsage
clang_getCXXAccessSpecifier
clang_getCanonicalCursor
clang_getCanonicalType
clang_getResultType
clang_getSpecializedCursorTemplate
clang_getSpellingLocation
+clang_getTUMemoryUsageName
clang_getTemplateCursorKind
clang_getTokenExtent
clang_getTokenKind