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 +4 -4
- data/Gemfile +12 -3
- data/README.md +1 -0
- data/lib/rambling/trie.rb +3 -2
- data/lib/rambling/trie/container.rb +7 -3
- data/lib/rambling/trie/enumerable.rb +3 -0
- data/lib/rambling/trie/forwardable.rb +16 -0
- data/lib/rambling/trie/invalid_operation.rb +2 -0
- data/lib/rambling/trie/node.rb +4 -5
- data/lib/rambling/trie/raw_node.rb +7 -9
- data/lib/rambling/trie/tasks/helpers/performance_report.rb +17 -0
- data/lib/rambling/trie/tasks/performance.rb +4 -0
- data/lib/rambling/trie/tasks/performance/benchmark.rb +22 -45
- data/lib/rambling/trie/tasks/performance/flamegraph.rb +119 -0
- data/lib/rambling/trie/tasks/performance/profile/call_tree.rb +65 -56
- data/lib/rambling/trie/tasks/performance/profile/memory.rb +69 -43
- data/lib/rambling/trie/version.rb +1 -1
- data/rambling-trie.gemspec +1 -5
- data/spec/assets/{test_words.txt → test_words.en_US.txt} +0 -0
- data/spec/assets/test_words.es_DO.txt +23 -0
- data/spec/integration/rambling/trie_spec.rb +17 -9
- data/spec/lib/rambling/trie/container_spec.rb +6 -0
- data/spec/lib/rambling/trie/node_spec.rb +0 -5
- data/spec/lib/rambling/trie/plain_text_reader_spec.rb +1 -1
- data/spec/lib/rambling/trie_spec.rb +2 -2
- data/spec/spec_helper.rb +7 -0
- metadata +9 -86
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -31
- data/.rspec +0 -1
- data/.travis.yml +0 -26
- data/assets/dictionaries/words_with_friends.txt +0 -172820
@@ -1,31 +1,46 @@
|
|
1
|
-
require_relative '../../helpers/path'
|
2
|
-
require_relative '../../helpers/time'
|
3
|
-
|
4
1
|
namespace :performance do
|
5
2
|
namespace :profile do
|
6
3
|
include Helpers::Path
|
7
4
|
include Helpers::Time
|
8
5
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
6
|
+
def performance_report
|
7
|
+
@performance_report ||= PerformanceReport.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def output
|
11
|
+
performance_report.output
|
12
|
+
end
|
13
|
+
|
14
|
+
class CallTreeProfile
|
15
|
+
def initialize dirname
|
16
|
+
@dirname = dirname
|
17
|
+
end
|
18
|
+
|
19
|
+
def perform times, params = nil
|
20
|
+
params = Array params
|
21
|
+
params << nil unless params.any?
|
12
22
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
23
|
+
result = RubyProf.profile merge_fibers: true do
|
24
|
+
params.each do |param|
|
25
|
+
times.times do
|
26
|
+
yield param
|
27
|
+
end
|
17
28
|
end
|
18
29
|
end
|
30
|
+
|
31
|
+
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, dirname
|
32
|
+
FileUtils.mkdir_p path
|
33
|
+
printer = RubyProf::CallTreePrinter.new result
|
34
|
+
printer.print path: path
|
19
35
|
end
|
20
36
|
|
21
|
-
|
22
|
-
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :dirname
|
23
40
|
end
|
24
41
|
|
25
42
|
def generate_lookups_call_tree
|
26
|
-
puts 'Generating call tree profiling reports for lookups...'
|
27
|
-
|
28
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
43
|
+
output.puts 'Generating call tree profiling reports for lookups...'
|
29
44
|
|
30
45
|
words = %w(hi help beautiful impressionism anthropological)
|
31
46
|
|
@@ -33,30 +48,24 @@ namespace :performance do
|
|
33
48
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
34
49
|
|
35
50
|
[ trie, compressed_trie ].each do |trie|
|
36
|
-
|
37
|
-
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, filename
|
38
|
-
FileUtils.mkdir_p path
|
51
|
+
prefix = "profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}"
|
39
52
|
|
40
|
-
|
53
|
+
call_tree_profile = CallTreeProfile.new "#{prefix}-word"
|
54
|
+
call_tree_profile.perform 200_000, words do
|
41
55
|
trie.word? word
|
42
56
|
end
|
43
57
|
|
44
|
-
|
45
|
-
|
46
|
-
FileUtils.mkdir_p path
|
47
|
-
|
48
|
-
profile 200_000, words, path do
|
58
|
+
call_tree_profile = CallTreeProfile.new "#{prefix}-partial-word"
|
59
|
+
call_tree_profile.perform 200_000, words do
|
49
60
|
trie.partial_word? word
|
50
61
|
end
|
51
62
|
end
|
52
63
|
|
53
|
-
puts 'Done'
|
64
|
+
output.puts 'Done'
|
54
65
|
end
|
55
66
|
|
56
67
|
def generate_scans_call_tree
|
57
|
-
puts 'Generating call tree profiling reports for scans...'
|
58
|
-
|
59
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
68
|
+
output.puts 'Generating call tree profiling reports for scans...'
|
60
69
|
|
61
70
|
words = {
|
62
71
|
hi: 1_000,
|
@@ -70,68 +79,68 @@ namespace :performance do
|
|
70
79
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
71
80
|
|
72
81
|
[ trie, compressed_trie ].each do |trie|
|
73
|
-
|
74
|
-
|
75
|
-
FileUtils.mkdir_p path
|
82
|
+
dirname = "profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}-scan"
|
83
|
+
call_tree_profile = CallTreeProfile.new dirname
|
76
84
|
|
77
85
|
words.each do |word, times|
|
78
|
-
|
86
|
+
call_tree_profile.perform times, word.to_s do |word|
|
79
87
|
trie.scan(word).size
|
80
88
|
end
|
81
89
|
end
|
82
90
|
end
|
83
91
|
|
84
|
-
puts 'Done'
|
92
|
+
output.puts 'Done'
|
85
93
|
end
|
86
94
|
|
87
95
|
namespace :call_tree do
|
96
|
+
desc 'Output banner'
|
97
|
+
task :banner do
|
98
|
+
performance_report.start 'Call Tree profile'
|
99
|
+
end
|
100
|
+
|
88
101
|
desc 'Generate call tree profiling reports for creation'
|
89
|
-
task creation: ['performance:directory'] do
|
90
|
-
puts 'Generating call tree profiling reports for creation...'
|
91
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
92
|
-
filename = "profile-new-trie"
|
93
|
-
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, filename
|
94
|
-
FileUtils.mkdir_p path
|
102
|
+
task creation: ['performance:directory', :banner] do
|
103
|
+
output.puts 'Generating call tree profiling reports for creation...'
|
95
104
|
|
96
|
-
|
105
|
+
call_tree_profile = CallTreeProfile.new 'profile-new-trie'
|
106
|
+
call_tree_profile.perform 5 do
|
97
107
|
trie = Rambling::Trie.create dictionary
|
98
108
|
end
|
109
|
+
|
110
|
+
output.puts 'Done'
|
99
111
|
end
|
100
112
|
|
101
113
|
desc 'Generate call tree profiling reports for compression'
|
102
|
-
task compression: ['performance:directory'] do
|
103
|
-
puts 'Generating call tree profiling reports for compression...'
|
104
|
-
puts "\nCall Tree profile for rambling-trie version #{Rambling::Trie::VERSION}"
|
105
|
-
|
106
|
-
filename = "profile-compressed-trie"
|
107
|
-
path = path 'reports', Rambling::Trie::VERSION, 'call-tree', time, filename
|
108
|
-
FileUtils.mkdir_p path
|
114
|
+
task compression: ['performance:directory', :banner] do
|
115
|
+
output.puts 'Generating call tree profiling reports for compression...'
|
109
116
|
|
110
117
|
tries = []
|
111
118
|
5.times { tries << Rambling::Trie.create(dictionary) }
|
112
119
|
|
113
|
-
|
114
|
-
|
115
|
-
nil
|
120
|
+
call_tree_profile = CallTreeProfile.new 'profile-compressed-trie'
|
121
|
+
call_tree_profile.perform 5, tries do |trie|
|
122
|
+
trie.compress!; nil
|
116
123
|
end
|
124
|
+
|
125
|
+
output.puts 'Done'
|
117
126
|
end
|
118
127
|
|
119
128
|
desc 'Generate call tree profiling reports for lookups'
|
120
|
-
task lookups: ['performance:directory'] do
|
129
|
+
task lookups: ['performance:directory', :banner] do
|
121
130
|
generate_lookups_call_tree
|
122
131
|
end
|
123
132
|
|
124
133
|
desc 'Generate call tree profiling reports for scans'
|
125
|
-
task scans: ['performance:directory'] do
|
134
|
+
task scans: ['performance:directory', :banner] do
|
126
135
|
generate_scans_call_tree
|
127
136
|
end
|
128
137
|
|
129
138
|
desc 'Generate all call tree profiling reports'
|
130
139
|
task all: [
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
140
|
+
:creation,
|
141
|
+
:compression,
|
142
|
+
:lookups,
|
143
|
+
:scans,
|
135
144
|
]
|
136
145
|
end
|
137
146
|
end
|
@@ -1,55 +1,79 @@
|
|
1
|
-
require_relative '../../helpers/path'
|
2
|
-
require_relative '../../helpers/time'
|
3
|
-
|
4
1
|
namespace :performance do
|
5
2
|
namespace :profile do
|
6
3
|
include Helpers::Path
|
7
4
|
include Helpers::Time
|
8
5
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
def performance_report
|
7
|
+
@performance_report ||= PerformanceReport.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def output
|
11
|
+
performance_report.output
|
13
12
|
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
class MemoryProfile
|
15
|
+
def initialize name
|
16
|
+
@name = name
|
17
|
+
end
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
def perform
|
20
|
+
result = MemoryProfiler.report allow_files: 'lib/rambling/trie', ignore_files: 'lib/rambling/trie/tasks' do
|
21
|
+
with_gc_stats do
|
22
|
+
yield
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
dir = path 'reports', Rambling::Trie::VERSION, 'memory', time
|
27
|
+
FileUtils.mkdir_p dir
|
28
|
+
result.pretty_print to_file: File.join(dir, name)
|
21
29
|
end
|
22
30
|
|
23
|
-
|
24
|
-
|
25
|
-
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :name
|
34
|
+
end
|
35
|
+
|
36
|
+
def with_gc_stats
|
37
|
+
output.puts "Live objects before - #{GC.stat[:heap_live_slots]}"
|
38
|
+
yield
|
39
|
+
output.puts "Live objects after - #{GC.stat[:heap_live_slots]}"
|
26
40
|
end
|
27
41
|
|
28
42
|
namespace :memory do
|
43
|
+
desc 'Output banner'
|
44
|
+
task :banner do
|
45
|
+
performance_report.start 'Memory profile'
|
46
|
+
end
|
47
|
+
|
29
48
|
desc 'Generate memory profiling reports for creation'
|
30
|
-
task creation: ['performance:directory'] do
|
31
|
-
puts 'Generating memory profiling reports for creation...'
|
49
|
+
task creation: ['performance:directory', :banner] do
|
50
|
+
output.puts 'Generating memory profiling reports for creation...'
|
32
51
|
|
33
52
|
trie = nil
|
34
53
|
|
35
|
-
memory_profile
|
36
|
-
|
54
|
+
memory_profile = MemoryProfile.new 'memory-profile-new-trie'
|
55
|
+
memory_profile.perform do
|
56
|
+
trie = Rambling::Trie.create dictionary
|
37
57
|
end
|
38
58
|
end
|
39
59
|
|
40
60
|
desc 'Generate memory profiling reports for compression'
|
41
|
-
task compression: ['performance:directory'] do
|
61
|
+
task compression: ['performance:directory', :banner] do
|
62
|
+
output.puts 'Generating memory profiling reports for compression...'
|
42
63
|
trie = Rambling::Trie.create dictionary
|
43
64
|
|
44
|
-
memory_profile
|
45
|
-
|
65
|
+
memory_profile = MemoryProfile.new 'memory-profile-trie-and-compress'
|
66
|
+
memory_profile.perform do
|
67
|
+
trie.compress!
|
46
68
|
end
|
47
69
|
|
48
70
|
with_gc_stats { GC.start }
|
49
71
|
end
|
50
72
|
|
51
73
|
desc 'Generate memory profiling reports for lookups'
|
52
|
-
task lookups: ['performance:directory'] do
|
74
|
+
task lookups: ['performance:directory', :banner] do
|
75
|
+
output.puts 'Generating memory profiling reports for lookups...'
|
76
|
+
|
53
77
|
words = %w(hi help beautiful impressionism anthropological)
|
54
78
|
|
55
79
|
trie = Rambling::Trie.create dictionary
|
@@ -57,24 +81,23 @@ namespace :performance do
|
|
57
81
|
[ trie, compressed_trie ].each do |trie|
|
58
82
|
times = 10
|
59
83
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
84
|
+
prefix = "memory-profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie"
|
85
|
+
name = "#{prefix}-word"
|
86
|
+
memory_profile = MemoryProfile.new name
|
87
|
+
memory_profile.perform do
|
88
|
+
words.each do |word|
|
89
|
+
times.times do
|
90
|
+
trie.word? word
|
67
91
|
end
|
68
92
|
end
|
69
93
|
end
|
70
94
|
|
71
|
-
name = "
|
72
|
-
memory_profile name
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
end
|
95
|
+
name = "#{prefix}-partial-word"
|
96
|
+
memory_profile = MemoryProfile.new name
|
97
|
+
memory_profile.perform do
|
98
|
+
words.each do |word|
|
99
|
+
times.times do
|
100
|
+
trie.partial_word? word
|
78
101
|
end
|
79
102
|
end
|
80
103
|
end
|
@@ -82,7 +105,9 @@ namespace :performance do
|
|
82
105
|
end
|
83
106
|
|
84
107
|
desc 'Generate memory profiling reports for scans'
|
85
|
-
task scans: ['performance:directory'] do
|
108
|
+
task scans: ['performance:directory', :banner] do
|
109
|
+
output.puts 'Generating memory profiling reports for scans...'
|
110
|
+
|
86
111
|
words = {
|
87
112
|
hi: 1,
|
88
113
|
help: 100,
|
@@ -95,7 +120,8 @@ namespace :performance do
|
|
95
120
|
compressed_trie = Rambling::Trie.create(dictionary).compress!
|
96
121
|
[ trie, compressed_trie ].each do |trie|
|
97
122
|
name = "memory-profile-#{trie.compressed? ? 'compressed' : 'uncompressed'}-trie-scan"
|
98
|
-
memory_profile name
|
123
|
+
memory_profile = MemoryProfile.new name
|
124
|
+
memory_profile.perform do
|
99
125
|
words.each do |word, times|
|
100
126
|
times.times do
|
101
127
|
trie.scan(word.to_s).size
|
@@ -107,10 +133,10 @@ namespace :performance do
|
|
107
133
|
|
108
134
|
desc 'Generate all memory profiling reports'
|
109
135
|
task all: [
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
136
|
+
:creation,
|
137
|
+
:compression,
|
138
|
+
:lookups,
|
139
|
+
:scans,
|
114
140
|
]
|
115
141
|
end
|
116
142
|
end
|
data/rambling-trie.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |gem|
|
|
11
11
|
gem.date = Time.now.strftime '%Y-%m-%d'
|
12
12
|
|
13
13
|
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename f }
|
14
|
-
gem.files = `git ls-files`.split "\n"
|
14
|
+
gem.files = `git ls-files -- {lib,*file,*.gemspec,LICENSE*,README*}`.split "\n"
|
15
15
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split "\n"
|
16
16
|
gem.require_paths = ['lib']
|
17
17
|
|
@@ -22,9 +22,5 @@ Gem::Specification.new do |gem|
|
|
22
22
|
|
23
23
|
gem.add_development_dependency 'rspec', '~> 3.5'
|
24
24
|
gem.add_development_dependency 'rake', '~> 12.0'
|
25
|
-
gem.add_development_dependency 'ruby-prof', '~> 0.16.2'
|
26
|
-
gem.add_development_dependency 'memory_profiler', '~> 0.9.7'
|
27
|
-
gem.add_development_dependency 'benchmark-ips', '~> 2.7.2'
|
28
25
|
gem.add_development_dependency 'yard', '~> 0.9.5'
|
29
|
-
gem.add_development_dependency 'redcarpet', '~> 3.3.4'
|
30
26
|
end
|
File without changes
|
@@ -53,20 +53,28 @@ describe Rambling::Trie do
|
|
53
53
|
describe 'with words provided directly' do
|
54
54
|
it_behaves_like 'a compressable trie' do
|
55
55
|
let(:words) { %w[a couple of words for our full trie integration test] }
|
56
|
-
let(:trie) { Rambling::Trie.create }
|
57
|
-
|
58
|
-
before do
|
59
|
-
words.each do |word|
|
60
|
-
trie << word
|
61
|
-
trie.add word
|
62
|
-
end
|
63
|
-
end
|
56
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
64
57
|
end
|
65
58
|
end
|
66
59
|
|
67
60
|
describe 'with words from a file' do
|
68
61
|
it_behaves_like 'a compressable trie' do
|
69
|
-
let(:filepath) { File.join ::SPEC_ROOT, 'assets', 'test_words.txt' }
|
62
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'assets', 'test_words.en_US.txt' }
|
63
|
+
let(:words) { File.readlines(filepath).map &:chomp! }
|
64
|
+
let(:trie) { Rambling::Trie.create filepath }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'with words with unicode characters' do
|
69
|
+
it_behaves_like 'a compressable trie' do
|
70
|
+
let(:words) { %w[poquísimas palabras para nuestra prueba de integración completa] }
|
71
|
+
let(:trie) { Rambling::Trie.create { |t| words.each { |w| t << w } } }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
describe 'with words with unicode characters from a file' do
|
76
|
+
it_behaves_like 'a compressable trie' do
|
77
|
+
let(:filepath) { File.join ::SPEC_ROOT, 'assets', 'test_words.en_US.txt' }
|
70
78
|
let(:words) { File.readlines(filepath).map &:chomp! }
|
71
79
|
let(:trie) { Rambling::Trie.create filepath }
|
72
80
|
end
|