rambling-trie 0.9.2 → 0.9.3

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
  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