vernier 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b9ba6d060b4eb230a865df67f378f81b08721d36a9f8cf394f9a8d5d0455b844
4
- data.tar.gz: d01c209f5fab9bc99940fb5b967a722f69c75376dd6aba0c3e7759a9c52bc698
3
+ metadata.gz: 4988794520691870cb34178385be791e28fa4806eb1f6934b0d0abf52c8a070c
4
+ data.tar.gz: b1e63c6f5398f61fb68d634f17f33dc6aa7461344cb8acf446dd75ca52395818
5
5
  SHA512:
6
- metadata.gz: 65e359b25b1cc5a5e3dc2724ec7c98eb4f20203a98e0fd8f402b5875fe329afb6a20f6fc722f8da2febdd4cd30e8e2d56a00e42a4e5262baffb7a250fba79f3d
7
- data.tar.gz: bf9ca5416e6b7b17d316eb9c762273ab711518c7ba50c862f803eed9e2d17fcbdeee378f9d6702d4029715926d105398105c5eb0f6aec046fa540611993ec89a
6
+ metadata.gz: '082561b2a381f88c540e607d1dd9c0d42d841a0de82fc61471fb2d67754ee14a4fd1e87fa71896b586077664e61fd1db623fd250cd13064d198c9dc91d3f13ed'
7
+ data.tar.gz: a28c197d405e4f52d999db3ae73187047886e1fcfb7d353d13f26ad5ba4b61f0675daf617119b37d72ad3760bd0dffcae234f2dcb0a0e960a60046dfb87dd784
data/Gemfile CHANGED
@@ -8,5 +8,6 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
 
10
10
  gem "rake-compiler"
11
+ gem "benchmark-ips"
11
12
 
12
13
  gem "minitest", "~> 5.0"
data/README.md CHANGED
@@ -30,17 +30,33 @@ gem 'vernier'
30
30
 
31
31
  ## Usage
32
32
 
33
+ The output can be viewed in the web app at https://vernier.prof or locally using the [`profile-viewer` gem](https://github.com/tenderlove/profiler/tree/ruby) (both are lightly customized versions of the firefox profiler frontend, which profiles are also compatible with).
34
+
35
+ - **Flame Graph**: Shows proportionally how much time is spent within particular stack frames. Frames are grouped together, which means that x-axis / left-to-right order is not meaningful.
36
+ - **Stack Chart**: Shows the stack at each sample with the x-axis representing time and can be read left-to-right.
37
+
33
38
 
34
39
  ### Time
35
40
 
41
+
42
+ #### Command line
43
+
44
+ The easiest way to record a program or script is via the CLI
45
+
36
46
  ```
37
- Vernier.trace(out: "time_profile.json") { some_slow_method }
47
+ $ vernier run -- ruby -e 'sleep 1'
48
+ starting profiler with interval 500
49
+ #<Vernier::Result 1.001589 seconds, 1 threads, 2002 samples, 1 unique>
50
+ written to /tmp/profile20240328-82441-gkzffc.vernier.json
38
51
  ```
39
52
 
40
- The output can be viewed in the web app at https://vernier.prof or locally using the [`profile-viewer` gem](https://github.com/tenderlove/profiler/tree/ruby) (both are lightly customized versions of the firefox profiler frontend, which profiles are also compatible with).
53
+ ### Block of code
41
54
 
42
- - **Flame Graph**: Shows proportionally how much time is spent within particular stack frames. Frames are grouped together, which means that x-axis / left-to-right order is not meaningful.
43
- - **Stack Chart**: Shows the stack at each sample with the x-axis representing time and can be read left-to-right.
55
+ ``` ruby
56
+ Vernier.run(out: "time_profile.json") do
57
+ some_slow_method
58
+ end
59
+ ```
44
60
 
45
61
  ### Retained memory
46
62
 
@@ -0,0 +1,62 @@
1
+ # Different (bad) ways to sleep
2
+
3
+ File.write("#{__dir__}/my_sleep.c", <<~EOF)
4
+ #include <time.h>
5
+ #include <sys/errno.h>
6
+
7
+ void my_sleep() {
8
+ struct timespec ts;
9
+ ts.tv_sec = 1;
10
+ ts.tv_nsec = 0;
11
+
12
+ int rc;
13
+ do {
14
+ rc = nanosleep(&ts, &ts);
15
+ } while (rc < 0 && errno == EINTR);
16
+ }
17
+ EOF
18
+
19
+ soext = RbConfig::CONFIG["SOEXT"]
20
+ system("gcc", "-shared", "-fPIC", "#{__dir__}/my_sleep.c", "-o", "#{__dir__}/my_sleep.#{soext}")
21
+
22
+ require "fiddle"
23
+
24
+ SLEEP_LIB = Fiddle.dlopen("./my_sleep.#{soext}")
25
+
26
+ def cfunc_sleep_gvl
27
+ Fiddle::Function.new(SLEEP_LIB['my_sleep'], [], Fiddle::TYPE_VOID, need_gvl: true).call
28
+ end
29
+
30
+ def cfunc_sleep_idle
31
+ Fiddle::Function.new(SLEEP_LIB['my_sleep'], [], Fiddle::TYPE_VOID, need_gvl: true).call
32
+ end
33
+
34
+ def ruby_sleep_gvl
35
+ target = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) + 1000
36
+ while Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond) < target
37
+ i = 0
38
+ while i < 1000
39
+ i += 1
40
+ end
41
+ end
42
+ end
43
+
44
+ def sleep_idle
45
+ sleep 1
46
+ end
47
+
48
+ def run(name)
49
+ STDOUT.print "#{name}..."
50
+ STDOUT.flush
51
+
52
+ before = Process.clock_gettime(Process::CLOCK_MONOTONIC)
53
+ send(name)
54
+ after = Process.clock_gettime(Process::CLOCK_MONOTONIC)
55
+
56
+ STDOUT.puts " %.2fs" % (after - before)
57
+ end
58
+
59
+ run(:cfunc_sleep_gvl)
60
+ run(:cfunc_sleep_idle)
61
+ run(:ruby_sleep_gvl)
62
+ run(:sleep_idle)
@@ -0,0 +1,39 @@
1
+ require "benchmark/ips"
2
+ require "vernier"
3
+
4
+ def compare(**options, &block)
5
+ block.call
6
+
7
+ Benchmark.ips do |x|
8
+ x.report "no profiler" do |n|
9
+ n.times do
10
+ block.call
11
+ end
12
+ end
13
+
14
+ x.report "vernier" do |n|
15
+ Vernier.profile(**options) do
16
+ n.times do
17
+ block.call
18
+ end
19
+ end
20
+ end
21
+
22
+ x.compare!
23
+ end
24
+ end
25
+
26
+ compare do
27
+ i = 0
28
+ while i < 10_000
29
+ i += 1
30
+ end
31
+ end
32
+
33
+ compare(allocation_sample_rate: 1000) do
34
+ Object.new
35
+ end
36
+
37
+ compare(allocation_sample_rate: 1) do
38
+ Object.new
39
+ end