corkscrews 0.1.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.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +130 -0
  4. data/Rakefile +20 -0
  5. data/exe/corkscrews +9 -0
  6. data/ext/corkscrews/corkscrews.c +24 -0
  7. data/ext/corkscrews/corkscrews_native.h +85 -0
  8. data/ext/corkscrews/delay.c +259 -0
  9. data/ext/corkscrews/extconf.rb +25 -0
  10. data/ext/corkscrews/hooks.c +156 -0
  11. data/ext/corkscrews/monitor.c +117 -0
  12. data/ext/corkscrews/record.c +109 -0
  13. data/ext/corkscrews/sampler.c +99 -0
  14. data/lib/corkscrews/analysis.rb +452 -0
  15. data/lib/corkscrews/boot.rb +25 -0
  16. data/lib/corkscrews/cli.rb +159 -0
  17. data/lib/corkscrews/controller.rb +137 -0
  18. data/lib/corkscrews/firefox_profile.rb +290 -0
  19. data/lib/corkscrews/native.rb +108 -0
  20. data/lib/corkscrews/primitives.rb +127 -0
  21. data/lib/corkscrews/rack.rb +39 -0
  22. data/lib/corkscrews/recorder.rb +903 -0
  23. data/lib/corkscrews/report.rb +241 -0
  24. data/lib/corkscrews/statistics.rb +112 -0
  25. data/lib/corkscrews/time_source.rb +11 -0
  26. data/lib/corkscrews/validate.rb +348 -0
  27. data/lib/corkscrews/version.rb +5 -0
  28. data/lib/corkscrews.rb +43 -0
  29. data/validate/benchmarks/b01_serial_hotspot/base.rb +28 -0
  30. data/validate/benchmarks/b01_serial_hotspot/manifest.yml +23 -0
  31. data/validate/benchmarks/b01_serial_hotspot/optimized.rb +28 -0
  32. data/validate/benchmarks/b02_false_hotspot/base.rb +43 -0
  33. data/validate/benchmarks/b02_false_hotspot/manifest.yml +19 -0
  34. data/validate/benchmarks/b02_false_hotspot/optimized.rb +43 -0
  35. data/validate/benchmarks/b03_io_wait/base.rb +29 -0
  36. data/validate/benchmarks/b03_io_wait/manifest.yml +16 -0
  37. data/validate/benchmarks/b03_io_wait/optimized.rb +29 -0
  38. data/validate/benchmarks/b04_lock_contention/base.rb +30 -0
  39. data/validate/benchmarks/b04_lock_contention/manifest.yml +19 -0
  40. data/validate/benchmarks/b04_lock_contention/optimized.rb +30 -0
  41. data/validate/benchmarks/b05_gvl_contention/base.rb +24 -0
  42. data/validate/benchmarks/b05_gvl_contention/manifest.yml +17 -0
  43. data/validate/benchmarks/b05_gvl_contention/optimized.rb +24 -0
  44. data/validate/benchmarks/b06_gc_pressure/base.rb +16 -0
  45. data/validate/benchmarks/b06_gc_pressure/manifest.yml +16 -0
  46. data/validate/benchmarks/b06_gc_pressure/optimized.rb +17 -0
  47. data/validate/benchmarks/b07_pipeline/base.rb +34 -0
  48. data/validate/benchmarks/b07_pipeline/manifest.yml +17 -0
  49. data/validate/benchmarks/b07_pipeline/optimized.rb +34 -0
  50. data/validate/benchmarks/b08_native_attribution/base.rb +18 -0
  51. data/validate/benchmarks/b08_native_attribution/manifest.yml +18 -0
  52. data/validate/benchmarks/b08_native_attribution/optimized.rb +18 -0
  53. data/validate/benchmarks/support.rb +29 -0
  54. data/validate/harness/run_all.rb +16 -0
  55. data/validate/harness/stats_check.py +27 -0
  56. data/validate/harness/t1.rb +15 -0
  57. data/validate/harness/t4.rb +15 -0
  58. data/validate/harness/t5.rb +15 -0
  59. metadata +118 -0
@@ -0,0 +1,19 @@
1
+ id: b04_lock_contention
2
+ category: lock
3
+ targets: both
4
+ progress_point: work_done
5
+ truth:
6
+ target:
7
+ kind: wait
8
+ name: lock_wait
9
+ decoys:
10
+ - { kind: line, file: base.rb, line: 10 }
11
+ optimized_speedup_of_target: 0.50
12
+ run:
13
+ repeat: 3
14
+ iterations: 160
15
+ sample_period_ms: 0.5
16
+ acceptance:
17
+ t1_mae_pct: 120.0
18
+ t3_decoy_max_effect_pct: 50.0
19
+ t4_overhead_pct: 40.0
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ def critical_work
6
+ CorkscrewsBench.busy(600)
7
+ end
8
+
9
+ def outside_work
10
+ CorkscrewsBench.busy(600)
11
+ end
12
+
13
+ iterations = CorkscrewsBench.iterations(180)
14
+ started = CorkscrewsBench.monotonic_ns
15
+ mutex = Mutex.new
16
+ done = Queue.new
17
+
18
+ 4.times do
19
+ Thread.new do
20
+ (iterations / 4).times do
21
+ mutex.synchronize { critical_work }
22
+ outside_work
23
+ Corkscrews.progress(:work_done)
24
+ end
25
+ done << true
26
+ end
27
+ end
28
+
29
+ 4.times { done.pop }
30
+ CorkscrewsBench.finish(progress: iterations - (iterations % 4), started_ns: started)
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ def gvl_work
6
+ 20_000.times.sum { |i| Integer.sqrt((i * i) + 7) }
7
+ end
8
+
9
+ iterations = CorkscrewsBench.iterations(200)
10
+ started = CorkscrewsBench.monotonic_ns
11
+ done = Queue.new
12
+
13
+ 4.times do
14
+ Thread.new do
15
+ (iterations / 4).times do
16
+ gvl_work
17
+ Corkscrews.progress(:work_done)
18
+ end
19
+ done << true
20
+ end
21
+ end
22
+
23
+ 4.times { done.pop }
24
+ CorkscrewsBench.finish(progress: iterations - (iterations % 4), started_ns: started)
@@ -0,0 +1,17 @@
1
+ id: b05_gvl_contention
2
+ category: gvl
3
+ targets: lines
4
+ progress_point: work_done
5
+ truth:
6
+ target:
7
+ kind: line
8
+ file: base.rb
9
+ line: 23
10
+ optimized_speedup_of_target: 0.50
11
+ run:
12
+ repeat: 3
13
+ iterations: 160
14
+ sample_period_ms: 0.5
15
+ acceptance:
16
+ t1_mae_pct: 80.0
17
+ t4_overhead_pct: 30.0
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ def gvl_work
6
+ 10_000.times.sum { |i| Integer.sqrt((i * i) + 7) }
7
+ end
8
+
9
+ iterations = CorkscrewsBench.iterations(200)
10
+ started = CorkscrewsBench.monotonic_ns
11
+ done = Queue.new
12
+
13
+ 4.times do
14
+ Thread.new do
15
+ (iterations / 4).times do
16
+ gvl_work
17
+ Corkscrews.progress(:work_done)
18
+ end
19
+ done << true
20
+ end
21
+ end
22
+
23
+ 4.times { done.pop }
24
+ CorkscrewsBench.finish(progress: iterations - (iterations % 4), started_ns: started)
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ iterations = CorkscrewsBench.iterations(500)
6
+ started = CorkscrewsBench.monotonic_ns
7
+ checksum = 0
8
+
9
+ iterations.times do
10
+ data = Array.new(400) { |i| "x#{i}" }
11
+ checksum ^= data.length
12
+ GC.start if (checksum % 17).zero?
13
+ Corkscrews.progress(:work_done)
14
+ end
15
+
16
+ CorkscrewsBench.finish(progress: iterations, started_ns: started, checksum: checksum)
@@ -0,0 +1,16 @@
1
+ id: b06_gc_pressure
2
+ category: gc
3
+ targets: both
4
+ progress_point: work_done
5
+ truth:
6
+ target:
7
+ kind: wait
8
+ name: gc_pause
9
+ optimized_speedup_of_target: 0.50
10
+ run:
11
+ repeat: 3
12
+ iterations: 400
13
+ sample_period_ms: 0.5
14
+ acceptance:
15
+ t1_mae_pct: 120.0
16
+ t4_overhead_pct: 45.0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ iterations = CorkscrewsBench.iterations(500)
6
+ started = CorkscrewsBench.monotonic_ns
7
+ buffer = Array.new(40)
8
+ checksum = 0
9
+
10
+ iterations.times do
11
+ buffer.each_index { |i| buffer[i] = i }
12
+ checksum ^= buffer.length
13
+ GC.start if (checksum % 101).zero?
14
+ Corkscrews.progress(:work_done)
15
+ end
16
+
17
+ CorkscrewsBench.finish(progress: iterations, started_ns: started, checksum: checksum)
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ iterations = CorkscrewsBench.iterations(160)
6
+ started = CorkscrewsBench.monotonic_ns
7
+ parse_q = Thread::SizedQueue.new(8)
8
+ write_q = Thread::SizedQueue.new(8)
9
+
10
+ parser = Thread.new do
11
+ iterations.times do |i|
12
+ CorkscrewsBench.busy(2_000)
13
+ parse_q << i
14
+ end
15
+ end
16
+
17
+ transformer = Thread.new do
18
+ iterations.times do
19
+ item = parse_q.pop
20
+ CorkscrewsBench.busy(8_000)
21
+ write_q << item
22
+ end
23
+ end
24
+
25
+ writer = Thread.new do
26
+ iterations.times do
27
+ write_q.pop
28
+ CorkscrewsBench.busy(2_000)
29
+ Corkscrews.progress(:work_done)
30
+ end
31
+ end
32
+
33
+ [parser, transformer, writer].each(&:join)
34
+ CorkscrewsBench.finish(progress: iterations, started_ns: started)
@@ -0,0 +1,17 @@
1
+ id: b07_pipeline
2
+ category: pipeline
3
+ targets: both
4
+ progress_point: work_done
5
+ truth:
6
+ target:
7
+ kind: line
8
+ file: base.rb
9
+ line: 33
10
+ optimized_speedup_of_target: 0.50
11
+ run:
12
+ repeat: 3
13
+ iterations: 120
14
+ sample_period_ms: 0.5
15
+ acceptance:
16
+ t1_mae_pct: 130.0
17
+ t4_overhead_pct: 45.0
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ iterations = CorkscrewsBench.iterations(160)
6
+ started = CorkscrewsBench.monotonic_ns
7
+ parse_q = Thread::SizedQueue.new(8)
8
+ write_q = Thread::SizedQueue.new(8)
9
+
10
+ parser = Thread.new do
11
+ iterations.times do |i|
12
+ CorkscrewsBench.busy(2_000)
13
+ parse_q << i
14
+ end
15
+ end
16
+
17
+ transformer = Thread.new do
18
+ iterations.times do
19
+ item = parse_q.pop
20
+ CorkscrewsBench.busy(4_000)
21
+ write_q << item
22
+ end
23
+ end
24
+
25
+ writer = Thread.new do
26
+ iterations.times do
27
+ write_q.pop
28
+ CorkscrewsBench.busy(2_000)
29
+ Corkscrews.progress(:work_done)
30
+ end
31
+ end
32
+
33
+ [parser, transformer, writer].each(&:join)
34
+ CorkscrewsBench.finish(progress: iterations, started_ns: started)
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ def native_call_work
6
+ 1_800.times.sum { |i| Integer.sqrt((i * i) + 7) }
7
+ end
8
+
9
+ iterations = CorkscrewsBench.iterations(500)
10
+ started = CorkscrewsBench.monotonic_ns
11
+ checksum = 0
12
+
13
+ iterations.times do
14
+ checksum ^= native_call_work
15
+ Corkscrews.progress(:work_done)
16
+ end
17
+
18
+ CorkscrewsBench.finish(progress: iterations, started_ns: started, checksum: checksum)
@@ -0,0 +1,18 @@
1
+ id: b08_native_attribution
2
+ category: native
3
+ targets: lines
4
+ progress_point: work_done
5
+ truth:
6
+ target:
7
+ kind: line
8
+ file: base.rb
9
+ line: 6
10
+ optimized_speedup_of_target: 0.50
11
+ run:
12
+ repeat: 3
13
+ iterations: 400
14
+ sample_period_ms: 0.5
15
+ round_ms: 10
16
+ acceptance:
17
+ t1_mae_pct: 80.0
18
+ t4_overhead_pct: 35.0
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../support"
4
+
5
+ def native_call_work
6
+ 900.times.sum { |i| Integer.sqrt((i * i) + 7) }
7
+ end
8
+
9
+ iterations = CorkscrewsBench.iterations(500)
10
+ started = CorkscrewsBench.monotonic_ns
11
+ checksum = 0
12
+
13
+ iterations.times do
14
+ checksum ^= native_call_work
15
+ Corkscrews.progress(:work_done)
16
+ end
17
+
18
+ CorkscrewsBench.finish(progress: iterations, started_ns: started, checksum: checksum)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "corkscrews"
5
+
6
+ module CorkscrewsBench
7
+ module_function
8
+
9
+ def iterations(default)
10
+ ENV.fetch("CS_BENCH_ITERATIONS", default.to_s).to_i
11
+ end
12
+
13
+ def monotonic_ns
14
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
15
+ end
16
+
17
+ def busy(iterations)
18
+ total = 0
19
+ iterations.times { |i| total += Integer.sqrt((i * i) + 7) }
20
+ total
21
+ end
22
+
23
+ def finish(progress:, started_ns:, checksum: 0)
24
+ elapsed_ns = monotonic_ns - started_ns
25
+ return unless ENV["CS_BENCH_JSON"] == "1"
26
+
27
+ puts JSON.generate(progress: progress, elapsed_ns: elapsed_ns, checksum: checksum)
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path("../../lib", __dir__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+
6
+ require "corkscrews/validate"
7
+
8
+ quick = ARGV.delete("--quick")
9
+ benchmark = nil
10
+ if (index = ARGV.index("--benchmark"))
11
+ benchmark = ARGV.fetch(index + 1)
12
+ end
13
+
14
+ result = Corkscrews::Validate.run_all(quick: quick, benchmark: benchmark)
15
+ puts JSON.pretty_generate(result.to_h)
16
+ exit(result.ok? ? 0 : 1)
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ """Independent smoke checks for validation statistics."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import statistics
7
+
8
+
9
+ def percentile(values: list[float], pct: float) -> float:
10
+ ordered = sorted(values)
11
+ index = round(pct * (len(ordered) - 1))
12
+ return ordered[index]
13
+
14
+
15
+ def main() -> int:
16
+ values = [9.7, 10.1, 10.4, 9.9, 10.2, 10.0, 10.3, 9.8]
17
+ mean = statistics.fmean(values)
18
+ lo = percentile(values, 0.025)
19
+ hi = percentile(values, 0.975)
20
+ if not lo <= mean <= hi:
21
+ raise SystemExit("mean is outside percentile interval")
22
+ print({"mean": mean, "interval": [lo, hi]})
23
+ return 0
24
+
25
+
26
+ if __name__ == "__main__":
27
+ raise SystemExit(main())
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/corkscrews/validate"
4
+
5
+ module Corkscrews
6
+ module Validate
7
+ module T1
8
+ module_function
9
+
10
+ def check!(manifest, profile, actual)
11
+ Validate.t1_prediction_check(manifest, profile, actual)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/corkscrews/validate"
4
+
5
+ module Corkscrews
6
+ module Validate
7
+ module T4
8
+ module_function
9
+
10
+ def check!(manifest, profile, actual)
11
+ Validate.t4_overhead_check(manifest, profile, actual)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../lib/corkscrews/validate"
4
+
5
+ module Corkscrews
6
+ module Validate
7
+ module T5
8
+ module_function
9
+
10
+ def check!
11
+ Validate.t5_statistics_check
12
+ end
13
+ end
14
+ end
15
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: corkscrews
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yudai Takada
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: fiddle
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
26
+ description: corkscrews records progress points, line samples, wait targets, and validation
27
+ benchmarks for Ruby causal profiling experiments.
28
+ email:
29
+ - t.yudai92@gmail.com
30
+ executables:
31
+ - corkscrews
32
+ extensions:
33
+ - ext/corkscrews/extconf.rb
34
+ extra_rdoc_files: []
35
+ files:
36
+ - LICENSE.txt
37
+ - README.md
38
+ - Rakefile
39
+ - exe/corkscrews
40
+ - ext/corkscrews/corkscrews.c
41
+ - ext/corkscrews/corkscrews_native.h
42
+ - ext/corkscrews/delay.c
43
+ - ext/corkscrews/extconf.rb
44
+ - ext/corkscrews/hooks.c
45
+ - ext/corkscrews/monitor.c
46
+ - ext/corkscrews/record.c
47
+ - ext/corkscrews/sampler.c
48
+ - lib/corkscrews.rb
49
+ - lib/corkscrews/analysis.rb
50
+ - lib/corkscrews/boot.rb
51
+ - lib/corkscrews/cli.rb
52
+ - lib/corkscrews/controller.rb
53
+ - lib/corkscrews/firefox_profile.rb
54
+ - lib/corkscrews/native.rb
55
+ - lib/corkscrews/primitives.rb
56
+ - lib/corkscrews/rack.rb
57
+ - lib/corkscrews/recorder.rb
58
+ - lib/corkscrews/report.rb
59
+ - lib/corkscrews/statistics.rb
60
+ - lib/corkscrews/time_source.rb
61
+ - lib/corkscrews/validate.rb
62
+ - lib/corkscrews/version.rb
63
+ - validate/benchmarks/b01_serial_hotspot/base.rb
64
+ - validate/benchmarks/b01_serial_hotspot/manifest.yml
65
+ - validate/benchmarks/b01_serial_hotspot/optimized.rb
66
+ - validate/benchmarks/b02_false_hotspot/base.rb
67
+ - validate/benchmarks/b02_false_hotspot/manifest.yml
68
+ - validate/benchmarks/b02_false_hotspot/optimized.rb
69
+ - validate/benchmarks/b03_io_wait/base.rb
70
+ - validate/benchmarks/b03_io_wait/manifest.yml
71
+ - validate/benchmarks/b03_io_wait/optimized.rb
72
+ - validate/benchmarks/b04_lock_contention/base.rb
73
+ - validate/benchmarks/b04_lock_contention/manifest.yml
74
+ - validate/benchmarks/b04_lock_contention/optimized.rb
75
+ - validate/benchmarks/b05_gvl_contention/base.rb
76
+ - validate/benchmarks/b05_gvl_contention/manifest.yml
77
+ - validate/benchmarks/b05_gvl_contention/optimized.rb
78
+ - validate/benchmarks/b06_gc_pressure/base.rb
79
+ - validate/benchmarks/b06_gc_pressure/manifest.yml
80
+ - validate/benchmarks/b06_gc_pressure/optimized.rb
81
+ - validate/benchmarks/b07_pipeline/base.rb
82
+ - validate/benchmarks/b07_pipeline/manifest.yml
83
+ - validate/benchmarks/b07_pipeline/optimized.rb
84
+ - validate/benchmarks/b08_native_attribution/base.rb
85
+ - validate/benchmarks/b08_native_attribution/manifest.yml
86
+ - validate/benchmarks/b08_native_attribution/optimized.rb
87
+ - validate/benchmarks/support.rb
88
+ - validate/harness/run_all.rb
89
+ - validate/harness/stats_check.py
90
+ - validate/harness/t1.rb
91
+ - validate/harness/t4.rb
92
+ - validate/harness/t5.rb
93
+ homepage: https://github.com/ydah/corkscrews
94
+ licenses:
95
+ - MIT
96
+ metadata:
97
+ allowed_push_host: https://rubygems.org
98
+ homepage_uri: https://github.com/ydah/corkscrews
99
+ source_code_uri: https://github.com/ydah/corkscrews
100
+ bug_tracker_uri: https://github.com/ydah/corkscrews/issues
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 3.3.0
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 4.0.6
116
+ specification_version: 4
117
+ summary: Causal profiling tools for Ruby bottleneck experiments.
118
+ test_files: []