File: rebind_vs_prepend.rb

package info (click to toggle)
ruby-traces 0.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 168 kB
  • sloc: ruby: 478; makefile: 4
file content (77 lines) | stat: -rw-r--r-- 1,187 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# frozen_string_literal: true

# Released under the MIT License.
# Copyright, 2021-2022, by Samuel Williams.

require 'benchmark/ips'

class MyClass1
	def my_method
		true
	end
end

module Tracer1
	def my_method(...)
		super
	end
end

MyClass1.prepend(Tracer1)

class MyClass2
	def my_method
		true
	end
end

module Tracer2
	def trace(name)
		original_method = instance_method(name)
		trace_provider = @trace_provider
		
		remove_method(name)
		
		define_method(name) do |*arguments, &block|
			original_method.bind(self).call(*arguments, &block)
		end
		
		ruby2_keywords(name)
	end
end

MyClass2.extend(Tracer2)
MyClass2.trace(:my_method)

module Trace
	module Provider
		def trace_provider
			@trace_provider ||= Module.new
		end
		
		def trace(name)
			trace_provider.module_eval "def #{name}(...); super; end"
		end
	end
	
	def self.Provider(klass)
		klass.extend(Provider)
		klass.prepend(klass.trace_provider)
	end
end

class MyClass3
	Trace::Provider(self)
	
	trace def my_method
		true
	end
end

Benchmark.ips do |x|
	x.report("MyClass1", "MyClass1.new.my_method")
	x.report("MyClass2", "MyClass2.new.my_method")
	x.report("MyClass3", "MyClass3.new.my_method")

	x.compare!
end