pf2 0.10.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 22269113784c160efa2ef33412444646afdb33d58215f0a7f0ec2e4e05ad2708
4
- data.tar.gz: cc1b783cab40fc4469b5bc09fc3a3a5dec4a76357d14accb7f6a4458ea7cc7bd
3
+ metadata.gz: 74e3ac2900007b7750e3c3274833e1f713b6e85570db0aa738761ea99b517fe8
4
+ data.tar.gz: 68ffc8d681328e4d5542e4bd4b3a98edfd08d69fa1b54342fdccbe8f9495bcf0
5
5
  SHA512:
6
- metadata.gz: 551b033c17201f6f21d741e53bf5b5c43cce3adb3f5daa0e1f17679176c23b87d727cbd162b67f855a39b9fd344ed499ec7d283598f95de30c25d2b3ac7d179e
7
- data.tar.gz: ffa342dcfd1c467737485c0aba8497ff98c144a53ae5c0e50566ef1ba58e6fc9e0cfbe0ad870e64788b2a93f31eb8011c0fa1194e674f092dfb9b662d7b9db71
6
+ metadata.gz: 4f1e67870eac32734a7532f46f29b74589ec6d71c59c925fc02456f473a516218fbbf46fed730558f0b9525c585dbb2fbc088fcf9cbfb47e7f4b89adda7f4974
7
+ data.tar.gz: 8f5ec74f112eb65a512dbcd7002b0db9a4da0d3a2124d3bd2e7106412c71009b36f92ff442efc87910a5a8829094c06e1ee93169c829ab893dd8e1bd86a81a4f
data/.document ADDED
@@ -0,0 +1,3 @@
1
+ ext/
2
+ lib/
3
+ *.md
data/.rdoc_options ADDED
@@ -0,0 +1,6 @@
1
+ title: Pf2
2
+ main_page: README.md
3
+ encoding: UTF-8
4
+
5
+ autolink_excluded_words:
6
+ - Pf2
data/CHANGELOG.md CHANGED
@@ -1,6 +1,25 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.11.0] - 2025-12-27
4
+
5
+ ### Added
6
+
7
+ - RDoc documentation is now online - https://osyoyu.github.io/pf2/
8
+ - Native stack consolidation now supports LTO-ed binaries (@hanazuki)
9
+
10
+ ### Changed
11
+
12
+ - `Pf2c` module is now completely removed. `Pf2c::Session` has been merged as `Pf2::Session`.
13
+
14
+ ### Fixed
15
+
16
+ - Fixed an bug where the program crashes when a `Pf2::Session` is GC'd before profiling starts.
17
+ - Fixed an bug where the program crashes when the native stack was more than 200 frames deep.
18
+
19
+
1
20
  ## [0.10.0] - 2025-12-26
2
21
 
3
- ## Added
22
+ ### Added
4
23
 
5
24
  **This version contains a complete rewrite of the profiler!**
6
25
 
data/README.md CHANGED
@@ -3,6 +3,9 @@ Pf2
3
3
 
4
4
  A experimental sampling-based profiler for Ruby 3.3+.
5
5
 
6
+ - GitHub: https://github.com/osyoyu/pf2
7
+ - Documentation: https://osyoyu.github.io/pf2/
8
+
6
9
  Notable Capabilites
7
10
  --------
8
11
 
@@ -13,6 +16,25 @@ Notable Capabilites
13
16
  Usage
14
17
  --------
15
18
 
19
+ ### Installation
20
+
21
+ You will need a C compiler to build the native extension.
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'pf2'
27
+
28
+ # When using the main branch, specify submodules: true
29
+ gem 'pf2', git: 'https://github.com/osyoyu/pf2.git', submodules: true
30
+ ```
31
+
32
+ Pf2 can be installed as a standalone CLI tool as well.
33
+
34
+ ```console
35
+ gem install pf2
36
+ ```
37
+
16
38
  ### Quickstart
17
39
 
18
40
  Run your Ruby program through `pf2 serve`.
data/Rakefile CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'bundler/gem_tasks'
2
2
  require 'rake/extensiontask'
3
3
  require 'minitest/test_task'
4
+ require 'rdoc/task'
4
5
 
5
6
  task default: %i[]
6
7
 
@@ -15,3 +16,7 @@ Minitest::TestTask.create(:test) do |t|
15
16
  t.warning = false
16
17
  t.test_globs = ["test/**/*_test.rb"]
17
18
  end
19
+
20
+ RDoc::Task.new do |doc|
21
+ doc.rdoc_dir = "_site" # for GitHub pages
22
+ end
data/ext/pf2/pf2.c CHANGED
@@ -2,16 +2,16 @@
2
2
 
3
3
  #include "session.h"
4
4
 
5
- VALUE rb_mPf2c;
5
+ VALUE rb_mPf2;
6
6
 
7
7
  RUBY_FUNC_EXPORTED void
8
8
  Init_pf2(void)
9
9
  {
10
- rb_mPf2c = rb_define_module("Pf2c");
11
- VALUE rb_mPf2c_cSession = rb_define_class_under(rb_mPf2c, "Session", rb_cObject);
12
- rb_define_alloc_func(rb_mPf2c_cSession, pf2_session_alloc);
13
- rb_define_method(rb_mPf2c_cSession, "initialize", rb_pf2_session_initialize, -1);
14
- rb_define_method(rb_mPf2c_cSession, "start", rb_pf2_session_start, 0);
15
- rb_define_method(rb_mPf2c_cSession, "stop", rb_pf2_session_stop, 0);
16
- rb_define_method(rb_mPf2c_cSession, "configuration", rb_pf2_session_configuration, 0);
10
+ rb_mPf2 = rb_define_module("Pf2");
11
+ VALUE rb_mPf2_cSession = rb_define_class_under(rb_mPf2, "Session", rb_cObject);
12
+ rb_define_alloc_func(rb_mPf2_cSession, pf2_session_alloc);
13
+ rb_define_method(rb_mPf2_cSession, "initialize", rb_pf2_session_initialize, -1);
14
+ rb_define_method(rb_mPf2_cSession, "start", rb_pf2_session_start, 0);
15
+ rb_define_method(rb_mPf2_cSession, "stop", rb_pf2_session_stop, 0);
16
+ rb_define_method(rb_mPf2_cSession, "configuration", rb_pf2_session_configuration, 0);
17
17
  }
data/ext/pf2/sample.c CHANGED
@@ -9,8 +9,6 @@
9
9
  #include "backtrace_state.h"
10
10
  #include "sample.h"
11
11
 
12
- const int PF2_SAMPLE_MAX_NATIVE_DEPTH = 300;
13
-
14
12
  static int capture_native_backtrace(struct pf2_sample *sample);
15
13
  static int backtrace_on_ok(void *data, uintptr_t pc);
16
14
 
@@ -29,7 +27,7 @@ pf2_sample_capture(struct pf2_sample *sample)
29
27
  sample->context_pthread = pthread_self();
30
28
 
31
29
  // Obtain the current stack from Ruby
32
- sample->depth = rb_profile_frames(0, 200, sample->cmes, sample->linenos);
30
+ sample->depth = rb_profile_frames(0, PF2_SAMPLE_MAX_RUBY_DEPTH, sample->cmes, sample->linenos);
33
31
 
34
32
  // Capture C-level backtrace
35
33
  sample->native_stack_depth = capture_native_backtrace(sample);
data/ext/pf2/sample.h CHANGED
@@ -5,17 +5,18 @@
5
5
 
6
6
  #include <ruby.h>
7
7
 
8
- extern const int PF2_SAMPLE_MAX_NATIVE_DEPTH;
8
+ #define PF2_SAMPLE_MAX_RUBY_DEPTH 200
9
+ #define PF2_SAMPLE_MAX_NATIVE_DEPTH 300
9
10
 
10
11
  struct pf2_sample {
11
12
  pthread_t context_pthread;
12
13
 
13
14
  int depth;
14
- VALUE cmes[200];
15
- int linenos[200];
15
+ VALUE cmes[PF2_SAMPLE_MAX_RUBY_DEPTH];
16
+ int linenos[PF2_SAMPLE_MAX_RUBY_DEPTH];
16
17
 
17
18
  size_t native_stack_depth;
18
- uintptr_t native_stack[200];
19
+ uintptr_t native_stack[PF2_SAMPLE_MAX_NATIVE_DEPTH];
19
20
 
20
21
  uint64_t consumed_time_ns;
21
22
  uint64_t timestamp_ns;
data/ext/pf2/session.c CHANGED
@@ -318,19 +318,32 @@ pf2_session_alloc(VALUE self)
318
318
  rb_raise(rb_eNoMemError, "Failed to allocate memory");
319
319
  }
320
320
 
321
+ // is_running
322
+ session->is_running = false;
323
+
324
+ // timer
325
+ #ifdef HAVE_TIMER_CREATE
326
+ session->timer = (timer_t)0;
327
+ #else
328
+ session->timer = (struct itimerval){0};
329
+ #endif
330
+
331
+ // rbuf
321
332
  session->rbuf = pf2_ringbuffer_new(1000);
322
333
  if (session->rbuf == NULL) {
323
334
  rb_raise(rb_eNoMemError, "Failed to allocate memory");
324
335
  }
325
336
 
337
+ // is_marking
326
338
  atomic_store_explicit(&session->is_marking, false, memory_order_relaxed);
339
+
340
+ // collector_thread
327
341
  session->collector_thread = malloc(sizeof(pthread_t));
328
342
  if (session->collector_thread == NULL) {
329
343
  rb_raise(rb_eNoMemError, "Failed to allocate memory");
330
344
  }
331
345
 
332
- session->duration_ns = 0;
333
-
346
+ // samples, samples_index, samples_capacity
334
347
  session->samples_index = 0;
335
348
  session->samples_capacity = 500; // 10 seconds worth of samples at 50 Hz
336
349
  session->samples = malloc(sizeof(struct pf2_sample) * session->samples_capacity);
@@ -338,6 +351,14 @@ pf2_session_alloc(VALUE self)
338
351
  rb_raise(rb_eNoMemError, "Failed to allocate memory");
339
352
  }
340
353
 
354
+ // start_time_realtime, start_time
355
+ session->start_time_realtime = (struct timespec){0};
356
+ session->start_time = (struct timespec){0};
357
+
358
+ // duration_ns
359
+ session->duration_ns = 0;
360
+
361
+ // configuration
341
362
  session->configuration = NULL;
342
363
 
343
364
  return TypedData_Wrap_Struct(self, &pf2_session_type, session);
data/ext/pf2/session.h CHANGED
@@ -43,7 +43,7 @@ void pf2_session_dfree(void *sess);
43
43
  size_t pf2_session_dsize(const void *sess);
44
44
 
45
45
  static const rb_data_type_t pf2_session_type = {
46
- .wrap_struct_name = "Pf2c::Session",
46
+ .wrap_struct_name = "Pf2::Session",
47
47
  .function = {
48
48
  .dmark = pf2_session_dmark,
49
49
  .dfree = pf2_session_dfree,
@@ -82,7 +82,7 @@ module Pf2
82
82
 
83
83
  # If the next function is a vm_exec_core() (= VM_EXEC in vm_exec.h),
84
84
  # we switch to the Ruby stack.
85
- function[:name] == 'vm_exec_core'
85
+ function[:name]&.match?(/\Avm_exec_core(?:\.lto_priv\.\d+)?\z/)
86
86
  end
87
87
  end
88
88
  end
data/lib/pf2/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pf2
4
- VERSION = '0.10.0'
4
+ VERSION = '0.11.0'
5
5
  end
data/lib/pf2.rb CHANGED
@@ -1,14 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'pf2/pf2'
4
- require_relative 'pf2/session'
5
4
  require_relative 'pf2/version'
6
5
 
7
6
  module Pf2
8
7
  class Error < StandardError; end
9
8
 
10
9
  def self.start(...)
11
- @@session = Pf2c::Session.new(...)
10
+ @@session = Session.new(...)
12
11
  @@session.start
13
12
  end
14
13
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pf2
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daisuke Aritomo
@@ -93,6 +93,20 @@ dependencies:
93
93
  - - ">="
94
94
  - !ruby/object:Gem::Version
95
95
  version: '0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rdoc
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
96
110
  email:
97
111
  - osyoyu@osyoyu.com
98
112
  executables:
@@ -101,6 +115,8 @@ extensions:
101
115
  - ext/pf2/extconf.rb
102
116
  extra_rdoc_files: []
103
117
  files:
118
+ - ".document"
119
+ - ".rdoc_options"
104
120
  - CHANGELOG.md
105
121
  - LICENSE.txt
106
122
  - README.md
@@ -132,7 +148,6 @@ files:
132
148
  - lib/pf2/reporter/firefox_profiler_ser2.rb
133
149
  - lib/pf2/reporter/stack_weaver.rb
134
150
  - lib/pf2/serve.rb
135
- - lib/pf2/session.rb
136
151
  - lib/pf2/version.rb
137
152
  - vendor/libbacktrace/.gitignore
138
153
  - vendor/libbacktrace/Isaac.Newton-Opticks.txt
data/lib/pf2/session.rb DELETED
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Pf2
4
- class Session
5
- attr_reader :configuration
6
-
7
- # Implementation is in Rust code.
8
- end
9
- end