jruby-async-profiler 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +8 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/README.md +35 -0
  6. data/Rakefile +2 -0
  7. data/bin/console +14 -0
  8. data/bin/setup +8 -0
  9. data/ext/Rakefile +6 -0
  10. data/ext/async-profiler/.gitattributes +1 -0
  11. data/ext/async-profiler/.gitignore +6 -0
  12. data/ext/async-profiler/.travis.yml +11 -0
  13. data/ext/async-profiler/CHANGELOG.md +107 -0
  14. data/ext/async-profiler/JavaHome.class +0 -0
  15. data/ext/async-profiler/LICENSE +201 -0
  16. data/ext/async-profiler/Makefile +66 -0
  17. data/ext/async-profiler/README.md +487 -0
  18. data/ext/async-profiler/demo/SwingSet2.svg +2247 -0
  19. data/ext/async-profiler/docs/cddl1.txt +358 -0
  20. data/ext/async-profiler/profiler.sh +240 -0
  21. data/ext/async-profiler/src/allocTracer.cpp +155 -0
  22. data/ext/async-profiler/src/allocTracer.h +74 -0
  23. data/ext/async-profiler/src/arch.h +69 -0
  24. data/ext/async-profiler/src/arguments.cpp +265 -0
  25. data/ext/async-profiler/src/arguments.h +152 -0
  26. data/ext/async-profiler/src/codeCache.cpp +128 -0
  27. data/ext/async-profiler/src/codeCache.h +99 -0
  28. data/ext/async-profiler/src/engine.cpp +50 -0
  29. data/ext/async-profiler/src/engine.h +38 -0
  30. data/ext/async-profiler/src/flameGraph.cpp +770 -0
  31. data/ext/async-profiler/src/flameGraph.h +118 -0
  32. data/ext/async-profiler/src/flightRecorder.cpp +727 -0
  33. data/ext/async-profiler/src/flightRecorder.h +39 -0
  34. data/ext/async-profiler/src/frameName.cpp +189 -0
  35. data/ext/async-profiler/src/frameName.h +56 -0
  36. data/ext/async-profiler/src/itimer.cpp +49 -0
  37. data/ext/async-profiler/src/itimer.h +43 -0
  38. data/ext/async-profiler/src/jattach/jattach.c +437 -0
  39. data/ext/async-profiler/src/java/one/profiler/AsyncProfiler.java +160 -0
  40. data/ext/async-profiler/src/java/one/profiler/AsyncProfilerMXBean.java +43 -0
  41. data/ext/async-profiler/src/java/one/profiler/Counter.java +25 -0
  42. data/ext/async-profiler/src/java/one/profiler/Events.java +28 -0
  43. data/ext/async-profiler/src/javaApi.cpp +124 -0
  44. data/ext/async-profiler/src/lockTracer.cpp +161 -0
  45. data/ext/async-profiler/src/lockTracer.h +55 -0
  46. data/ext/async-profiler/src/mutex.cpp +33 -0
  47. data/ext/async-profiler/src/mutex.h +49 -0
  48. data/ext/async-profiler/src/os.h +45 -0
  49. data/ext/async-profiler/src/os_linux.cpp +129 -0
  50. data/ext/async-profiler/src/os_macos.cpp +115 -0
  51. data/ext/async-profiler/src/perfEvents.h +60 -0
  52. data/ext/async-profiler/src/perfEvents_linux.cpp +550 -0
  53. data/ext/async-profiler/src/perfEvents_macos.cpp +64 -0
  54. data/ext/async-profiler/src/profiler.cpp +952 -0
  55. data/ext/async-profiler/src/profiler.h +238 -0
  56. data/ext/async-profiler/src/spinLock.h +66 -0
  57. data/ext/async-profiler/src/stackFrame.h +57 -0
  58. data/ext/async-profiler/src/stackFrame_aarch64.cpp +75 -0
  59. data/ext/async-profiler/src/stackFrame_arm.cpp +58 -0
  60. data/ext/async-profiler/src/stackFrame_i386.cpp +82 -0
  61. data/ext/async-profiler/src/stackFrame_x64.cpp +113 -0
  62. data/ext/async-profiler/src/symbols.h +37 -0
  63. data/ext/async-profiler/src/symbols_linux.cpp +354 -0
  64. data/ext/async-profiler/src/symbols_macos.cpp +156 -0
  65. data/ext/async-profiler/src/vmEntry.cpp +173 -0
  66. data/ext/async-profiler/src/vmEntry.h +105 -0
  67. data/ext/async-profiler/src/vmStructs.cpp +104 -0
  68. data/ext/async-profiler/src/vmStructs.h +112 -0
  69. data/ext/async-profiler/src/wallClock.cpp +96 -0
  70. data/ext/async-profiler/src/wallClock.h +56 -0
  71. data/ext/async-profiler/test/AllocatingTarget.java +26 -0
  72. data/ext/async-profiler/test/LoadLibraryTest.java +21 -0
  73. data/ext/async-profiler/test/Target.java +31 -0
  74. data/ext/async-profiler/test/ThreadsTarget.java +35 -0
  75. data/ext/async-profiler/test/alloc-smoke-test.sh +36 -0
  76. data/ext/async-profiler/test/load-library-test.sh +35 -0
  77. data/ext/async-profiler/test/smoke-test.sh +37 -0
  78. data/ext/async-profiler/test/thread-smoke-test.sh +32 -0
  79. data/jruby-async-profiler.gemspec +32 -0
  80. data/lib/jruby/async/profiler.rb +10 -0
  81. data/lib/jruby/async/profiler/version.rb +7 -0
  82. metadata +155 -0
@@ -0,0 +1,55 @@
1
+ /*
2
+ * Copyright 2017 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _LOCKTRACER_H
18
+ #define _LOCKTRACER_H
19
+
20
+ #include <jvmti.h>
21
+ #include "engine.h"
22
+
23
+
24
+ typedef void (JNICALL *UnsafeParkFunc)(JNIEnv*, jobject, jboolean, jlong);
25
+
26
+ class LockTracer : public Engine {
27
+ private:
28
+ static jlong _start_time;
29
+ static jclass _LockSupport;
30
+ static jmethodID _getBlocker;
31
+ static UnsafeParkFunc _original_Unsafe_Park;
32
+ static bool _supports_lock_names;
33
+
34
+ static jclass getParkBlockerClass(jvmtiEnv* jvmti, JNIEnv* env);
35
+ static void recordContendedLock(jclass lock_class, jlong time);
36
+ static void bindUnsafePark(UnsafeParkFunc entry);
37
+
38
+ public:
39
+ const char* name() {
40
+ return "lock";
41
+ }
42
+
43
+ const char* units() {
44
+ return "ns";
45
+ }
46
+
47
+ Error start(Arguments& args);
48
+ void stop();
49
+
50
+ static void JNICALL MonitorContendedEnter(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jobject object);
51
+ static void JNICALL MonitorContendedEntered(jvmtiEnv* jvmti, JNIEnv* env, jthread thread, jobject object);
52
+ static void JNICALL UnsafeParkTrap(JNIEnv* env, jobject instance, jboolean isAbsolute, jlong time);
53
+ };
54
+
55
+ #endif // _LOCKTRACER_H
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Copyright 2018 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #include "mutex.h"
18
+
19
+
20
+ Mutex::Mutex() {
21
+ pthread_mutexattr_t attr;
22
+ pthread_mutexattr_init(&attr);
23
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
24
+ pthread_mutex_init(&_mutex, &attr);
25
+ }
26
+
27
+ void Mutex::lock() {
28
+ pthread_mutex_lock(&_mutex);
29
+ }
30
+
31
+ void Mutex::unlock() {
32
+ pthread_mutex_unlock(&_mutex);
33
+ }
@@ -0,0 +1,49 @@
1
+ /*
2
+ * Copyright 2018 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _MUTEX_H
18
+ #define _MUTEX_H
19
+
20
+ #include <pthread.h>
21
+
22
+
23
+ class Mutex {
24
+ private:
25
+ pthread_mutex_t _mutex;
26
+
27
+ public:
28
+ Mutex();
29
+
30
+ void lock();
31
+ void unlock();
32
+ };
33
+
34
+
35
+ class MutexLocker {
36
+ private:
37
+ Mutex* _mutex;
38
+
39
+ public:
40
+ MutexLocker(Mutex& mutex) : _mutex(&mutex) {
41
+ _mutex->lock();
42
+ }
43
+
44
+ ~MutexLocker() {
45
+ _mutex->unlock();
46
+ }
47
+ };
48
+
49
+ #endif // _MUTEX_H
@@ -0,0 +1,45 @@
1
+ /*
2
+ * Copyright 2018 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _OS_H
18
+ #define _OS_H
19
+
20
+ #include <signal.h>
21
+ #include "arch.h"
22
+
23
+
24
+ class ThreadList {
25
+ public:
26
+ virtual ~ThreadList() {}
27
+ virtual int next() = 0;
28
+ };
29
+
30
+
31
+ class OS {
32
+ public:
33
+ static u64 nanotime();
34
+ static u64 millis();
35
+ static u64 hton64(u64 x);
36
+ static int threadId();
37
+ static bool isThreadRunning(int thread_id);
38
+ static bool isSignalSafeTLS();
39
+ static bool isJavaLibraryVisible();
40
+ static void installSignalHandler(int signo, void (*handler)(int, siginfo_t*, void*));
41
+ static void sendSignalToThread(int thread_id, int signo);
42
+ static ThreadList* listThreads();
43
+ };
44
+
45
+ #endif // _OS_H
@@ -0,0 +1,129 @@
1
+ /*
2
+ * Copyright 2018 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifdef __linux__
18
+
19
+ #include <arpa/inet.h>
20
+ #include <byteswap.h>
21
+ #include <dirent.h>
22
+ #include <fcntl.h>
23
+ #include <stdio.h>
24
+ #include <stdlib.h>
25
+ #include <string.h>
26
+ #include <sys/stat.h>
27
+ #include <sys/syscall.h>
28
+ #include <sys/time.h>
29
+ #include <sys/types.h>
30
+ #include <time.h>
31
+ #include <unistd.h>
32
+ #include "os.h"
33
+
34
+
35
+ class LinuxThreadList : public ThreadList {
36
+ private:
37
+ DIR* _dir;
38
+
39
+ public:
40
+ LinuxThreadList() {
41
+ _dir = opendir("/proc/self/task");
42
+ }
43
+
44
+ ~LinuxThreadList() {
45
+ if (_dir != NULL) {
46
+ closedir(_dir);
47
+ }
48
+ }
49
+
50
+ int next() {
51
+ if (_dir != NULL) {
52
+ struct dirent* entry;
53
+ while ((entry = readdir(_dir)) != NULL) {
54
+ if (entry->d_name[0] != '.') {
55
+ return atoi(entry->d_name);
56
+ }
57
+ }
58
+ }
59
+ return -1;
60
+ }
61
+ };
62
+
63
+
64
+ u64 OS::nanotime() {
65
+ struct timespec tp;
66
+ clock_gettime(CLOCK_MONOTONIC, &tp);
67
+ return (u64)tp.tv_sec * 1000000000 + tp.tv_nsec;
68
+ }
69
+
70
+ u64 OS::millis() {
71
+ struct timeval tv;
72
+ gettimeofday(&tv, NULL);
73
+ return (u64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
74
+ }
75
+
76
+ u64 OS::hton64(u64 x) {
77
+ return htonl(1) == 1 ? x : bswap_64(x);
78
+ }
79
+
80
+ int OS::threadId() {
81
+ return syscall(__NR_gettid);
82
+ }
83
+
84
+ bool OS::isThreadRunning(int thread_id) {
85
+ char buf[512];
86
+ sprintf(buf, "/proc/self/task/%d/stat", thread_id);
87
+ int fd = open(buf, O_RDONLY);
88
+ if (fd == -1) {
89
+ return false;
90
+ }
91
+
92
+ bool running = false;
93
+ if (read(fd, buf, sizeof(buf)) > 0) {
94
+ char* s = strchr(buf, ')');
95
+ running = s != NULL && (s[2] == 'R' || s[2] == 'D');
96
+ }
97
+
98
+ close(fd);
99
+ return running;
100
+ }
101
+
102
+ bool OS::isSignalSafeTLS() {
103
+ return true;
104
+ }
105
+
106
+ bool OS::isJavaLibraryVisible() {
107
+ return false;
108
+ }
109
+
110
+ void OS::installSignalHandler(int signo, void (*handler)(int, siginfo_t*, void*)) {
111
+ struct sigaction sa;
112
+ sigemptyset(&sa.sa_mask);
113
+ sa.sa_sigaction = handler;
114
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
115
+
116
+ sigaction(signo, &sa, NULL);
117
+ }
118
+
119
+ void OS::sendSignalToThread(int thread_id, int signo) {
120
+ static const int self_pid = getpid();
121
+
122
+ syscall(__NR_tgkill, self_pid, thread_id, signo);
123
+ }
124
+
125
+ ThreadList* OS::listThreads() {
126
+ return new LinuxThreadList();
127
+ }
128
+
129
+ #endif // __linux__
@@ -0,0 +1,115 @@
1
+ /*
2
+ * Copyright 2018 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifdef __APPLE__
18
+
19
+ #include <libkern/OSByteOrder.h>
20
+ #include <mach/mach.h>
21
+ #include <mach/mach_time.h>
22
+ #include <sys/time.h>
23
+ #include "os.h"
24
+
25
+
26
+ class MacThreadList : public ThreadList {
27
+ private:
28
+ thread_array_t _thread_array;
29
+ unsigned int _thread_count;
30
+ unsigned int _thread_index;
31
+
32
+ public:
33
+ MacThreadList() : _thread_array(NULL), _thread_count(0), _thread_index(0) {
34
+ task_threads(mach_task_self(), &_thread_array, &_thread_count);
35
+ }
36
+
37
+ ~MacThreadList() {
38
+ task_t task = mach_task_self();
39
+ for (int i = 0; i < _thread_count; i++) {
40
+ mach_port_deallocate(task, _thread_array[i]);
41
+ }
42
+ vm_deallocate(task, (vm_address_t)_thread_array, sizeof(thread_t) * _thread_count);
43
+ }
44
+
45
+ int next() {
46
+ if (_thread_index < _thread_count) {
47
+ return (int)_thread_array[_thread_index++];
48
+ }
49
+ return -1;
50
+ }
51
+ };
52
+
53
+
54
+ static mach_timebase_info_data_t timebase = {0, 0};
55
+
56
+ u64 OS::nanotime() {
57
+ if (timebase.denom == 0) {
58
+ mach_timebase_info(&timebase);
59
+ }
60
+ return (u64)mach_absolute_time() * timebase.numer / timebase.denom;
61
+ }
62
+
63
+ u64 OS::millis() {
64
+ struct timeval tv;
65
+ gettimeofday(&tv, NULL);
66
+ return (u64)tv.tv_sec * 1000 + tv.tv_usec / 1000;
67
+ }
68
+
69
+ u64 OS::hton64(u64 x) {
70
+ return OSSwapHostToBigInt64(x);
71
+ }
72
+
73
+ int OS::threadId() {
74
+ // Used to be pthread_mach_thread_np(pthread_self()),
75
+ // but pthread_mach_thread_np is not async signal safe
76
+ mach_port_t port = mach_thread_self();
77
+ mach_port_deallocate(mach_task_self(), port);
78
+ return (int)port;
79
+ }
80
+
81
+ bool OS::isThreadRunning(int thread_id) {
82
+ struct thread_basic_info info;
83
+ mach_msg_type_number_t size = sizeof(info);
84
+ if (thread_info((thread_act_t)thread_id, THREAD_BASIC_INFO, (thread_info_t)&info, &size) != 0) {
85
+ return false;
86
+ }
87
+ return info.run_state == TH_STATE_RUNNING;
88
+ }
89
+
90
+ bool OS::isSignalSafeTLS() {
91
+ return false;
92
+ }
93
+
94
+ bool OS::isJavaLibraryVisible() {
95
+ return true;
96
+ }
97
+
98
+ void OS::installSignalHandler(int signo, void (*handler)(int, siginfo_t*, void*)) {
99
+ struct sigaction sa;
100
+ sigemptyset(&sa.sa_mask);
101
+ sa.sa_sigaction = handler;
102
+ sa.sa_flags = SA_RESTART | SA_SIGINFO;
103
+
104
+ sigaction(signo, &sa, NULL);
105
+ }
106
+
107
+ void OS::sendSignalToThread(int thread_id, int signo) {
108
+ asm volatile("syscall" : : "a"(0x2000148), "D"(thread_id), "S"(signo));
109
+ }
110
+
111
+ ThreadList* OS::listThreads() {
112
+ return new MacThreadList();
113
+ }
114
+
115
+ #endif // __APPLE__
@@ -0,0 +1,60 @@
1
+ /*
2
+ * Copyright 2017 Andrei Pangin
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+
17
+ #ifndef _PERFEVENTS_H
18
+ #define _PERFEVENTS_H
19
+
20
+ #include <signal.h>
21
+ #include "engine.h"
22
+
23
+
24
+ class PerfEvent;
25
+ class PerfEventType;
26
+
27
+ class PerfEvents : public Engine {
28
+ private:
29
+ static int _max_events;
30
+ static PerfEvent* _events;
31
+ static PerfEventType* _event_type;
32
+ static long _interval;
33
+ static Ring _ring;
34
+ static bool _print_extended_warning;
35
+
36
+ static bool createForThread(int tid);
37
+ static void destroyForThread(int tid);
38
+ static void signalHandler(int signo, siginfo_t* siginfo, void* ucontext);
39
+
40
+ public:
41
+ const char* name() {
42
+ return "perf";
43
+ }
44
+
45
+ const char* units();
46
+
47
+ Error start(Arguments& args);
48
+ void stop();
49
+
50
+ void onThreadStart();
51
+ void onThreadEnd();
52
+
53
+ int getNativeTrace(void* ucontext, int tid, const void** callchain, int max_depth,
54
+ const void* jit_min_address, const void* jit_max_address);
55
+
56
+ static bool supported();
57
+ static const char* getEventName(int event_id);
58
+ };
59
+
60
+ #endif // _PERFEVENTS_H