rambling-trie 0.9.2 → 0.9.3

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
  SHA1:
3
- metadata.gz: 9db4c20b2cd932bc23376649e312e566eb43e227
4
- data.tar.gz: 40e5584acca19930a92cd894e43a51dccca4d1f1
3
+ metadata.gz: 54be3d6a000a38c0864250d0951a1986b2ceac2c
4
+ data.tar.gz: 5a8b13f581ce79c239f71e7e96c014572697f0c6
5
5
  SHA512:
6
- metadata.gz: f0e1a3166c876d3d3730dd439563567fbeb2108b33b908152c1a388daf2edf75cfbc250f67a7c0d00ec3dd923be3e71f770b3d3ff28bbd0ecaeadb3fe3fe162c
7
- data.tar.gz: 9f0decef0f2d1dd386677a8631888b4744315ede61b5f5957fd51ebf98b845a4564ea3ada4df60590ffcc8a82a27f5904d7261bd3dc21cf7f422c184932b8781
6
+ metadata.gz: 62bf472c3abfc664ca22e2df3ba55254d3e03e1d66ab7f3f64bba4755feaf6e4ce92de604ff5c7b479056840734b4e3ca0be4707af447f0521c327d1bbc274e6
7
+ data.tar.gz: c13d4ce29e89093292268426240cc543026f11a4e0747a33c65bcd7950b156629a39ac61a9a5a78a95320de82d734680a532a043ac78a4c56e0334e746f9bb72
data/Gemfile CHANGED
@@ -1,13 +1,22 @@
1
+ # frozen_string_literal: true
1
2
  source 'https://rubygems.org'
2
3
 
3
4
  gemspec
4
5
 
5
- gem 'coveralls', require: false
6
-
7
6
  group :development do
8
- gem 'simplecov', require: false
7
+ gem 'ruby-prof'
8
+ gem 'memory_profiler'
9
+ gem 'benchmark-ips'
10
+ gem 'flamegraph'
11
+ gem 'stackprof'
9
12
  end
10
13
 
11
14
  group :test do
15
+ gem 'simplecov', require: false
16
+ gem 'codeclimate-test-reporter', require: false
17
+ gem 'coveralls', require: false
18
+ end
19
+
20
+ group :local do
12
21
  gem 'guard-rspec'
13
22
  end
data/README.md CHANGED
@@ -134,6 +134,7 @@ You can find further API documentation on the autogenerated [rambling-trie gem R
134
134
 
135
135
  The Rambling Trie has been tested with the following Ruby versions:
136
136
 
137
+ * 2.4.x
137
138
  * 2.3.x
138
139
  * 2.2.x
139
140
  * 2.1.x
@@ -1,7 +1,8 @@
1
1
  require 'forwardable'
2
2
  %w{
3
- compression compressor inspector container enumerable invalid_operation
4
- plain_text_reader node missing_node compressed_node raw_node version
3
+ forwardable compression compressor inspector container enumerable
4
+ invalid_operation plain_text_reader node missing_node compressed_node
5
+ raw_node version
5
6
  }.each do |file|
6
7
  require File.join('rambling', 'trie', file)
7
8
  end
@@ -2,8 +2,7 @@ module Rambling
2
2
  module Trie
3
3
  # Wrapper on top of Trie data structure.
4
4
  class Container
5
- extend ::Forwardable
6
-
5
+ extend Rambling::Trie::Forwardable
7
6
  include ::Enumerable
8
7
 
9
8
  delegate [
@@ -13,6 +12,7 @@ module Rambling
13
12
  :children_tree,
14
13
  :compressed?,
15
14
  :each,
15
+ :to_a,
16
16
  :has_key?,
17
17
  :inspect,
18
18
  :letter,
@@ -21,6 +21,10 @@ module Rambling
21
21
  :to_s
22
22
  ] => :root
23
23
 
24
+ # The root node of this trie.
25
+ # @return [Node] the root node of this trie.
26
+ attr_reader :root
27
+
24
28
  # Creates a new Trie.
25
29
  # @param [Node] root the root node for the trie
26
30
  # @param [Compressor] compressor responsible for compressing the trie
@@ -81,7 +85,7 @@ module Rambling
81
85
  private
82
86
 
83
87
  attr_reader :compressor
84
- attr_accessor :root
88
+ attr_writer :root
85
89
 
86
90
  def default_root
87
91
  Rambling::Trie::RawNode.new
@@ -4,6 +4,9 @@ module Rambling
4
4
  module Enumerable
5
5
  include ::Enumerable
6
6
 
7
+ # Returns number of words contained in the trie. See
8
+ # {https://ruby-doc.org/core-2.4.0/Enumerable.html#method-i-count
9
+ # Enumerable}
7
10
  alias_method :size, :count
8
11
 
9
12
  # Iterates over the words contained in the trie.
@@ -0,0 +1,16 @@
1
+ module Rambling
2
+ module Trie
3
+ # Provides delegation behavior
4
+ module Forwardable
5
+ def delegate delegated_methods_to_delegated_to
6
+ delegated_methods_to_delegated_to.each do |methods, delegated_to|
7
+ methods.each do |method|
8
+ define_method method do |*args|
9
+ send(delegated_to).send method, *args
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,6 +2,8 @@ module Rambling
2
2
  module Trie
3
3
  # Raised when trying to execute an invalid operation on a Trie data structure.
4
4
  class InvalidOperation < Exception
5
+ # Creates a new InvalidOperation exception.
6
+ # @param [String, nil] message the exception message.
5
7
  def initialize message = nil
6
8
  super
7
9
  end
@@ -2,7 +2,10 @@ module Rambling
2
2
  module Trie
3
3
  # A representation of a node in the Trie data structure.
4
4
  class Node
5
- extend ::Forwardable
5
+ extend Rambling::Trie::Forwardable
6
+ include Rambling::Trie::Compression
7
+ include Rambling::Trie::Enumerable
8
+ include Rambling::Trie::Inspector
6
9
 
7
10
  delegate [
8
11
  :[],
@@ -11,10 +14,6 @@ module Rambling
11
14
  :has_key?
12
15
  ] => :children_tree
13
16
 
14
- include Rambling::Trie::Compression
15
- include Rambling::Trie::Enumerable
16
- include Rambling::Trie::Inspector
17
-
18
17
  # Letter or letters corresponding to this node.
19
18
  # @return [Symbol, nil] the corresponding letter(s) or nil.
20
19
  attr_reader :letter
@@ -54,15 +54,6 @@ module Rambling
54
54
  false
55
55
  end
56
56
 
57
- protected
58
-
59
- def closest_node chars
60
- letter = chars.slice!(0).to_sym
61
- child = children_tree[letter]
62
-
63
- child ? child.scan(chars) : Rambling::Trie::MissingNode.new
64
- end
65
-
66
57
  private
67
58
 
68
59
  def add_to_children_tree word
@@ -77,6 +68,13 @@ module Rambling
77
68
  node.letter = letter
78
69
  children_tree[letter] = node
79
70
  end
71
+
72
+ def closest_node chars
73
+ letter = chars.slice!(0).to_sym
74
+ child = children_tree[letter]
75
+
76
+ child ? child.scan(chars) : Rambling::Trie::MissingNode.new
77
+ end
80
78
  end
81
79
  end
82
80
  end
@@ -0,0 +1,17 @@
1
+ class PerformanceReport
2
+ attr_reader :output
3
+
4
+ def initialize output = $stdout.dup
5
+ @output = output
6
+ end
7
+
8
+ def start name
9
+ output.puts
10
+ output.puts "#{name} for rambling-trie version #{Rambling::Trie::VERSION}"
11
+ output.puts
12
+ end
13
+
14
+ def finish
15
+ output.close
16
+ end
17
+ end
@@ -3,9 +3,13 @@ require 'benchmark'
3
3
  require 'ruby-prof'
4
4
  require 'memory_profiler'
5
5
  require 'benchmark/ips'
6
+ require 'flamegraph'
6
7
  require_relative 'helpers/path'
8
+ require_relative 'helpers/time'
9
+ require_relative 'helpers/performance_report'
7
10
  require_relative 'performance/directory'
8
11
  require_relative 'performance/benchmark'
12
+ require_relative 'performance/flamegraph'
9
13
  require_relative 'performance/profile/call_tree'
10
14
  require_relative 'performance/profile/memory'
11
15
  require_relative 'performance/all'
@@ -1,20 +1,6 @@
1
- require_relative '../helpers/path'
2
-
3
1
  namespace :performance do
4
2
  include Helpers::Path
5
3
 
6
- class BenchmarkReport
7
- attr_reader :output
8
-
9
- def initialize output
10
- @output = output
11
- end
12
-
13
- def finish
14
- output.close
15
- end
16
- end
17
-
18
4
  class BenchmarkMeasurement
19
5
  def initialize output
20
6
  @output = output
@@ -42,10 +28,6 @@ namespace :performance do
42
28
  end
43
29
  end
44
30
 
45
- def banner
46
- output.puts "\nBenchmark for rambling-trie version #{Rambling::Trie::VERSION}"
47
- end
48
-
49
31
  private
50
32
 
51
33
  attr_reader :output
@@ -64,23 +46,20 @@ namespace :performance do
64
46
  end
65
47
  end
66
48
 
67
- def benchmark_report= benchmark_report
68
- @benchmark_report = benchmark_report
49
+ def performance_report= performance_report
50
+ @performance_report = performance_report
69
51
  end
70
52
 
71
- def benchmark_report
72
- Rake::Task['performance:benchmark:output:stdout'].invoke unless @benchmark_report
73
-
74
- @benchmark_report
53
+ def performance_report
54
+ @performance_report ||= PerformanceReport.new
75
55
  end
76
56
 
77
57
  def output
78
- benchmark_report.output
58
+ performance_report.output
79
59
  end
80
60
 
81
61
  def generate_lookups_benchmark filename = nil
82
62
  measure = BenchmarkMeasurement.new output
83
- measure.banner
84
63
 
85
64
  trie = Rambling::Trie.create dictionary
86
65
  compressed_trie = Rambling::Trie.create(dictionary).compress!
@@ -102,7 +81,6 @@ namespace :performance do
102
81
 
103
82
  def generate_scans_benchmark filename = nil
104
83
  measure = BenchmarkMeasurement.new output
105
- measure.banner
106
84
 
107
85
  words = {
108
86
  hi: 1_000,
@@ -128,38 +106,37 @@ namespace :performance do
128
106
 
129
107
  namespace :benchmark do
130
108
  namespace :output do
131
- desc 'Set task reporting output to stdout'
132
- task :stdout do
133
- self.benchmark_report = BenchmarkReport.new IO.new(1)
134
- end
135
-
136
109
  desc 'Set task reporting output to file'
137
110
  task file: ['performance:directory'] do
138
111
  path = path 'reports', Rambling::Trie::VERSION, 'benchmark'
139
112
  file = File.open path, 'a+'
140
- self.benchmark_report = BenchmarkReport.new file
113
+ self.performance_report = PerformanceReport.new file
141
114
  end
142
115
 
143
116
  desc 'Close output stream'
144
117
  task :close do
145
- benchmark_report.finish unless benchmark_report.nil?
118
+ performance_report.finish
146
119
  end
147
120
  end
148
121
 
122
+ desc 'Output banner'
123
+ task :banner do
124
+ performance_report.start 'Benchmark'
125
+ end
126
+
149
127
  desc 'Generate lookups performance benchmark report'
150
- task :lookups do
128
+ task lookups: :banner do
151
129
  generate_lookups_benchmark
152
130
  end
153
131
 
154
132
  desc 'Generate scans performance benchmark report'
155
- task :scans do
133
+ task scans: :banner do
156
134
  generate_scans_benchmark
157
135
  end
158
136
 
159
137
  desc 'Generate creation performance benchmark report'
160
- task :creation do
138
+ task creation: :banner do
161
139
  measure = BenchmarkMeasurement.new output
162
- measure.banner
163
140
 
164
141
  output.puts '==> Creation'
165
142
  output.puts '`Rambling::Trie.create`'
@@ -170,9 +147,8 @@ namespace :performance do
170
147
  end
171
148
 
172
149
  desc 'Generate compression performance benchmark report'
173
- task :compression do
150
+ task compression: :banner do
174
151
  measure = BenchmarkMeasurement.new output
175
- measure.banner
176
152
 
177
153
  output.puts '==> Compression'
178
154
  output.puts '`compress!`'
@@ -188,22 +164,23 @@ namespace :performance do
188
164
 
189
165
  desc 'Generate all performance benchmark reports'
190
166
  task all: [
191
- 'creation',
192
- 'compression',
193
- 'lookups',
194
- 'scans',
167
+ :creation,
168
+ :compression,
169
+ :lookups,
170
+ :scans,
195
171
  ]
196
172
 
197
173
  namespace :all do
198
174
  desc "Generate and store performance benchmark report in reports/#{Rambling::Trie::VERSION}"
199
175
  task save: [
200
176
  'output:file',
201
- 'all'
177
+ :all
202
178
  ]
203
179
  end
204
180
 
205
181
  desc 'Compare ips for different implementations (changes over time)'
206
182
  task :compare do
183
+ require 'benchmark/ips'
207
184
  Benchmark.ips do |b|
208
185
  hash = { 'thing' => 'gniht' }
209
186
 
@@ -0,0 +1,119 @@
1
+ namespace :performance do
2
+ include Helpers::Path
3
+ include Helpers::Time
4
+
5
+ def performance_report
6
+ @performance_report ||= PerformanceReport.new
7
+ end
8
+
9
+ def output
10
+ performance_report.output
11
+ end
12
+
13
+ class FlamegraphProfile
14
+ def initialize filename
15
+ @filename = filename
16
+ end
17
+
18
+ def perform times, params = nil
19
+ params = Array params
20
+ params << nil unless params.any?
21
+
22
+ dirname = path 'reports', Rambling::Trie::VERSION, 'flamegraph', time
23
+ FileUtils.mkdir_p dirname
24
+ path = File.join dirname, "#{filename}.html"
25
+
26
+ result = Flamegraph.generate path do
27
+ params.each do |param|
28
+ times.times do
29
+ yield param
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ attr_reader :filename
38
+ end
39
+
40
+ namespace :flamegraph do
41
+ desc 'Output banner'
42
+ task :banner do
43
+ performance_report.start 'Flamegraph'
44
+ end
45
+
46
+ desc 'Generate flamegraph reports for creation'
47
+ task creation: ['performance:directory', :banner] do
48
+ output.puts 'Generating flamegraph reports for creation...'
49
+
50
+ flamegraph = FlamegraphProfile.new 'new-trie'
51
+ flamegraph.perform 1 do
52
+ trie = Rambling::Trie.create dictionary
53
+ end
54
+ end
55
+
56
+ desc 'Generate flamegraph reports for compression'
57
+ task compression: ['performance:directory', :banner] do
58
+ output.puts 'Generating flamegraph reports for compression...'
59
+
60
+ tries = [ Rambling::Trie.create(dictionary) ]
61
+
62
+ flamegraph = FlamegraphProfile.new 'compressed-trie'
63
+ flamegraph.perform 1, tries do |trie|
64
+ trie.compress!
65
+ nil
66
+ end
67
+ end
68
+
69
+ desc 'Generate flamegraph reports for lookups'
70
+ task lookups: ['performance:directory', :banner] do
71
+ output.puts 'Generating flamegraph reports for lookups...'
72
+
73
+ words = %w(hi help beautiful impressionism anthropological)
74
+
75
+ trie = Rambling::Trie.create dictionary
76
+ compressed_trie = Rambling::Trie.create(dictionary).compress!
77
+
78
+ [ trie, compressed_trie ].each do |trie|
79
+ prefix = "#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie"
80
+
81
+ flamegraph = FlamegraphProfile.new "#{prefix}-word"
82
+ flamegraph.perform 1, words do |word|
83
+ trie.word? word
84
+ end
85
+
86
+ flamegraph = FlamegraphProfile.new "#{prefix}-partial-word"
87
+ flamegraph.perform 1, words do |word|
88
+ trie.partial_word? word
89
+ end
90
+ end
91
+ end
92
+
93
+ desc 'Generate flamegraph reports for scans'
94
+ task scans: ['performance:directory', :banner] do
95
+ output.puts 'Generating flamegraph reports for scans...'
96
+
97
+ words = %w(hi help beautiful impressionism anthropological)
98
+
99
+ trie = Rambling::Trie.create dictionary
100
+ compressed_trie = Rambling::Trie.create(dictionary).compress!
101
+
102
+ [ trie, compressed_trie ].each do |trie|
103
+ prefix = "#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie"
104
+ flamegraph = FlamegraphProfile.new "#{prefix}-scan"
105
+ flamegraph.perform 1, words do |word|
106
+ trie.scan(word).size
107
+ end
108
+ end
109
+ end
110
+
111
+ desc 'Generate all flamegraph reports'
112
+ task all: [
113
+ :creation,
114
+ :compression,
115
+ :lookups,
116
+ :scans,
117
+ ]
118
+ end
119
+ end