Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Unified Diff: tools/cygprofile/cygprofile2.cc

Issue 2924093003: (Do not land) Very hacky patch for using -fprofile-functions in the Win-Clang build
Patch Set: Add code to print functions by call frquency Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/cygprofile/BUILD.gn ('k') | tools/cygprofile/cygprofile2_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/cygprofile/cygprofile2.cc
diff --git a/tools/cygprofile/cygprofile2.cc b/tools/cygprofile/cygprofile2.cc
new file mode 100644
index 0000000000000000000000000000000000000000..5c883fecaf07176ffb723b2ac572257ad73c48dc
--- /dev/null
+++ b/tools/cygprofile/cygprofile2.cc
@@ -0,0 +1,138 @@
+#include <stdio.h>
+#include <algorithm>
+#include <unordered_set>
+#include <unordered_map>
+
+// Compiling printf with -finstrument-functions seems to break it?
+
+#ifdef _MSC_VER
+#include <windows.h>
+#include <process.h>
+#include <dbghelp.h>
+
+#if 0
+extern "C" unsigned long __stdcall GetCurrentProcessId(void);
+
+extern "C" unsigned long _beginthread( void( __cdecl *start_address )( void * ), unsigned stack_size, void *arglist );
+#endif
+
+namespace {
+
+// We can easily run out of memory if this is too high.
+#define N (50*1024*1024)
+//#define N (1*1024*1024)
+void *tracebuf[N];
+int n = 0;
+
+char symbuf[1024*1024];
+
+void dump(void*) {
+ HMODULE dbghelp = LoadLibraryA("dbghelp.dll");
+ decltype(::SymFromAddr) *symfromaddr =
+ reinterpret_cast<decltype(::SymFromAddr)*>(GetProcAddress(dbghelp, "SymFromAddr"));
+ decltype(::SymInitialize) *syminitialize =
+ reinterpret_cast<decltype(::SymInitialize)*>(GetProcAddress(dbghelp, "SymInitialize"));
+ decltype(::SymSetOptions) *symsetoptions =
+ reinterpret_cast<decltype(::SymSetOptions)*>(GetProcAddress(dbghelp, "SymSetOptions"));
+
+
+ char fname[128];
+ sprintf(fname, "/src/tmp/cygprofile%lu.txt", GetCurrentProcessId());
+ FILE *f = fopen(fname, "a");
+
+ syminitialize(GetCurrentProcess(), NULL, TRUE);
+ symsetoptions(SYMOPT_DEFERRED_LOADS | SYMOPT_PUBLICS_ONLY);
+
+ std::unordered_set<void*> seen;
+
+#if 0
+ std::unordered_map<void*, unsigned> freq;
+ for (int i = 0; i < N; i++)
+ ++freq[tracebuf[i]];
+ std::vector<void*> funcs;
+ for (auto i : freq)
+ funcs.push_back(i.first);
+ std::sort(funcs.begin(), funcs.end(), [&](void* a, void* b) {
+ return freq[b] < freq[a];
+ });
+ std::unordered_set<std::string> seen_names;
+ for (void *func : funcs) {
+ PSYMBOL_INFO symbol = (PSYMBOL_INFO)symbuf;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ DWORD64 offset = 0;
+ if (symfromaddr(GetCurrentProcess(), (DWORD64)func, &offset, symbol)) {
+ char *name = symbol->Name;
+ if (name[0] == '_')
+ name++;
+ if (seen_names.count(name))
+ continue;
+ seen_names.insert(name);
+ fprintf(f, "%s (%u)\n", name, freq[func]);
+ }
+ }
+#endif
+
+#if 1
+ // Due to inlining, multiple functions can end up with the same symbol.
+ std::unordered_set<std::string> seen_names;
+
+ for (int i = 0; i < N; i++) {
+ if (seen.count(tracebuf[i]))
+ continue;
+ seen.insert(tracebuf[i]);
+
+ //fprintf(f, "0x%p\n", tracebuf[i]);
+
+ PSYMBOL_INFO symbol = (PSYMBOL_INFO)symbuf;
+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
+ symbol->MaxNameLen = MAX_SYM_NAME;
+ DWORD64 offset = 0;
+ if (symfromaddr(GetCurrentProcess(), (DWORD64)tracebuf[i], &offset, symbol)) {
+ char *name = symbol->Name;
+ if (name[0] == '_')
+ name++;
+ if (seen_names.count(name))
+ continue;
+ seen_names.insert(name);
+ fprintf(f, "%s\n", name);
+ }
+ }
+#endif
+
+ fclose(f);
+}
+
+}
+#endif
+
+extern "C" {
+
+// Set attributes to be sure we don't instrument ourselves.
+void __cyg_profile_func_enter(void* this_fn, void* call_site)
+ __attribute__((no_instrument_function));
+void __cyg_profile_func_exit(void* this_fn, void* call_site)
+ __attribute__((no_instrument_function));
+
+void __cyg_profile_func_enter(void* this_fn, void* callee_unused) {
+ // This gets pulled into NaCL binaries and all kinds of places.
+#ifdef _MSC_VER
+ static int done = 0;
+
+ if (done)
+ return;
+
+ tracebuf[n++] = this_fn;
+
+ if (n == N) {
+ done = 1;
+ _beginthread(dump, 0, nullptr);
+ return;
+ }
+#endif
+}
+
+void __cyg_profile_func_exit(void* this_fn, void* call_site) {}
+
+} // extern "C"
+
« no previous file with comments | « tools/cygprofile/BUILD.gn ('k') | tools/cygprofile/cygprofile2_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698