From 13e835e83df31ff62e4c75c8b84888479e059d6c Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 31 May 2021 13:29:19 +0300 Subject: [PATCH 01/31] Remove the "Profiling started" message --- src/profiler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/profiler.cpp b/src/profiler.cpp index 9bb3202d7..27bbb50db 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1504,7 +1504,6 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { if (error) { return error; } - out << "Profiling started\n"; break; } case ACTION_STOP: { From e16fad0c93a50e099bf031493cdf24fc9017be35 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sat, 5 Jun 2021 03:33:59 +0300 Subject: [PATCH 02/31] Remove the "Profiling stopped" message --- src/profiler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/profiler.cpp b/src/profiler.cpp index 27bbb50db..dda257e28 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1512,7 +1512,6 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { if (error) { return error; } - out << "Profiling stopped after " << uptime() << " seconds. No dump options specified\n"; break; } // Fall through From 0c25728d1ce98e1e06c243f8b5a99d98a17ae16e Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 12 Jul 2021 23:12:13 +0300 Subject: [PATCH 03/31] Compile statically with libstdc++ We have encountered errors like "Error loading shared library libstdc++.so.6", this is an attempt to solve them. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bae90d22b..6b928a01f 100644 --- a/Makefile +++ b/Makefile @@ -129,7 +129,7 @@ ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ -xc++ - $(LIBS) else - $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -o $@ $(SOURCES) $(LIBS) endif build/$(JATTACH): src/jattach/*.c src/jattach/*.h From fca73defc235511411e3077880a5a9e8771a82f3 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 13 Jul 2021 00:17:17 +0300 Subject: [PATCH 04/31] Build jattach statically --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6b928a01f..31a51ac30 100644 --- a/Makefile +++ b/Makefile @@ -133,7 +133,7 @@ else endif build/$(JATTACH): src/jattach/*.c src/jattach/*.h - $(CC) $(CFLAGS) -DJATTACH_VERSION=\"$(PROFILER_VERSION)-ap\" -o $@ src/jattach/*.c + $(CC) $(CFLAGS) -static -DJATTACH_VERSION=\"$(PROFILER_VERSION)-ap\" -o $@ src/jattach/*.c build/fdtransfer: src/fdtransfer/*.cpp src/fdtransfer/*.h src/jattach/psutil.c src/jattach/psutil.h $(CXX) $(CFLAGS) -o $@ src/fdtransfer/*.cpp src/jattach/psutil.c From f8f77fd7ed4f2303c01974ef17b891f59c83a5f6 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 4 Oct 2021 10:36:23 +0300 Subject: [PATCH 05/31] Build fdtransfer statically Like we did for jattach --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 31a51ac30..6d72c2f3b 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ build/$(JATTACH): src/jattach/*.c src/jattach/*.h $(CC) $(CFLAGS) -static -DJATTACH_VERSION=\"$(PROFILER_VERSION)-ap\" -o $@ src/jattach/*.c build/fdtransfer: src/fdtransfer/*.cpp src/fdtransfer/*.h src/jattach/psutil.c src/jattach/psutil.h - $(CXX) $(CFLAGS) -o $@ src/fdtransfer/*.cpp src/jattach/psutil.c + $(CXX) $(CFLAGS) -static -o $@ src/fdtransfer/*.cpp src/jattach/psutil.c build/$(API_JAR): $(API_SOURCES) mkdir -p build/api From ab6e1dee50697a6ce826d0ddbb3d8e461ceca461 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 29 Nov 2021 21:06:49 +0200 Subject: [PATCH 06/31] Compile statically with libgcc --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6d72c2f3b..af6d9d369 100644 --- a/Makefile +++ b/Makefile @@ -129,7 +129,7 @@ ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ -xc++ - $(LIBS) else - $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -static-libgcc -o $@ $(SOURCES) $(LIBS) endif build/$(JATTACH): src/jattach/*.c src/jattach/*.h From ae5daf195ff698483b021329b4d7dfe60aaec225 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Thu, 14 Apr 2022 12:25:15 +0300 Subject: [PATCH 07/31] Fix -static-* args passed only in non-MERGE case :( --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index af6d9d369..a653c3443 100644 --- a/Makefile +++ b/Makefile @@ -124,12 +124,13 @@ $(PACKAGE_DIR): build/$(LIB_PROFILER) build/$(JATTACH) $(FDTRANSFER_BIN) \ build: mkdir -p build +PROFILER_STATIC_FLAGS=-static-libstdc++ -static-libgcc build/$(LIB_PROFILER_SO): $(SOURCES) $(HEADERS) $(RESOURCES) $(JAVA_HELPER_CLASSES) ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ - $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ -xc++ - $(LIBS) + $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ -xc++ - $(LIBS) else - $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -static-libgcc -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ $(SOURCES) $(LIBS) endif build/$(JATTACH): src/jattach/*.c src/jattach/*.h From c8c72a19339e6e9754a1c7ea33bb1beacde9297e Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 13 Jul 2022 00:57:37 +0300 Subject: [PATCH 08/31] Close standard streams after forking in fdtransfer --- src/fdtransfer/fdtransferServer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fdtransfer/fdtransferServer.cpp b/src/fdtransfer/fdtransferServer.cpp index 188445ec7..bb40eeaf0 100644 --- a/src/fdtransfer/fdtransferServer.cpp +++ b/src/fdtransfer/fdtransferServer.cpp @@ -312,6 +312,9 @@ static int single_pid_server(int pid, const char *path) { // CLONE_NEWPID affects children only - so we fork here. if (0 == fork()) { + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); return FdTransferServer::acceptPeer(&nspid) && FdTransferServer::serveRequests(nspid) ? 0 : 1; } else { // Exit now, let our caller continue. From 49080a221b46e312041947ebbf7845dc054b4438 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 30 Aug 2022 11:20:16 +0300 Subject: [PATCH 09/31] -static-libstdc++ only on musl --- Makefile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a653c3443..69faa302c 100644 --- a/Makefile +++ b/Makefile @@ -124,7 +124,11 @@ $(PACKAGE_DIR): build/$(LIB_PROFILER) build/$(JATTACH) $(FDTRANSFER_BIN) \ build: mkdir -p build -PROFILER_STATIC_FLAGS=-static-libstdc++ -static-libgcc +PROFILER_STATIC_FLAGS=-static-libgcc +ifeq ($(OS_TAG),linux-musl) + PROFILER_STATIC_FLAGS+= -static-libstdc++ +endif + build/$(LIB_PROFILER_SO): $(SOURCES) $(HEADERS) $(RESOURCES) $(JAVA_HELPER_CLASSES) ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ From f4d874c2f64740032b98406c056ca5fe744089cc Mon Sep 17 00:00:00 2001 From: marcin-ol Date: Thu, 27 Oct 2022 00:05:57 +0200 Subject: [PATCH 10/31] Convert frame name format to 'function (DSO)' for LIB style (#2) For https://github.com/Granulate/gprofiler/pull/491 --- src/codeCache.cpp | 8 +++++++- src/codeCache.h | 1 + src/frameName.cpp | 4 ++-- src/profiler.cpp | 16 ++++++++++++---- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/codeCache.cpp b/src/codeCache.cpp index 3465b9036..9e00accbd 100644 --- a/src/codeCache.cpp +++ b/src/codeCache.cpp @@ -41,6 +41,10 @@ size_t NativeFunc::usedMemory(const char* name) { CodeCache::CodeCache(const char* name, short lib_index, const void* min_address, const void* max_address) { _name = NativeFunc::create(name, -1); + char *tmp = (char*)malloc(strlen(name) + 3); + snprintf(tmp, strlen(name) + 3, "(%s)", name); + _lib_symbol = NativeFunc::create(tmp, -1); + free(tmp); _lib_index = lib_index; _min_address = min_address; _max_address = max_address; @@ -63,6 +67,7 @@ CodeCache::~CodeCache() { for (int i = 0; i < _count; i++) { NativeFunc::destroy(_blobs[i]._name); } + NativeFunc::destroy(_lib_symbol); NativeFunc::destroy(_name); delete[] _blobs; free(_dwarf_table); @@ -153,7 +158,8 @@ const char* CodeCache::binarySearch(const void* address) { if (low > 0 && (_blobs[low - 1]._start == _blobs[low - 1]._end || _blobs[low - 1]._end == address)) { return _blobs[low - 1]._name; } - return _name; + + return _lib_symbol; } const void* CodeCache::findSymbol(const char* name) { diff --git a/src/codeCache.h b/src/codeCache.h index 18a6cbf41..f4192c9cd 100644 --- a/src/codeCache.h +++ b/src/codeCache.h @@ -87,6 +87,7 @@ class FrameDesc; class CodeCache { protected: char* _name; + char* _lib_symbol; short _lib_index; const void* _min_address; const void* _max_address; diff --git a/src/frameName.cpp b/src/frameName.cpp index afd86a229..e6f0ca5b0 100644 --- a/src/frameName.cpp +++ b/src/frameName.cpp @@ -134,7 +134,7 @@ const char* FrameName::decodeNativeSymbol(const char* name) { char* demangled = abi::__cxa_demangle(name, NULL, NULL, &status); if (demangled != NULL) { if (lib_name != NULL) { - _str.assign(lib_name).append("`").append(demangled); + _str.assign(demangled).append(" (").append(lib_name).append(")"); } else { _str.assign(demangled); } @@ -144,7 +144,7 @@ const char* FrameName::decodeNativeSymbol(const char* name) { } if (lib_name != NULL) { - return _str.assign(lib_name).append("`").append(name).c_str(); + return _str.assign(name).append(" (").append(lib_name).append(")").c_str(); } else { return name; } diff --git a/src/profiler.cpp b/src/profiler.cpp index dda257e28..64ef8e8c1 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -245,8 +245,7 @@ const char* Profiler::getLibraryName(const char* native_symbol) { if (lib_index >= 0 && lib_index < _native_libs.count()) { const char* s = _native_libs[lib_index]->name(); if (s != NULL) { - const char* p = strrchr(s, '/'); - return p != NULL ? p + 1 : s; + return s; } } return NULL; @@ -259,15 +258,24 @@ CodeCache* Profiler::findJvmLibrary(const char* lib_name) { CodeCache* Profiler::findLibraryByName(const char* lib_name) { const size_t lib_name_len = strlen(lib_name); const int native_lib_count = _native_libs.count(); + int basename_match_i = -1; for (int i = 0; i < native_lib_count; i++) { const char* s = _native_libs[i]->name(); if (s != NULL) { - const char* p = strrchr(s, '/'); - if (p != NULL && strncmp(p + 1, lib_name, lib_name_len) == 0) { + if (strncmp(s, lib_name, lib_name_len) == 0) { return _native_libs[i]; } + if (basename_match_i < 0) { + const char* p = strrchr(s, '/'); + if (p != NULL && strncmp(p + 1, lib_name, lib_name_len) == 0) { + basename_match_i = i; + } + } } } + if (basename_match_i >= 0) { + return _native_libs[basename_match_i]; + } return NULL; } From bb06e2354929141561824f384e35e4ea07a54767 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Fri, 18 Nov 2022 19:14:38 +0200 Subject: [PATCH 11/31] Add accept timeout as 3rd parameter of fdtransfer --- src/fdtransfer/fdtransferServer.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/fdtransfer/fdtransferServer.cpp b/src/fdtransfer/fdtransferServer.cpp index bb40eeaf0..7e0b2a482 100644 --- a/src/fdtransfer/fdtransferServer.cpp +++ b/src/fdtransfer/fdtransferServer.cpp @@ -273,7 +273,7 @@ bool FdTransferServer::sendFd(int fd, struct fd_response *resp, size_t resp_size return true; } -static int single_pid_server(int pid, const char *path) { +static int single_pid_server(int pid, const char *path, unsigned int timeout) { // get its nspid prior to moving to its PID namespace. int nspid; uid_t _target_uid; @@ -301,7 +301,7 @@ static int single_pid_server(int pid, const char *path) { } } - if (!FdTransferServer::bindServer(&sun, addrlen, 10)) { + if (!FdTransferServer::bindServer(&sun, addrlen, timeout)) { return 1; } @@ -373,10 +373,12 @@ static int path_server(const char *path) { int main(int argc, const char** argv) { int pid = 0; - if (argc == 3) { + unsigned int timeout = 0; + if (argc == 4) { pid = atoi(argv[2]); + timeout = atoi(argv[3]); } else if (argc != 2) { - fprintf(stderr, "Usage: %s []\n", argv[0]); + fprintf(stderr, "Usage: %s [ ]\n", argv[0]); return 1; } @@ -384,7 +386,7 @@ int main(int argc, const char** argv) { // pid is not given - bind on a path and accept requests forever, from any PID, until being killed. // pid is given - bind on an path for that PID, accept requests only from that PID until the single connection is closed. if (pid != 0) { - return single_pid_server(pid, argv[1]); + return single_pid_server(pid, argv[1], timeout); } else { return path_server(argv[1]); } From faaabf8831d4fe7edfed0e846a39b8b4d517a5b0 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 29 Nov 2022 17:37:19 +0200 Subject: [PATCH 12/31] Use compat-glibc on x86_64 glibc --- Makefile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 69faa302c..739fec19e 100644 --- a/Makefile +++ b/Makefile @@ -124,17 +124,25 @@ $(PACKAGE_DIR): build/$(LIB_PROFILER) build/$(JATTACH) $(FDTRANSFER_BIN) \ build: mkdir -p build -PROFILER_STATIC_FLAGS=-static-libgcc +PROFILER_FLAGS=-static-libgcc ifeq ($(OS_TAG),linux-musl) - PROFILER_STATIC_FLAGS+= -static-libstdc++ + PROFILER_FLAGS+= -static-libstdc++ +endif + +# On x86_64 glibc (not musl), build against compat-glibc +# see https://centos.pkgs.org/7/centos-x86_64/compat-glibc-2.12-4.el7.centos.x86_64.rpm.html +ifneq ($(OS_TAG),linux-musl) + ifeq ($(ARCH),x86_64) + PROFILER_FLAGS+= -I /usr/lib/x86_64-redhat-linux6E/include -B /usr/lib/x86_64-redhat-linux6E/lib64/ + endif endif build/$(LIB_PROFILER_SO): $(SOURCES) $(HEADERS) $(RESOURCES) $(JAVA_HELPER_CLASSES) ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ - $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ -xc++ - $(LIBS) + $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_FLAGS) -o $@ -xc++ - $(LIBS) else - $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_FLAGS) -o $@ $(SOURCES) $(LIBS) endif build/$(JATTACH): src/jattach/*.c src/jattach/*.h From df5df4a22826300c4e53bf5fc4143c5335d61c35 Mon Sep 17 00:00:00 2001 From: Guy Bortnikov Date: Tue, 29 Nov 2022 16:36:14 +0200 Subject: [PATCH 13/31] dump stats on stop --- src/arguments.cpp | 3 +++ src/arguments.h | 5 ++++- src/profiler.cpp | 10 ++++++++++ src/profiler.h | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index 51ec2aae6..507442fae 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -350,6 +350,9 @@ Error Arguments::parse(const char* args) { CASE("reverse") _reverse = true; + CASE("meminfolog") + _log_meminfo_on_dump = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index 40dfbe411..e5f81cc92 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -174,6 +174,8 @@ class Arguments { const char* _title; double _minwidth; bool _reverse; + // Granulate Extra + bool _log_meminfo_on_dump; Arguments(bool persistent = false) : _buf(NULL), @@ -218,7 +220,8 @@ class Arguments { _end(NULL), _title(NULL), _minwidth(0), - _reverse(false) { + _reverse(false), + _log_meminfo_on_dump(false) { } ~Arguments(); diff --git a/src/profiler.cpp b/src/profiler.cpp index 64ef8e8c1..123b9ab07 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1526,6 +1526,10 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { } case ACTION_DUMP: { Error error = dump(out, args); + if (args._log_meminfo_on_dump) { + logUsedMemory(); + } + if (error) { return error; } @@ -1646,3 +1650,9 @@ void Profiler::shutdown(Arguments& args) { _state = TERMINATED; } + +void Profiler::logUsedMemory() { + std::ostringstream stringStream; + printUsedMemory(stringStream); + Log::info("%s", stringStream.str().c_str()); +} diff --git a/src/profiler.h b/src/profiler.h index 3da7d8413..dd934a586 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -201,6 +201,7 @@ class Profiler { Error stop(); Error flushJfr(); Error dump(std::ostream& out, Arguments& args); + void logUsedMemory(); void printUsedMemory(std::ostream& out); void switchThreadEvents(jvmtiEventMode mode); int convertNativeTrace(int native_frames, const void** callchain, ASGCT_CallFrame* frames); From 60cbc128a752c657e8a97300784686e08c8dbe9d Mon Sep 17 00:00:00 2001 From: Andrei Pangin Date: Tue, 20 Dec 2022 22:57:35 +0000 Subject: [PATCH 14/31] Do not try to parse mapped pseudofiles --- src/symbols_linux.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/symbols_linux.cpp b/src/symbols_linux.cpp index d0157df00..1d9a16435 100644 --- a/src/symbols_linux.cpp +++ b/src/symbols_linux.cpp @@ -583,6 +583,10 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) { if (!map.isReadable() || map.file() == NULL || map.file()[0] == 0) { continue; } + if (strchr(map.file(), ':') != NULL) { + // Skip pseudofiles like anon_inode:name, /memfd:name + continue; + } const char* image_base = map.addr(); if (image_base != image_end) last_readable_base = image_base; @@ -605,7 +609,8 @@ void Symbols::parseLibraries(CodeCacheArray* array, bool kernel_symbols) { // Do not parse the same executable twice, e.g. on Alpine Linux if (_parsed_inodes.insert(u64(map.dev()) << 32 | inode).second) { // Be careful: executable file is not always ELF, e.g. classes.jsa - if ((image_base -= map.offs()) >= last_readable_base) { + unsigned long offs = map.offs(); + if ((unsigned long)image_base > offs && (image_base -= offs) >= last_readable_base) { ElfParser::parseProgramHeaders(cc, image_base, image_end); } ElfParser::parseFile(cc, image_base, map.file(), true); From 4938ce815be597fafc6a7a185a16ff394b9d7f41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Po=C5=BAniak?= Date: Wed, 15 Mar 2023 12:33:01 +0100 Subject: [PATCH 15/31] Add option to include method modifiers in frame name (#5) async-profiler side of https://github.com/Granulate/gprofiler/issues/570. --- src/arguments.cpp | 3 +++ src/arguments.h | 4 +++- src/frameName.cpp | 31 ++++++++++++++++++++++++++++++- src/frameName.h | 1 + 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index 507442fae..abecbe80c 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -353,6 +353,9 @@ Error Arguments::parse(const char* args) { CASE("meminfolog") _log_meminfo_on_dump = true; + CASE("includemm") + _includemm = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index e5f81cc92..b36a6f31a 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -157,6 +157,7 @@ class Arguments { bool _sched; bool _live; bool _fdtransfer; + bool _includemm; const char* _fdtransfer_path; int _style; CStack _cstack; @@ -221,7 +222,8 @@ class Arguments { _title(NULL), _minwidth(0), _reverse(false), - _log_meminfo_on_dump(false) { + _log_meminfo_on_dump(false), + _includemm(false) { } ~Arguments(); diff --git a/src/frameName.cpp b/src/frameName.cpp index e6f0ca5b0..8d85d9227 100644 --- a/src/frameName.cpp +++ b/src/frameName.cpp @@ -28,6 +28,24 @@ static inline bool isDigit(char c) { } +// Based on: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#:~:text=Table%C2%A04.5.%C2%A0Method%20access%20and%20property%20flags +// Good practice order from: https://checkstyle.sourceforge.io/config_modifier.html#ModifierOrder +const static std::pair access_flags [] = { + std::make_pair(0x0001, "public"), + std::make_pair(0x0002, "private"), + std::make_pair(0x0004, "protected"), + std::make_pair(0x0400, "abstract"), + std::make_pair(0x0008, "static"), + std::make_pair(0x0010, "final"), + std::make_pair(0x0020, "synchronized"), + std::make_pair(0x0100, "native"), + std::make_pair(0x0800, "strict"), + std::make_pair(0x0040, "bridge"), + std::make_pair(0x0080, "varargs"), + std::make_pair(0x1000, "synthetic"), +}; + + Matcher::Matcher(const char* pattern) { if (pattern[0] == '*') { _type = MATCH_ENDS_WITH; @@ -95,7 +113,7 @@ FrameName::FrameName(Arguments& args, int style, int epoch, Mutex& thread_names_ { // Require printf to use standard C format regardless of system locale _saved_locale = uselocale(newlocale(LC_NUMERIC_MASK, "C", (locale_t)0)); - + _includemm = args._includemm; buildFilter(_include, args._buf, args._include); buildFilter(_exclude, args._buf, args._exclude); @@ -168,6 +186,7 @@ void FrameName::javaMethodName(jmethodID method) { char* class_name = NULL; char* method_name = NULL; char* method_sig = NULL; + jint modifiers = 0; jvmtiEnv* jvmti = VM::jvmti(); jvmtiError err; @@ -177,6 +196,16 @@ void FrameName::javaMethodName(jmethodID method) { (err = jvmti->GetClassSignature(method_class, &class_name, NULL)) == 0) { // Trim 'L' and ';' off the class descriptor like 'Ljava/lang/Object;' javaClassName(class_name + 1, strlen(class_name) - 2, _style); + if (_includemm) { + jvmti->GetMethodModifiers(method, &modifiers); + std::string modifiers_to_append = ""; + for (int i=0; i<(sizeof(access_flags) / sizeof(access_flags[0])); i++) { + if (modifiers & access_flags[i].first) { + modifiers_to_append.append(access_flags[i].second + " "); + } + } + _str.insert(0, modifiers_to_append); + } _str.append(".").append(method_name); if (_style & STYLE_SIGNATURES) { if (_style & STYLE_NO_SEMICOLON) { diff --git a/src/frameName.h b/src/frameName.h index 26d8e837c..e8cea7ad4 100644 --- a/src/frameName.h +++ b/src/frameName.h @@ -75,6 +75,7 @@ class FrameName { Mutex& _thread_names_lock; ThreadMap& _thread_names; locale_t _saved_locale; + bool _includemm; void buildFilter(std::vector& vector, const char* base, int offset); const char* decodeNativeSymbol(const char* name); From 666a620f2519405ef6630aa36ceb03166a42282b Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Thu, 23 Mar 2023 13:13:11 +0000 Subject: [PATCH 16/31] Add recycle flag which allows resetting timeout timer --- src/arguments.cpp | 12 ++++++++++++ src/arguments.h | 4 +++- src/profiler.cpp | 23 ++++++++++++++++++++++- src/profiler.h | 1 + 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index abecbe80c..0fc42f788 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -107,6 +107,8 @@ static const Multiplier UNIVERSAL[] = {{'n', 1}, {'u', 1000}, {'m', 1000000}, {' // title=TITLE - FlameGraph title // minwidth=PCT - FlameGraph minimum frame width in percent // reverse - generate stack-reversed FlameGraph / Call tree +// includemm - inclue method modifiers +// recycle - recycle timeout timer (only: dump and status) // // It is possible to specify multiple dump options at the same time @@ -356,6 +358,9 @@ Error Arguments::parse(const char* args) { CASE("includemm") _includemm = true; + CASE("recycle") + _recycle = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } @@ -383,6 +388,13 @@ Error Arguments::parse(const char* args) { _action = ACTION_DUMP; } + if (_recycle && _action != ACTION_DUMP && _action != ACTION_STATUS) { + return Error("Recycle argument only valid for actions: dump and status"); + } + if (_recycle && _loop) { + return Error("Recycle argument doesn't support loop mode"); + } + return Error::OK; } diff --git a/src/arguments.h b/src/arguments.h index b36a6f31a..d7a3b8f73 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -177,6 +177,7 @@ class Arguments { bool _reverse; // Granulate Extra bool _log_meminfo_on_dump; + bool _recycle; Arguments(bool persistent = false) : _buf(NULL), @@ -223,7 +224,8 @@ class Arguments { _minwidth(0), _reverse(false), _log_meminfo_on_dump(false), - _includemm(false) { + _includemm(false), + _recycle(false) { } ~Arguments(); diff --git a/src/profiler.cpp b/src/profiler.cpp index 123b9ab07..380f6474d 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1165,6 +1165,9 @@ Error Profiler::dump(std::ostream& out, Arguments& args) { } if (_state == RUNNING) { + if (args._recycle && args._timeout) { + recycleTimeoutTimer(args); + } updateJavaThreadNames(); updateNativeThreadNames(); } @@ -1475,7 +1478,8 @@ void Profiler::stopTimer() { void Profiler::timerLoop(void* timer_id) { u64 current_micros = OS::micros(); - u64 stop_micros = _stop_time * 1000000ULL; + time_t stop_time = _stop_time; + u64 stop_micros = stop_time * 1000000ULL; u64 sleep_until = _jfr.active() ? current_micros + 1000000 : stop_micros; MutexLocker ml(_timer_lock); @@ -1484,6 +1488,11 @@ void Profiler::timerLoop(void* timer_id) { // timeout not reached } if (_timer_id != timer_id) return; + if (_stop_time != stop_time) { + // handle timeout recycling + stop_time = _stop_time; + stop_micros = stop_time * 1000000ULL; + } if ((current_micros = OS::micros()) >= stop_micros) { VM::restartProfiler(); @@ -1504,6 +1513,15 @@ void Profiler::timerThreadEntry(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { instance()->timerLoop(arg); } +void Profiler::recycleTimeoutTimer(Arguments& args) { + MutexLocker ml(_timer_lock); + if (_timer_id != NULL) { + time_t current_time = time(NULL); + _stop_time = addTimeout(current_time, args._timeout); + _timer_lock.notify(); + } +} + Error Profiler::runInternal(Arguments& args, std::ostream& out) { switch (args._action) { case ACTION_START: @@ -1547,6 +1565,9 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { MutexLocker ml(_state_lock); if (_state == RUNNING) { out << "Profiling is running for " << uptime() << " seconds\n"; + if (args._recycle && args._timeout) { + recycleTimeoutTimer(args); + } } else { out << "Profiler is not active\n"; } diff --git a/src/profiler.h b/src/profiler.h index dd934a586..7c3162c5a 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -146,6 +146,7 @@ class Profiler { void stopTimer(); void timerLoop(void* timer_id); static void timerThreadEntry(jvmtiEnv* jvmti, JNIEnv* jni, void* arg); + void recycleTimeoutTimer(Arguments& args); void lockAll(); void unlockAll(); From d3a863aedab934eccd89eb00af4617eb6ffa27e4 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 31 May 2021 13:29:19 +0300 Subject: [PATCH 17/31] Remove the "Profiling started" message --- src/profiler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/profiler.cpp b/src/profiler.cpp index a9b3351e0..b753ece3d 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1546,7 +1546,6 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { if (error) { return error; } - out << "Profiling started\n"; break; } case ACTION_STOP: { From a0a9633526b970e560be10c197b0834da4b7e658 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Sat, 5 Jun 2021 03:33:59 +0300 Subject: [PATCH 18/31] Remove the "Profiling stopped" message --- src/profiler.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/profiler.cpp b/src/profiler.cpp index b753ece3d..bbb016404 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1554,7 +1554,6 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { if (error) { return error; } - out << "Profiling stopped after " << uptime() << " seconds. No dump options specified\n"; break; } // Fall through From f71df14480d56f8bf0293f4aa1ecf90387c40e08 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 12 Jul 2021 23:12:13 +0300 Subject: [PATCH 19/31] Compile statically with libstdc++ We have encountered errors like "Error loading shared library libstdc++.so.6", this is an attempt to solve them. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 981ee1f4d..39f7cd419 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,7 @@ ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ -xc++ - $(LIBS) else - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -o $@ $(SOURCES) $(LIBS) endif build/$(API_JAR): $(API_SOURCES) From bf4337c8fbf878f95d2eac57312f6317096bda9f Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Mon, 29 Nov 2021 21:06:49 +0200 Subject: [PATCH 20/31] Compile statically with libgcc --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 39f7cd419..f5d2fd2b8 100644 --- a/Makefile +++ b/Makefile @@ -126,7 +126,7 @@ ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ -xc++ - $(LIBS) else - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -static-libgcc -o $@ $(SOURCES) $(LIBS) endif build/$(API_JAR): $(API_SOURCES) From 8ebf5254f2e8fffed1942a525ea5b44f51b67ac5 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Thu, 14 Apr 2022 12:25:15 +0300 Subject: [PATCH 21/31] Fix -static-* args passed only in non-MERGE case :( --- Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f5d2fd2b8..4837b6e4a 100644 --- a/Makefile +++ b/Makefile @@ -121,12 +121,14 @@ build/$(LAUNCHER): src/launcher/* src/jattach/* src/fdtransfer.h $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -DSUPPRESS_OUTPUT -o $@ src/launcher/*.cpp src/jattach/*.c strip $@ +PROFILER_STATIC_FLAGS=-static-libstdc++ -static-libgcc + build/$(LIB_PROFILER): $(SOURCES) $(HEADERS) $(RESOURCES) $(JAVA_HELPER_CLASSES) ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -o $@ -xc++ - $(LIBS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ -xc++ - $(LIBS) else - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared -static-libstdc++ -static-libgcc -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ $(SOURCES) $(LIBS) endif build/$(API_JAR): $(API_SOURCES) From 98280bae34a5e19180a5b14da0bf14babe9a9f8c Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Wed, 13 Jul 2022 00:57:37 +0300 Subject: [PATCH 22/31] Close standard streams after forking in fdtransfer --- src/launcher/fdtransferServer_linux.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/launcher/fdtransferServer_linux.cpp b/src/launcher/fdtransferServer_linux.cpp index 03cb50044..b5c3f7cd4 100644 --- a/src/launcher/fdtransferServer_linux.cpp +++ b/src/launcher/fdtransferServer_linux.cpp @@ -298,6 +298,9 @@ bool FdTransferServer::runOnce(int pid, const char *path) { // CLONE_NEWPID affects children only - so we fork here. if (fork() == 0) { + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); return acceptPeer(&nspid) && serveRequests(nspid); } else { // Exit now, let our caller continue. From 87f9dff8617f40626db5549e9e96bf0c7256119d Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 30 Aug 2022 11:20:16 +0300 Subject: [PATCH 23/31] -static-libstdc++ only on musl --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4837b6e4a..a3b0efe9f 100644 --- a/Makefile +++ b/Makefile @@ -121,7 +121,10 @@ build/$(LAUNCHER): src/launcher/* src/jattach/* src/fdtransfer.h $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -DSUPPRESS_OUTPUT -o $@ src/launcher/*.cpp src/jattach/*.c strip $@ -PROFILER_STATIC_FLAGS=-static-libstdc++ -static-libgcc +PROFILER_STATIC_FLAGS=-static-libgcc +ifeq ($(OS_TAG),linux-musl) + PROFILER_STATIC_FLAGS+= -static-libstdc++ +endif build/$(LIB_PROFILER): $(SOURCES) $(HEADERS) $(RESOURCES) $(JAVA_HELPER_CLASSES) ifeq ($(MERGE),true) From 99e87c85bcc329176bf706151e40df03ae974f7f Mon Sep 17 00:00:00 2001 From: marcin-ol Date: Thu, 27 Oct 2022 00:05:57 +0200 Subject: [PATCH 24/31] Convert frame name format to 'function (DSO)' for LIB style (#2) For https://github.com/Granulate/gprofiler/pull/491 --- src/codeCache.cpp | 8 +++++++- src/codeCache.h | 1 + src/frameName.cpp | 4 ++-- src/profiler.cpp | 16 ++++++++++++---- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/codeCache.cpp b/src/codeCache.cpp index 3465b9036..9e00accbd 100644 --- a/src/codeCache.cpp +++ b/src/codeCache.cpp @@ -41,6 +41,10 @@ size_t NativeFunc::usedMemory(const char* name) { CodeCache::CodeCache(const char* name, short lib_index, const void* min_address, const void* max_address) { _name = NativeFunc::create(name, -1); + char *tmp = (char*)malloc(strlen(name) + 3); + snprintf(tmp, strlen(name) + 3, "(%s)", name); + _lib_symbol = NativeFunc::create(tmp, -1); + free(tmp); _lib_index = lib_index; _min_address = min_address; _max_address = max_address; @@ -63,6 +67,7 @@ CodeCache::~CodeCache() { for (int i = 0; i < _count; i++) { NativeFunc::destroy(_blobs[i]._name); } + NativeFunc::destroy(_lib_symbol); NativeFunc::destroy(_name); delete[] _blobs; free(_dwarf_table); @@ -153,7 +158,8 @@ const char* CodeCache::binarySearch(const void* address) { if (low > 0 && (_blobs[low - 1]._start == _blobs[low - 1]._end || _blobs[low - 1]._end == address)) { return _blobs[low - 1]._name; } - return _name; + + return _lib_symbol; } const void* CodeCache::findSymbol(const char* name) { diff --git a/src/codeCache.h b/src/codeCache.h index 18a6cbf41..f4192c9cd 100644 --- a/src/codeCache.h +++ b/src/codeCache.h @@ -87,6 +87,7 @@ class FrameDesc; class CodeCache { protected: char* _name; + char* _lib_symbol; short _lib_index; const void* _min_address; const void* _max_address; diff --git a/src/frameName.cpp b/src/frameName.cpp index 08e1bfabd..601b654f1 100644 --- a/src/frameName.cpp +++ b/src/frameName.cpp @@ -133,7 +133,7 @@ const char* FrameName::decodeNativeSymbol(const char* name) { char* demangled = Demangle::demangle(name); if (demangled != NULL) { if (lib_name != NULL) { - _str.assign(lib_name).append("`").append(demangled); + _str.assign(demangled).append(" (").append(lib_name).append(")"); } else { _str.assign(demangled); } @@ -143,7 +143,7 @@ const char* FrameName::decodeNativeSymbol(const char* name) { } if (lib_name != NULL) { - return _str.assign(lib_name).append("`").append(name).c_str(); + return _str.assign(name).append(" (").append(lib_name).append(")").c_str(); } else { return name; } diff --git a/src/profiler.cpp b/src/profiler.cpp index bbb016404..bd51f1ef5 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -252,8 +252,7 @@ const char* Profiler::getLibraryName(const char* native_symbol) { if (lib_index >= 0 && lib_index < _native_libs.count()) { const char* s = _native_libs[lib_index]->name(); if (s != NULL) { - const char* p = strrchr(s, '/'); - return p != NULL ? p + 1 : s; + return s; } } return NULL; @@ -266,15 +265,24 @@ CodeCache* Profiler::findJvmLibrary(const char* lib_name) { CodeCache* Profiler::findLibraryByName(const char* lib_name) { const size_t lib_name_len = strlen(lib_name); const int native_lib_count = _native_libs.count(); + int basename_match_i = -1; for (int i = 0; i < native_lib_count; i++) { const char* s = _native_libs[i]->name(); if (s != NULL) { - const char* p = strrchr(s, '/'); - if (p != NULL && strncmp(p + 1, lib_name, lib_name_len) == 0) { + if (strncmp(s, lib_name, lib_name_len) == 0) { return _native_libs[i]; } + if (basename_match_i < 0) { + const char* p = strrchr(s, '/'); + if (p != NULL && strncmp(p + 1, lib_name, lib_name_len) == 0) { + basename_match_i = i; + } + } } } + if (basename_match_i >= 0) { + return _native_libs[basename_match_i]; + } return NULL; } From f83d0dc7642b30099d68e7c7f20b630cfbde1308 Mon Sep 17 00:00:00 2001 From: Yonatan Goldschmidt Date: Tue, 29 Nov 2022 17:37:19 +0200 Subject: [PATCH 25/31] Use compat-glibc on x86_64 glibc --- Makefile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index a3b0efe9f..e1d799540 100644 --- a/Makefile +++ b/Makefile @@ -121,17 +121,25 @@ build/$(LAUNCHER): src/launcher/* src/jattach/* src/fdtransfer.h $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -DSUPPRESS_OUTPUT -o $@ src/launcher/*.cpp src/jattach/*.c strip $@ -PROFILER_STATIC_FLAGS=-static-libgcc +PROFILER_FLAGS=-static-libgcc ifeq ($(OS_TAG),linux-musl) - PROFILER_STATIC_FLAGS+= -static-libstdc++ + PROFILER_FLAGS+= -static-libstdc++ +endif + +# On x86_64 glibc (not musl), build against compat-glibc +# see https://centos.pkgs.org/7/centos-x86_64/compat-glibc-2.12-4.el7.centos.x86_64.rpm.html +ifneq ($(OS_TAG),linux-musl) + ifeq ($(ARCH),x86_64) + PROFILER_FLAGS+= -I /usr/lib/x86_64-redhat-linux6E/include -B /usr/lib/x86_64-redhat-linux6E/lib64/ + endif endif build/$(LIB_PROFILER): $(SOURCES) $(HEADERS) $(RESOURCES) $(JAVA_HELPER_CLASSES) ifeq ($(MERGE),true) for f in src/*.cpp; do echo '#include "'$$f'"'; done |\ - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ -xc++ - $(LIBS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_FLAGS) -o $@ -xc++ - $(LIBS) else - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_STATIC_FLAGS) -o $@ $(SOURCES) $(LIBS) + $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" $(INCLUDES) -fPIC -shared $(PROFILER_FLAGS) -o $@ $(SOURCES) $(LIBS) endif build/$(API_JAR): $(API_SOURCES) From 677879968d3e794a34d5ab5d44fdc0faf5f1043e Mon Sep 17 00:00:00 2001 From: Guy Bortnikov Date: Tue, 29 Nov 2022 16:36:14 +0200 Subject: [PATCH 26/31] dump stats on stop --- src/arguments.cpp | 3 +++ src/arguments.h | 5 ++++- src/profiler.cpp | 10 ++++++++++ src/profiler.h | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index 336182eba..a9fb58833 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -364,6 +364,9 @@ Error Arguments::parse(const char* args) { CASE("reverse") _reverse = true; + CASE("meminfolog") + _log_meminfo_on_dump = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index 763017679..1bf82bade 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -184,6 +184,8 @@ class Arguments { const char* _title; double _minwidth; bool _reverse; + // Granulate Extra + bool _log_meminfo_on_dump; Arguments(bool persistent = false) : _buf(NULL), @@ -230,7 +232,8 @@ class Arguments { _end(NULL), _title(NULL), _minwidth(0), - _reverse(false) { + _reverse(false), + _log_meminfo_on_dump(false) { } ~Arguments(); diff --git a/src/profiler.cpp b/src/profiler.cpp index bd51f1ef5..ebfe3e961 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1568,6 +1568,10 @@ Error Profiler::runInternal(Arguments& args, std::ostream& out) { } case ACTION_DUMP: { Error error = dump(out, args); + if (args._log_meminfo_on_dump) { + logUsedMemory(); + } + if (error) { return error; } @@ -1685,3 +1689,9 @@ void Profiler::shutdown(Arguments& args) { _state = TERMINATED; } + +void Profiler::logUsedMemory() { + std::ostringstream stringStream; + printUsedMemory(stringStream); + Log::info("%s", stringStream.str().c_str()); +} diff --git a/src/profiler.h b/src/profiler.h index dc535725d..8e58b2046 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -200,6 +200,7 @@ class Profiler { Error stop(); Error flushJfr(); Error dump(std::ostream& out, Arguments& args); + void logUsedMemory(); void printUsedMemory(std::ostream& out); void switchThreadEvents(jvmtiEventMode mode); int convertNativeTrace(int native_frames, const void** callchain, ASGCT_CallFrame* frames); From 1f31fdca51ddacf5273629946892d2cc0453cab2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Po=C5=BAniak?= Date: Wed, 15 Mar 2023 12:33:01 +0100 Subject: [PATCH 27/31] Add option to include method modifiers in frame name (#5) async-profiler side of https://github.com/Granulate/gprofiler/issues/570. --- src/arguments.cpp | 3 +++ src/arguments.h | 4 +++- src/frameName.cpp | 31 ++++++++++++++++++++++++++++++- src/frameName.h | 1 + 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index a9fb58833..8bcc21b39 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -367,6 +367,9 @@ Error Arguments::parse(const char* args) { CASE("meminfolog") _log_meminfo_on_dump = true; + CASE("includemm") + _includemm = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index 1bf82bade..9151dbffd 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -166,6 +166,7 @@ class Arguments { bool _sched; bool _live; bool _fdtransfer; + bool _includemm; const char* _fdtransfer_path; int _style; CStack _cstack; @@ -233,7 +234,8 @@ class Arguments { _title(NULL), _minwidth(0), _reverse(false), - _log_meminfo_on_dump(false) { + _log_meminfo_on_dump(false), + _includemm(false) { } ~Arguments(); diff --git a/src/frameName.cpp b/src/frameName.cpp index 601b654f1..448359ea5 100644 --- a/src/frameName.cpp +++ b/src/frameName.cpp @@ -28,6 +28,24 @@ static inline bool isDigit(char c) { } +// Based on: https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#:~:text=Table%C2%A04.5.%C2%A0Method%20access%20and%20property%20flags +// Good practice order from: https://checkstyle.sourceforge.io/config_modifier.html#ModifierOrder +const static std::pair access_flags [] = { + std::make_pair(0x0001, "public"), + std::make_pair(0x0002, "private"), + std::make_pair(0x0004, "protected"), + std::make_pair(0x0400, "abstract"), + std::make_pair(0x0008, "static"), + std::make_pair(0x0010, "final"), + std::make_pair(0x0020, "synchronized"), + std::make_pair(0x0100, "native"), + std::make_pair(0x0800, "strict"), + std::make_pair(0x0040, "bridge"), + std::make_pair(0x0080, "varargs"), + std::make_pair(0x1000, "synthetic"), +}; + + Matcher::Matcher(const char* pattern) { if (pattern[0] == '*') { _type = MATCH_ENDS_WITH; @@ -95,7 +113,7 @@ FrameName::FrameName(Arguments& args, int style, int epoch, Mutex& thread_names_ { // Require printf to use standard C format regardless of system locale _saved_locale = uselocale(newlocale(LC_NUMERIC_MASK, "C", (locale_t)0)); - + _includemm = args._includemm; buildFilter(_include, args._buf, args._include); buildFilter(_exclude, args._buf, args._exclude); @@ -167,6 +185,7 @@ void FrameName::javaMethodName(jmethodID method) { char* class_name = NULL; char* method_name = NULL; char* method_sig = NULL; + jint modifiers = 0; jvmtiEnv* jvmti = VM::jvmti(); jvmtiError err; @@ -176,6 +195,16 @@ void FrameName::javaMethodName(jmethodID method) { (err = jvmti->GetClassSignature(method_class, &class_name, NULL)) == 0) { // Trim 'L' and ';' off the class descriptor like 'Ljava/lang/Object;' javaClassName(class_name + 1, strlen(class_name) - 2, _style); + if (_includemm) { + jvmti->GetMethodModifiers(method, &modifiers); + std::string modifiers_to_append = ""; + for (int i=0; i<(sizeof(access_flags) / sizeof(access_flags[0])); i++) { + if (modifiers & access_flags[i].first) { + modifiers_to_append.append(access_flags[i].second + " "); + } + } + _str.insert(0, modifiers_to_append); + } _str.append(".").append(method_name); if (_style & STYLE_SIGNATURES) { if (_style & STYLE_NO_SEMICOLON) { diff --git a/src/frameName.h b/src/frameName.h index 26d8e837c..e8cea7ad4 100644 --- a/src/frameName.h +++ b/src/frameName.h @@ -75,6 +75,7 @@ class FrameName { Mutex& _thread_names_lock; ThreadMap& _thread_names; locale_t _saved_locale; + bool _includemm; void buildFilter(std::vector& vector, const char* base, int offset); const char* decodeNativeSymbol(const char* name); From b3baf6010e31378679a28fe1cd30168f51cc1ade Mon Sep 17 00:00:00 2001 From: marcin-ol Date: Wed, 10 May 2023 13:29:49 +0200 Subject: [PATCH 28/31] Export gProfiler-needed functionality from asprof (#7) --- Makefile | 4 +- src/launcher/fdtransferServer.h | 4 +- src/launcher/fdtransferServer_linux.cpp | 4 +- src/launcher/main.cpp | 98 +++++++++++++++++++++---- 4 files changed, 89 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index e1d799540..e70949107 100644 --- a/Makefile +++ b/Makefile @@ -118,7 +118,7 @@ build/%: mkdir -p $@ build/$(LAUNCHER): src/launcher/* src/jattach/* src/fdtransfer.h - $(CC) $(CPPFLAGS) $(CFLAGS) -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -DSUPPRESS_OUTPUT -o $@ src/launcher/*.cpp src/jattach/*.c + $(CC) $(CPPFLAGS) $(CFLAGS) -static -DPROFILER_VERSION=\"$(PROFILER_VERSION)\" -o $@ src/launcher/*.cpp src/jattach/*.c strip $@ PROFILER_FLAGS=-static-libgcc @@ -155,7 +155,7 @@ build/$(CONVERTER_JAR): $(CONVERTER_SOURCES) $(RESOURCES) $(RM) -r build/converter %.class: %.java - $(JAVAC) --source $(JAVA_TARGET) -target $(JAVA_TARGET) -Xlint:-options -g:none $^ + $(JAVAC) -source $(JAVA_TARGET) -target $(JAVA_TARGET) -Xlint:-options -g:none $^ test: all test/smoke-test.sh diff --git a/src/launcher/fdtransferServer.h b/src/launcher/fdtransferServer.h index d234e8cc8..07ce4ff3e 100644 --- a/src/launcher/fdtransferServer.h +++ b/src/launcher/fdtransferServer.h @@ -36,7 +36,7 @@ class FdTransferServer { public: static bool supported() { return true; } - static bool runOnce(int pid, const char *path); + static bool runOnce(int pid, const char *path, unsigned int timeout); static bool runLoop(const char *path); }; @@ -46,7 +46,7 @@ class FdTransferServer { public: static bool supported() { return false; } - static bool runOnce(int pid, const char *path) { return false; } + static bool runOnce(int pid, const char *path, unsigned int timeout) { return false; } static bool runLoop(const char *path) { return false; } }; diff --git a/src/launcher/fdtransferServer_linux.cpp b/src/launcher/fdtransferServer_linux.cpp index b5c3f7cd4..193e32f5a 100644 --- a/src/launcher/fdtransferServer_linux.cpp +++ b/src/launcher/fdtransferServer_linux.cpp @@ -260,7 +260,7 @@ bool FdTransferServer::sendFd(int fd, struct fd_response *resp, size_t resp_size return true; } -bool FdTransferServer::runOnce(int pid, const char *path) { +bool FdTransferServer::runOnce(int pid, const char *path, unsigned int timeout) { // get its nspid prior to moving to its PID namespace. int nspid; uid_t target_uid; @@ -287,7 +287,7 @@ bool FdTransferServer::runOnce(int pid, const char *path) { } } - if (!bindServer(&sun, addrlen, 30)) { + if (!bindServer(&sun, addrlen, timeout)) { return false; } diff --git a/src/launcher/main.cpp b/src/launcher/main.cpp index ea3a64506..c2455e964 100644 --- a/src/launcher/main.cpp +++ b/src/launcher/main.cpp @@ -51,6 +51,10 @@ static const char USAGE_STRING[] = " list list profiling events supported by the target JVM\n" " collect collect profile for the specified period of time\n" " and then stop (default action)\n" + " fdtransfer start fdtransfer to serve perf requests on behalf of profiled process\n" + " jattach invoke jattach directly; requires --jattach-cmd,\n" + " ignores all arguments except --lib-path\n" + "\n" "Options:\n" " -e event profiling event: cpu|alloc|lock|cache-misses etc.\n" " -d duration run profiling for seconds\n" @@ -87,6 +91,11 @@ static const char USAGE_STRING[] = " --jfrsync config synchronize profiler with JFR recording\n" " --fdtransfer use fdtransfer to serve perf requests\n" " from the non-privileged target\n" + " --jattach-cmd string\n" + " arguments to use with jattach action\n" + " -L|--lib-path string\n" + " path to async-profiler's shared lib\n" + " --fd-path string socket path for fdtransfer to bind to\n" "\n" " is a numeric process ID of the target JVM\n" " or 'jps' keyword to find running JVM automatically\n" @@ -97,6 +106,7 @@ static const char USAGE_STRING[] = " " APP_BINARY " stop -o flat jps\n" " " APP_BINARY " -d 5 -e alloc MyAppName\n"; +static const unsigned int DEFAULT_FDTRANSFER_TIMEOUT = 30; extern "C" int jattach(int pid, int argc, const char** argv); @@ -170,6 +180,10 @@ class String { return strcmp(_str, other._str) == 0; } + bool operator!=(const String& other) const { + return !(*this == other); + } + String& operator<<(const char* tail) { size_t len = strlen(_str); _str = (char*)realloc(_str, len + strlen(tail) + 1); @@ -205,11 +219,16 @@ class String { static String action = "collect"; +static const String kEmpty; +static const String kJattachLoad = "load"; +static const String kJattachJcmd = "jcmd"; static String file, logfile, output, params, format, fdtransfer, libpath; static bool use_tmp_file = false; static int duration = 60; static int pid = 0; static volatile unsigned long long end_time; +// gprofiler-specific: holds timeout value for fdtransfer command +static unsigned int fdtransfer_timeout = DEFAULT_FDTRANSFER_TIMEOUT; static void sigint_handler(int sig) { end_time = 0; @@ -314,7 +333,7 @@ static int jps(const char* cmd, const char* app_name = NULL) { return pid; } -static void run_fdtransfer(int pid, String& fdtransfer) { +static void run_fdtransfer(int pid, String& fdtransfer, unsigned int timeout) { if (!FdTransferServer::supported() || fdtransfer == "") return; pid_t child = fork(); @@ -323,7 +342,7 @@ static void run_fdtransfer(int pid, String& fdtransfer) { } if (child == 0) { - exit(FdTransferServer::runOnce(pid, fdtransfer.str()) ? 0 : 1); + exit(FdTransferServer::runOnce(pid, fdtransfer.str(), timeout) ? 0 : 1); } else { int ret = wait_for_exit(child); if (ret != 0) { @@ -332,26 +351,31 @@ static void run_fdtransfer(int pid, String& fdtransfer) { } } -static void run_jattach(int pid, String& cmd) { +static void run_jattach(int pid, const String& verb, String& cmd) { pid_t child = fork(); if (child == -1) { error("fork failed", errno); } if (child == 0) { - const char* argv[] = {"load", libpath.str(), libpath.str()[0] == '/' ? "true" : "false", cmd.str()}; - exit(jattach(pid, 4, argv)); + if (verb == kJattachLoad) { + const char* args[] = {kJattachLoad.str(), libpath.str(), libpath.str()[0] == '/' ? "true" : "false", cmd.str()}; + exit(jattach(pid, 4, args)); + } else if (verb == kJattachJcmd) { + const char* args[] = {kJattachJcmd.str(), cmd.str()}; + exit(jattach(pid, 2, args)); + } else { exit (1); } } else { int ret = wait_for_exit(child); if (ret != 0) { if (WEXITSTATUS(ret) == 255) { fprintf(stderr, "Target JVM failed to load %s\n", libpath.str()); } - print_file(logfile, STDERR_FILENO); + if (logfile != kEmpty) print_file(logfile, STDERR_FILENO); exit(WEXITSTATUS(ret)); } - print_file(logfile, STDERR_FILENO); + if (logfile != kEmpty) print_file(logfile, STDERR_FILENO); if (use_tmp_file) print_file(file, STDOUT_FILENO); } } @@ -359,11 +383,13 @@ static void run_jattach(int pid, String& cmd) { int main(int argc, const char** argv) { Args args(argc, argv); + String jattach_cmd; while (args.hasNext()) { String arg = args.next(); if (arg == "start" || arg == "resume" || arg == "stop" || arg == "dump" || arg == "check" || - arg == "status" || arg == "meminfo" || arg == "list" || arg == "collect") { + arg == "status" || arg == "meminfo" || arg == "list" || arg == "collect" || + arg == "fdtransfer" || arg == "jattach" || arg == "jcmd") { action = arg; } else if (arg == "-h" || arg == "--help") { @@ -454,14 +480,24 @@ int main(int argc, const char** argv) { } else if (arg == "--timeout" || arg == "--loop") { params << "," << (arg.str() + 2) << "=" << args.next(); + if (action == "collect") action = "start"; + } else if (arg == "--fdtransfer-timeout") { + fdtransfer_timeout = atoi(args.next()); + + } else if (arg == "--fd-path") { + fdtransfer = String(args.next()); + } else if (arg == "--fdtransfer") { char buf[64]; snprintf(buf, sizeof(buf), "@async-profiler-%d-%08x", getpid(), (unsigned int)time_micros()); fdtransfer = buf; params << ",fdtransfer=" << fdtransfer; + } else if (arg == "--jattach-cmd") { + jattach_cmd = String(args.next()); + } else if (arg.str()[0] >= '0' && arg.str()[0] <= '9' && pid == 0) { pid = atoi(arg.str()); @@ -474,6 +510,9 @@ int main(int argc, const char** argv) { // The last argument is the application name as it would appear in the jps tool pid = jps("jps -J-XX:+PerfDisableSharedMem", arg.str()); + } else if (arg == "-L" || arg == "--lib-path") { + libpath = String(args.next()); + } else { fprintf(stderr, "Unrecognized option: %s\n", arg.str()); return 1; @@ -485,12 +524,20 @@ int main(int argc, const char** argv) { return 1; } - setup_output_files(pid); - setup_lib_path(); + if (jattach_cmd == kEmpty) { + setup_output_files(pid); + } else if (params != kEmpty) { + fprintf(stderr, "Argument --jattach-cmd was given, need no other parameters\n"); + return 1; + } + + if (libpath == kEmpty) { + setup_lib_path(); + } if (action == "collect") { - run_fdtransfer(pid, fdtransfer); - run_jattach(pid, String("start,file=") << file << "," << output << format << params << ",log=" << logfile); + run_fdtransfer(pid, fdtransfer, 0); + run_jattach(pid, kJattachLoad, String("start,file=") << file << "," << output << format << params << ",log=" << logfile); fprintf(stderr, "Profiling for %d seconds\n", duration); end_time = time_micros() + duration * 1000000ULL; @@ -508,10 +555,31 @@ int main(int argc, const char** argv) { signal(SIGINT, SIG_DFL); fprintf(stderr, "Done\n"); - run_jattach(pid, String("stop,file=") << file << "," << output << format << ",log=" << logfile); + run_jattach(pid, kJattachLoad, String("stop,file=") << file << "," << output << format << ",log=" << logfile); + } else if (action == "fdtransfer") { + if (params != kEmpty) { + fprintf(stderr, "Action fdtransfer was given, all parameters are to be passed with --jattach-cmd\n"); + return 1; + } + run_fdtransfer(pid, fdtransfer, fdtransfer_timeout); + + } else if (action == "jattach") { + if (jattach_cmd == kEmpty) { + fprintf(stderr, "Action jattach was given, missing required --jattach-cmd argument\n"); + return 1; + } + run_jattach(pid, kJattachLoad, jattach_cmd); + + } else if (action == "jcmd") { + if (jattach_cmd == kEmpty) { + fprintf(stderr, "Action jcmd was given, missing required --jattach-cmd argument\n"); + return 1; + } + run_jattach(pid, kJattachJcmd, jattach_cmd); + } else { - if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer); - run_jattach(pid, String(action) << ",file=" << file << "," << output << format << params << ",log=" << logfile); + if (action == "start" || action == "resume") run_fdtransfer(pid, fdtransfer, 0); + run_jattach(pid, kJattachLoad, String(action) << ",file=" << file << "," << output << format << params << ",log=" << logfile); } return 0; From 46a6883d084e443a0b2a91ba9208302e65fe216a Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Wed, 19 Jul 2023 14:36:22 +0200 Subject: [PATCH 29/31] Add reset trace functionality --- src/arguments.cpp | 3 +++ src/arguments.h | 4 +++- src/profiler.cpp | 15 +++++++++++++++ src/profiler.h | 1 + 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index 359cf48f6..bf5c63327 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -375,6 +375,9 @@ Error Arguments::parse(const char* args) { CASE("recycle") _recycle = true; + CASE("resettrace") + _reset_trace = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index 63e09fdb3..87edaa8ad 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -188,6 +188,7 @@ class Arguments { // Granulate Extra bool _log_meminfo_on_dump; bool _recycle; + bool _reset_trace; Arguments(bool persistent = false) : _buf(NULL), @@ -237,7 +238,8 @@ class Arguments { _reverse(false), _log_meminfo_on_dump(false), _includemm(false), - _recycle(false) { + _recycle(false), + _reset_trace(false) { } ~Arguments(); diff --git a/src/profiler.cpp b/src/profiler.cpp index 7501d2fa5..88350c072 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1234,6 +1234,9 @@ Error Profiler::dump(std::ostream& out, Arguments& args) { default: return Error("No output format selected"); } + if (args._reset_trace) { + resetTrace(); + } return Error::OK; } @@ -1555,6 +1558,18 @@ void Profiler::timerThreadEntry(jvmtiEnv* jvmti, JNIEnv* jni, void* arg) { instance()->timerLoop(arg); } +void Profiler::resetTrace() { + // Reset traces for next collection round, to get comparable outcomes from dump. + // Must be called under _state_lock mutex + _total_samples = 0; + memset(_failures, 0, sizeof(_failures)); + + // Reset call trace storage + lockAll(); + _call_trace_storage.clear(); + unlockAll(); +} + void Profiler::recycleTimeoutTimer(Arguments& args) { MutexLocker ml(_timer_lock); if (_timer_id != NULL) { diff --git a/src/profiler.h b/src/profiler.h index 9b2ed1f1a..92102971d 100644 --- a/src/profiler.h +++ b/src/profiler.h @@ -144,6 +144,7 @@ class Profiler { void stopTimer(); void timerLoop(void* timer_id); static void timerThreadEntry(jvmtiEnv* jvmti, JNIEnv* jni, void* arg); + void resetTrace(); void recycleTimeoutTimer(Arguments& args); void lockAll(); From 7d2c6abcc0b371fa0976f60cf88fbce0f4e60dc8 Mon Sep 17 00:00:00 2001 From: Marcin Olszewski Date: Thu, 20 Jul 2023 18:02:31 +0200 Subject: [PATCH 30/31] Add dumpactive flag to verify dump is called when actively profiling --- src/arguments.cpp | 3 +++ src/arguments.h | 4 +++- src/profiler.cpp | 3 ++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index bf5c63327..b039fef9d 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -378,6 +378,9 @@ Error Arguments::parse(const char* args) { CASE("resettrace") _reset_trace = true; + CASE("dumpactive") + _dump_active = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index 87edaa8ad..80c3bba05 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -189,6 +189,7 @@ class Arguments { bool _log_meminfo_on_dump; bool _recycle; bool _reset_trace; + bool _dump_active; Arguments(bool persistent = false) : _buf(NULL), @@ -239,7 +240,8 @@ class Arguments { _log_meminfo_on_dump(false), _includemm(false), _recycle(false), - _reset_trace(false) { + _reset_trace(false), + _dump_active(false) { } ~Arguments(); diff --git a/src/profiler.cpp b/src/profiler.cpp index 88350c072..2a9583fe2 100644 --- a/src/profiler.cpp +++ b/src/profiler.cpp @@ -1199,7 +1199,8 @@ Error Profiler::flushJfr() { Error Profiler::dump(std::ostream& out, Arguments& args) { MutexLocker ml(_state_lock); - if (_state != IDLE && _state != RUNNING) { + // in dump-active make sure profiler is not idle + if ((_state != IDLE || args._dump_active) && _state != RUNNING) { return Error("Profiler has not started"); } From 40b850a4101756bc398051661d1adbbe5d7e2211 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Po=C5=BAniak?= Date: Tue, 25 Jul 2023 12:08:16 +0200 Subject: [PATCH 31/31] Add includeln argument which includes method line number to frame (#8) gProfiler PR: https://github.com/Granulate/gprofiler/pull/821 --- src/arguments.cpp | 3 +++ src/arguments.h | 4 +++- src/frameName.cpp | 10 ++++++++++ src/frameName.h | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/arguments.cpp b/src/arguments.cpp index 8bcc21b39..29712cd21 100644 --- a/src/arguments.cpp +++ b/src/arguments.cpp @@ -370,6 +370,9 @@ Error Arguments::parse(const char* args) { CASE("includemm") _includemm = true; + CASE("includeln") + _includeln = true; + DEFAULT() if (_unknown_arg == NULL) _unknown_arg = arg; } diff --git a/src/arguments.h b/src/arguments.h index 9151dbffd..568d46efd 100644 --- a/src/arguments.h +++ b/src/arguments.h @@ -167,6 +167,7 @@ class Arguments { bool _live; bool _fdtransfer; bool _includemm; + bool _includeln; const char* _fdtransfer_path; int _style; CStack _cstack; @@ -235,7 +236,8 @@ class Arguments { _minwidth(0), _reverse(false), _log_meminfo_on_dump(false), - _includemm(false) { + _includemm(false), + _includeln(false) { } ~Arguments(); diff --git a/src/frameName.cpp b/src/frameName.cpp index 448359ea5..9e01ae9c5 100644 --- a/src/frameName.cpp +++ b/src/frameName.cpp @@ -114,6 +114,7 @@ FrameName::FrameName(Arguments& args, int style, int epoch, Mutex& thread_names_ // Require printf to use standard C format regardless of system locale _saved_locale = uselocale(newlocale(LC_NUMERIC_MASK, "C", (locale_t)0)); _includemm = args._includemm; + _includeln = args._includeln; buildFilter(_include, args._buf, args._include); buildFilter(_exclude, args._buf, args._exclude); @@ -185,6 +186,8 @@ void FrameName::javaMethodName(jmethodID method) { char* class_name = NULL; char* method_name = NULL; char* method_sig = NULL; + jvmtiLineNumberEntry* line_number_table = NULL; + jint entry_count = 0; jint modifiers = 0; jvmtiEnv* jvmti = VM::jvmti(); @@ -206,6 +209,13 @@ void FrameName::javaMethodName(jmethodID method) { _str.insert(0, modifiers_to_append); } _str.append(".").append(method_name); + if (_includeln) { + if (jvmti->GetLineNumberTable(method, &entry_count, &line_number_table) == 0) { + char buf[32]; + sprintf(buf, ":%d", line_number_table[0].line_number); + _str.append(buf); + } + } if (_style & STYLE_SIGNATURES) { if (_style & STYLE_NO_SEMICOLON) { for (char* s = method_sig; *s; s++) { diff --git a/src/frameName.h b/src/frameName.h index e8cea7ad4..5139e4731 100644 --- a/src/frameName.h +++ b/src/frameName.h @@ -76,6 +76,7 @@ class FrameName { ThreadMap& _thread_names; locale_t _saved_locale; bool _includemm; + bool _includeln; void buildFilter(std::vector& vector, const char* base, int offset); const char* decodeNativeSymbol(const char* name);