vernier 0.5.0 → 0.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/vernier/vernier.cc +45 -33
- data/lib/vernier/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da42588d9f2409a9d82a79439014490ecd81f00cb74c975267d6568a6e343c46
|
4
|
+
data.tar.gz: 921543f2b8cfec4e5803c4a47c8953df1acff567b88ddce2e1a65faad9e7c895
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a674536e944ef26f2db5893821d9d643fc8f651d45b7a72923ae9ab7c01f270431f0e5fadea76e3bb3feeabe30edde203b520310cbbbae6a53f03edb148db570
|
7
|
+
data.tar.gz: 1f39e9f04a2fd1c80525a72ce27aca6e8d614dfa9a4ba9f9721beff08f11a41431f6690c6215f0592dcc7923e49e516a4a0ddb812b493820877ceca81b4373ab
|
data/ext/vernier/vernier.cc
CHANGED
@@ -331,7 +331,7 @@ struct RawSample {
|
|
331
331
|
|
332
332
|
Frame frame(int i) const {
|
333
333
|
int idx = len - i - 1;
|
334
|
-
if (idx < 0) throw std::out_of_range("out of range");
|
334
|
+
if (idx < 0) throw std::out_of_range("VERNIER BUG: index out of range");
|
335
335
|
const Frame frame = {frames[idx], lines[idx]};
|
336
336
|
return frame;
|
337
337
|
}
|
@@ -446,7 +446,7 @@ struct FrameList {
|
|
446
446
|
|
447
447
|
int stack_index(const RawSample &stack) {
|
448
448
|
if (stack.empty()) {
|
449
|
-
throw std::runtime_error("empty stack");
|
449
|
+
throw std::runtime_error("VERNIER BUG: empty stack");
|
450
450
|
}
|
451
451
|
|
452
452
|
StackNode *node = &root_stack_node;
|
@@ -659,8 +659,8 @@ class Marker {
|
|
659
659
|
|
660
660
|
class MarkerTable {
|
661
661
|
public:
|
662
|
-
std::vector<Marker> list;
|
663
662
|
std::mutex mutex;
|
663
|
+
std::vector<Marker> list;
|
664
664
|
|
665
665
|
void record_interval(Marker::Type type, TimeStamp from, TimeStamp to, int stack_index = -1) {
|
666
666
|
const std::lock_guard<std::mutex> lock(mutex);
|
@@ -780,19 +780,18 @@ class Thread {
|
|
780
780
|
int stack_on_suspend_idx;
|
781
781
|
SampleTranslator translator;
|
782
782
|
|
783
|
-
MarkerTable
|
783
|
+
unique_ptr<MarkerTable> markers;
|
784
784
|
|
785
|
-
|
785
|
+
std::string name;
|
786
786
|
|
787
|
-
|
787
|
+
// FIXME: don't use pthread at start
|
788
788
|
Thread(State state, pthread_t pthread_id, VALUE ruby_thread) : pthread_id(pthread_id), ruby_thread(ruby_thread), state(state), stack_on_suspend_idx(-1) {
|
789
|
-
name = Qnil;
|
790
789
|
ruby_thread_id = rb_obj_id(ruby_thread);
|
791
|
-
|
790
|
+
//ruby_thread_id = ULL2NUM(ruby_thread);
|
792
791
|
native_tid = get_native_thread_id();
|
793
792
|
started_at = state_changed_at = TimeStamp::Now();
|
794
793
|
name = "";
|
795
|
-
markers =
|
794
|
+
markers = std::make_unique<MarkerTable>();
|
796
795
|
|
797
796
|
if (state == State::STARTED) {
|
798
797
|
markers->record(Marker::Type::MARKER_GVL_THREAD_STARTED);
|
@@ -879,15 +878,15 @@ class ThreadTable {
|
|
879
878
|
public:
|
880
879
|
FrameList &frame_list;
|
881
880
|
|
882
|
-
std::vector<Thread> list;
|
881
|
+
std::vector<std::unique_ptr<Thread> > list;
|
883
882
|
std::mutex mutex;
|
884
883
|
|
885
884
|
ThreadTable(FrameList &frame_list) : frame_list(frame_list) {
|
886
885
|
}
|
887
886
|
|
888
887
|
void mark() {
|
889
|
-
for (auto &thread : list) {
|
890
|
-
thread
|
888
|
+
for (const auto &thread : list) {
|
889
|
+
thread->mark();
|
891
890
|
}
|
892
891
|
}
|
893
892
|
|
@@ -923,7 +922,8 @@ class ThreadTable {
|
|
923
922
|
|
924
923
|
//fprintf(stderr, "th %p (tid: %i) from %s to %s\n", (void *)th, native_tid, gvl_event_name(state), gvl_event_name(new_state));
|
925
924
|
|
926
|
-
for (auto &
|
925
|
+
for (auto &threadptr : list) {
|
926
|
+
auto &thread = *threadptr;
|
927
927
|
if (thread_equal(th, thread.ruby_thread)) {
|
928
928
|
if (new_state == Thread::State::SUSPENDED) {
|
929
929
|
|
@@ -950,7 +950,7 @@ class ThreadTable {
|
|
950
950
|
}
|
951
951
|
|
952
952
|
//fprintf(stderr, "NEW THREAD: th: %p, state: %i\n", th, new_state);
|
953
|
-
list.
|
953
|
+
list.push_back(std::make_unique<Thread>(new_state, pthread_self(), th));
|
954
954
|
}
|
955
955
|
|
956
956
|
bool thread_equal(VALUE a, VALUE b) {
|
@@ -1226,17 +1226,22 @@ class GlobalSignalHandler {
|
|
1226
1226
|
if (count == 0) clear_signal_handler();
|
1227
1227
|
}
|
1228
1228
|
|
1229
|
-
|
1229
|
+
bool record_sample(LiveSample &sample, pthread_t pthread_id) {
|
1230
1230
|
const std::lock_guard<std::mutex> lock(mutex);
|
1231
1231
|
|
1232
1232
|
assert(pthread_id);
|
1233
1233
|
|
1234
1234
|
live_sample = &sample;
|
1235
|
-
|
1236
|
-
|
1235
|
+
int rc = pthread_kill(pthread_id, SIGPROF);
|
1236
|
+
if (rc) {
|
1237
|
+
fprintf(stderr, "VERNIER BUG: pthread_kill of %lu failed (%i)\n", (unsigned long)pthread_id, rc);
|
1238
|
+
live_sample = NULL;
|
1239
|
+
return false;
|
1240
|
+
} else {
|
1241
|
+
sample.wait();
|
1242
|
+
live_sample = NULL;
|
1243
|
+
return true;
|
1237
1244
|
}
|
1238
|
-
sample.wait();
|
1239
|
-
live_sample = NULL;
|
1240
1245
|
}
|
1241
1246
|
|
1242
1247
|
private:
|
@@ -1307,9 +1312,9 @@ class TimeCollector : public BaseCollector {
|
|
1307
1312
|
rb_ary_push(list, ary);
|
1308
1313
|
}
|
1309
1314
|
for (auto &thread : threads.list) {
|
1310
|
-
for (auto& marker: thread
|
1315
|
+
for (auto& marker: thread->markers->list) {
|
1311
1316
|
VALUE ary = marker.to_array();
|
1312
|
-
RARRAY_ASET(ary, 0, thread
|
1317
|
+
RARRAY_ASET(ary, 0, thread->ruby_thread_id);
|
1313
1318
|
rb_ary_push(list, ary);
|
1314
1319
|
}
|
1315
1320
|
}
|
@@ -1325,14 +1330,21 @@ class TimeCollector : public BaseCollector {
|
|
1325
1330
|
TimeStamp sample_start = TimeStamp::Now();
|
1326
1331
|
|
1327
1332
|
threads.mutex.lock();
|
1328
|
-
for (auto &
|
1333
|
+
for (auto &threadptr : threads.list) {
|
1334
|
+
auto &thread = *threadptr;
|
1335
|
+
|
1329
1336
|
//if (thread.state == Thread::State::RUNNING) {
|
1330
1337
|
//if (thread.state == Thread::State::RUNNING || (thread.state == Thread::State::SUSPENDED && thread.stack_on_suspend_idx < 0)) {
|
1331
1338
|
if (thread.state == Thread::State::RUNNING) {
|
1332
1339
|
//fprintf(stderr, "sampling %p on tid:%i\n", thread.ruby_thread, thread.native_tid);
|
1333
|
-
GlobalSignalHandler::get_instance()->record_sample(sample, thread.pthread_id);
|
1334
|
-
|
1335
|
-
if (
|
1340
|
+
bool signal_sent = GlobalSignalHandler::get_instance()->record_sample(sample, thread.pthread_id);
|
1341
|
+
|
1342
|
+
if (!signal_sent) {
|
1343
|
+
// The thread has died. We probably should have caught
|
1344
|
+
// that by the GVL instrumentation, but let's try to get
|
1345
|
+
// it to a consistent state and stop profiling it.
|
1346
|
+
thread.set_state(Thread::State::STOPPED);
|
1347
|
+
} else if (sample.sample.gc) {
|
1336
1348
|
// fprintf(stderr, "skipping GC sample\n");
|
1337
1349
|
} else {
|
1338
1350
|
record_sample(sample.sample, sample_start, thread, CATEGORY_NORMAL);
|
@@ -1465,7 +1477,7 @@ class TimeCollector : public BaseCollector {
|
|
1465
1477
|
int ret = pthread_create(&sample_thread, NULL, &sample_thread_entry, this);
|
1466
1478
|
if (ret != 0) {
|
1467
1479
|
perror("pthread_create");
|
1468
|
-
rb_bug("pthread_create");
|
1480
|
+
rb_bug("VERNIER: pthread_create failed");
|
1469
1481
|
}
|
1470
1482
|
|
1471
1483
|
// Set the state of the current Ruby thread to RUNNING, which we know it
|
@@ -1511,15 +1523,15 @@ class TimeCollector : public BaseCollector {
|
|
1511
1523
|
|
1512
1524
|
for (const auto& thread: this->threads.list) {
|
1513
1525
|
VALUE hash = rb_hash_new();
|
1514
|
-
thread
|
1526
|
+
thread->samples.write_result(hash);
|
1515
1527
|
|
1516
|
-
rb_hash_aset(threads, thread
|
1517
|
-
rb_hash_aset(hash, sym("tid"), ULL2NUM(thread
|
1518
|
-
rb_hash_aset(hash, sym("started_at"), ULL2NUM(thread
|
1519
|
-
if (!thread
|
1520
|
-
rb_hash_aset(hash, sym("stopped_at"), ULL2NUM(thread
|
1528
|
+
rb_hash_aset(threads, thread->ruby_thread_id, hash);
|
1529
|
+
rb_hash_aset(hash, sym("tid"), ULL2NUM(thread->native_tid));
|
1530
|
+
rb_hash_aset(hash, sym("started_at"), ULL2NUM(thread->started_at.nanoseconds()));
|
1531
|
+
if (!thread->stopped_at.zero()) {
|
1532
|
+
rb_hash_aset(hash, sym("stopped_at"), ULL2NUM(thread->stopped_at.nanoseconds()));
|
1521
1533
|
}
|
1522
|
-
rb_hash_aset(hash, sym("name"), rb_str_new(thread
|
1534
|
+
rb_hash_aset(hash, sym("name"), rb_str_new(thread->name.data(), thread->name.length()));
|
1523
1535
|
|
1524
1536
|
}
|
1525
1537
|
|
data/lib/vernier/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vernier
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Hawthorn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: An experimental profiler
|
14
14
|
email:
|
@@ -67,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
requirements: []
|
70
|
-
rubygems_version: 3.
|
70
|
+
rubygems_version: 3.5.3
|
71
71
|
signing_key:
|
72
72
|
specification_version: 4
|
73
73
|
summary: An experimental profiler
|