trace_visualization 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -0
- data/Rakefile +4 -4
- data/bin/trace_visualization +133 -0
- data/lib/trace_visualization.rb +6 -0
- data/lib/trace_visualization/mapping.rb +61 -42
- data/lib/trace_visualization/reorder.rb +2 -0
- data/lib/trace_visualization/repetitions_score.rb +87 -0
- data/lib/trace_visualization/utils.rb +1 -1
- data/lib/trace_visualization/version.rb +1 -1
- data/lib/trace_visualization/visualization/console_color_print.rb +8 -8
- data/spec/bwt_spec.rb +3 -5
- data/spec/longest_common_prefix_spec.rb +11 -4
- data/spec/repetitions_concatenation_spec.rb +8 -2
- data/spec/repetitions_psy_spec.rb +23 -10
- data/spec/suffix_array_spec.rb +64 -37
- data/trace_visualization.gemspec +14 -14
- metadata +6 -15
- data/lib/trace_visualization/preprocessor/Makefile +0 -43
- data/lib/trace_visualization/preprocessor/hashmap.c +0 -93
- data/lib/trace_visualization/preprocessor/hashmap.h +0 -27
- data/lib/trace_visualization/preprocessor/hashmap_test.cpp +0 -90
- data/lib/trace_visualization/preprocessor/lexeme.h +0 -11
- data/lib/trace_visualization/preprocessor/lexeme_table.c +0 -50
- data/lib/trace_visualization/preprocessor/lexeme_table.h +0 -13
- data/lib/trace_visualization/preprocessor/lexeme_table_cpp.h +0 -61
- data/lib/trace_visualization/preprocessor/parser_functions.c +0 -42
- data/lib/trace_visualization/preprocessor/parser_test.cpp +0 -71
- data/lib/trace_visualization/preprocessor/preprocessor.l +0 -18
- data/lib/trace_visualization/preprocessor/test_main.cpp +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12c27504ea6bbbabd78f47e5bee3df251a5a7050
|
4
|
+
data.tar.gz: 75a0bf55e52a108f449def1998de4fbf319d1f94
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6fff098106b2ba908595a05345bebafc5686348454061983671c937c21a26ecb0cee59a8d6209203707949e7283daba5d620b7d386cd1ac230e021668f4a7f5
|
7
|
+
data.tar.gz: 6e39264b5f0141746d7fda75d4c2c2be624a0829c12ed548160e6bd9f74afac162b06a6e9e670155ef042f7b7baf65eb0bff43a42236051f0aec81b15842495c
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
2
|
|
3
|
-
desc 'Compile preprocessor'
|
4
|
-
task :install do
|
5
|
-
system('cd
|
6
|
-
end
|
3
|
+
#desc 'Compile preprocessor'
|
4
|
+
#task :install do
|
5
|
+
# system('cd ext/preprocessor; make install')
|
6
|
+
#end
|
7
7
|
|
8
8
|
desc 'Spec all functionality of gem'
|
9
9
|
task :spec_all do
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'trace_visualization'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'benchmark'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
include TraceVisualization
|
9
|
+
|
10
|
+
##
|
11
|
+
# Parse command line options
|
12
|
+
def parse_options
|
13
|
+
options = {}
|
14
|
+
|
15
|
+
optionParser = OptionParser.new do|opts|
|
16
|
+
opts.banner = "Usage: trace_visualization [options] file"
|
17
|
+
|
18
|
+
options[:offset] = 0
|
19
|
+
opts.on('-x', '--offset N', 'Number of lines for offset. Default 0') do |n|
|
20
|
+
options[:offset] = n.to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
options[:limit] = 2**32
|
24
|
+
opts.on('-l', '--limit N', "Number of lines. Default #{options[:limit]}") do |n|
|
25
|
+
options[:limit] = n.to_i
|
26
|
+
end
|
27
|
+
|
28
|
+
options[:out] = 3
|
29
|
+
opts.on('-o', '--out N', 'Number of output results') do |n|
|
30
|
+
options[:out] = n.to_i
|
31
|
+
end
|
32
|
+
|
33
|
+
options[:positions_min_size] = 3
|
34
|
+
opts.on('-m', '--positions_min_size N', "The minimum number of repetition positions. Default #{options[:positions_min_size]}") do |s|
|
35
|
+
options[:positions_min_size] = s.to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
options[:test_preprocessor_performance] = false
|
39
|
+
opts.on('-t', '--test_preprocessor_performance', 'Test preprocessor performance') do
|
40
|
+
options[:test_preprocessor_performance] = true
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on('-h', '--help', 'Display this screen') do
|
44
|
+
puts opts
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
optionParser.parse!
|
50
|
+
|
51
|
+
options[:source_file_name] = ARGV[0]
|
52
|
+
|
53
|
+
options
|
54
|
+
end
|
55
|
+
|
56
|
+
#------------------------------------------------------------------------------
|
57
|
+
def foo(options)
|
58
|
+
|
59
|
+
preprocessorConfig = TracePreprocessor.init do
|
60
|
+
use_default_lexemes
|
61
|
+
|
62
|
+
output_token "printf(\"{TOKEN;%s;%s;%ld;%d}\", name, source, value, value_kind);"
|
63
|
+
end
|
64
|
+
|
65
|
+
preprocessor = nil
|
66
|
+
bm('Preprocessor Generate') do
|
67
|
+
preprocessor = TracePreprocessor.generate(preprocessorConfig, :c)
|
68
|
+
end
|
69
|
+
|
70
|
+
tmp_file = Tempfile.new('trace_visualization')
|
71
|
+
|
72
|
+
bm('Preprocessor work') do
|
73
|
+
preprocessor.run options[:source_file_name], tmp_file.path
|
74
|
+
end
|
75
|
+
|
76
|
+
mapping = nil
|
77
|
+
bm('Mapping') do
|
78
|
+
mapping = TraceVisualization::Mapping.new
|
79
|
+
mapping.process_without_reorder { from_preprocessed_file(tmp_file.path, options[:offset], options[:limit], !options[:test_preprocessor_performance]) }
|
80
|
+
end
|
81
|
+
|
82
|
+
source_file_length = `wc -c #{options[:source_file_name]}`.to_i
|
83
|
+
tmp_file_length = tmp_file.length
|
84
|
+
|
85
|
+
puts "source_file_length = #{source_file_length}"
|
86
|
+
puts "tmp_file_length = #{tmp_file_length} (+#{((tmp_file_length - source_file_length) * 100.0 / source_file_length).round(2)}%)"
|
87
|
+
puts "mapping_length = #{mapping.length} (-#{((source_file_length - mapping.length) * 100.0 / source_file_length).round(2)}%)"
|
88
|
+
|
89
|
+
tmp_file.close
|
90
|
+
tmp_file.unlink
|
91
|
+
|
92
|
+
if options[:test_preprocessor_performance]
|
93
|
+
puts "Finish preprocessor"
|
94
|
+
exit 0
|
95
|
+
end
|
96
|
+
|
97
|
+
rs = nil
|
98
|
+
bm('PSY1') do
|
99
|
+
rs = Repetitions.psy1(mapping, options[:positions_min_size], true)
|
100
|
+
end
|
101
|
+
|
102
|
+
puts "rs.size = #{rs.size}"
|
103
|
+
|
104
|
+
#context = nil
|
105
|
+
#bm('Context') do
|
106
|
+
# context = TraceVisualization::Repetitions::Context.new(mapping, rs)
|
107
|
+
#end
|
108
|
+
|
109
|
+
RepetitionsScore.fill_score(rs, :sort => true, :order => 'desc', :version => 'relative')
|
110
|
+
|
111
|
+
rs[0 ... options[:out]].each do |r|
|
112
|
+
puts '---------------------'
|
113
|
+
puts r
|
114
|
+
puts Visualization::ConsoleColorPrint.hl(mapping, r)
|
115
|
+
end
|
116
|
+
|
117
|
+
rs
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def bm(name, &block)
|
122
|
+
Benchmark.bm(17) do |x|
|
123
|
+
x.report(name, &block)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
options = parse_options
|
129
|
+
rs = foo(options)
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
|
data/lib/trace_visualization.rb
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
mapping
|
3
3
|
utils
|
4
4
|
version
|
5
|
+
reorder
|
6
|
+
repetitions
|
7
|
+
repetitions_psy
|
8
|
+
repetitions_context
|
9
|
+
repetitions_score
|
10
|
+
visualization/console_color_print
|
5
11
|
).each { |file| require File.join(File.dirname(__FILE__), 'trace_visualization', file) }
|
6
12
|
|
7
13
|
require 'logger'
|
@@ -58,61 +58,73 @@ module TraceVisualization
|
|
58
58
|
@max_value = TraceVisualization::Reorder.process(@mapped_str)
|
59
59
|
end
|
60
60
|
|
61
|
+
def process_without_reorder(&block)
|
62
|
+
instance_eval(&block)
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
61
66
|
# Load data from source file. File is read line by line
|
67
|
+
|
62
68
|
def from_file(path)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
69
|
+
validate_file_name_argument(path)
|
70
|
+
|
71
|
+
open(path) do |fd|
|
72
|
+
while (line = fd.gets)
|
73
|
+
process_line(line)
|
74
|
+
end
|
75
|
+
end
|
70
76
|
end
|
71
77
|
|
78
|
+
##
|
72
79
|
# Load data from preprocessed file. File is read line by line
|
73
|
-
def from_preprocessed_file(path)
|
74
|
-
raise ArgumentError, 'Argument must be a string' unless path.instance_of? String
|
75
|
-
raise ArgumentError, 'File path is not defined' unless path.empty?
|
76
|
-
raise RuntimeError, 'File doesn\'t exists' unless File.exists?(path)
|
77
80
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
+
def from_preprocessed_file(path, offset, limit, use_lexeme_table = true)
|
82
|
+
validate_file_name_argument(path)
|
83
|
+
|
84
|
+
idx = 0
|
85
|
+
open(path) do |fd|
|
86
|
+
while (line = fd.gets)
|
87
|
+
process_preprocessed_line(line, use_lexeme_table) if (idx >= offset && idx < offset + limit)
|
88
|
+
|
89
|
+
idx += 1
|
90
|
+
end
|
91
|
+
end
|
81
92
|
end
|
82
93
|
|
83
94
|
# new
|
84
95
|
def from_string(str)
|
85
|
-
|
86
|
-
raise ArgumentError, 'String is not defined' if str.empty?
|
96
|
+
validate_string_argument(str)
|
87
97
|
|
88
98
|
@str = str
|
89
99
|
|
90
100
|
str.split("\n").each do |line|
|
91
101
|
process_line(line)
|
92
102
|
end
|
103
|
+
|
104
|
+
@mapped_str.pop if @mapped_str[-1].value == "\n" && str[-1] != "\n"
|
93
105
|
end
|
94
|
-
|
95
|
-
def from_preprocessed_string(str)
|
96
|
-
|
97
|
-
raise ArgumentError, 'String is not defined' if str.empty?
|
106
|
+
|
107
|
+
def from_preprocessed_string(str, use_lexeme_table = true)
|
108
|
+
validate_string_argument(str)
|
98
109
|
|
99
110
|
str.split("\n").each do |line|
|
100
111
|
process_preprocessed_line(line)
|
101
112
|
end
|
102
113
|
end
|
103
114
|
|
104
|
-
def process_preprocessed_line(line)
|
115
|
+
def process_preprocessed_line(line, use_lexeme_table = true)
|
105
116
|
lexeme_positions = []
|
106
117
|
pos = 0
|
107
118
|
while (m = LEXEME_REGEXP.match(line, pos))
|
108
119
|
pos = m.begin(0)
|
109
|
-
|
110
|
-
lexeme = install_lexeme_m(m)
|
120
|
+
|
121
|
+
lexeme = install_lexeme_m(m, use_lexeme_table)
|
111
122
|
lexeme_positions << TraceVisualization::Data::LexemePos.new(lexeme, pos)
|
112
123
|
|
113
124
|
pos += lexeme.lexeme_length
|
114
125
|
end
|
115
|
-
|
126
|
+
|
127
|
+
|
116
128
|
pos, idx = 0, 0
|
117
129
|
while pos < line.length
|
118
130
|
lexeme = nil
|
@@ -120,13 +132,13 @@ module TraceVisualization
|
|
120
132
|
lexeme = lexeme_positions[idx].lexeme
|
121
133
|
idx += 1
|
122
134
|
else
|
123
|
-
lexeme = install_lexeme('CHAR', line[pos], line[pos].ord, 1)
|
135
|
+
lexeme = install_lexeme('CHAR', line[pos], line[pos].ord, 1, use_lexeme_table)
|
124
136
|
end
|
125
137
|
pos += lexeme.lexeme_length
|
126
138
|
@mapped_str << lexeme
|
127
139
|
end
|
128
|
-
|
129
|
-
@mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1)
|
140
|
+
|
141
|
+
@mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1, use_lexeme_table)
|
130
142
|
end
|
131
143
|
|
132
144
|
# new
|
@@ -164,28 +176,21 @@ module TraceVisualization
|
|
164
176
|
@mapped_str << install_lexeme('CHAR', "\n", "\n".ord, 1)
|
165
177
|
end
|
166
178
|
|
167
|
-
def install_lexeme(name, lexeme_string, int_value, lexeme_length)
|
168
|
-
lexeme = @lexeme_table[lexeme_string]
|
179
|
+
def install_lexeme(name, lexeme_string, int_value, lexeme_length, use_lexeme_table = true)
|
180
|
+
lexeme = use_lexeme_table ? @lexeme_table[lexeme_string] : nil
|
169
181
|
|
170
|
-
if lexeme
|
182
|
+
if lexeme.nil?
|
171
183
|
lexeme = TraceVisualization::Data::Lexeme.new(name, lexeme_string, int_value)
|
172
184
|
lexeme.lexeme_length = lexeme_length
|
173
|
-
|
185
|
+
|
186
|
+
@lexeme_table[lexeme_string] = lexeme if use_lexeme_table
|
174
187
|
end
|
175
188
|
|
176
189
|
lexeme
|
177
190
|
end
|
178
191
|
|
179
|
-
def install_lexeme_m(m)
|
180
|
-
|
181
|
-
|
182
|
-
if lexeme == nil
|
183
|
-
lexeme = TraceVisualization::Data::Lexeme.new(m[:name], m[:source], m[:value].to_i)
|
184
|
-
lexeme.lexeme_length = m.to_s.length
|
185
|
-
@lexeme_table[m[:source]] = lexeme
|
186
|
-
end
|
187
|
-
|
188
|
-
lexeme
|
192
|
+
def install_lexeme_m(m, use_lexeme_table = true)
|
193
|
+
install_lexeme(m[:name], m[:source], m[:value].to_i, m.to_s.length, use_lexeme_table)
|
189
194
|
end
|
190
195
|
|
191
196
|
def [](index)
|
@@ -201,7 +206,9 @@ module TraceVisualization
|
|
201
206
|
end
|
202
207
|
|
203
208
|
def <<(object)
|
204
|
-
|
209
|
+
lexeme = install_lexeme('UNKNOWN', object, object.to_i, object.to_s.length)
|
210
|
+
lexeme.ord = 0 # fake ord because Reorder already processed
|
211
|
+
@mapped_str << lexeme
|
205
212
|
end
|
206
213
|
|
207
214
|
def pop
|
@@ -279,5 +286,17 @@ module TraceVisualization
|
|
279
286
|
end
|
280
287
|
|
281
288
|
end
|
289
|
+
|
290
|
+
def validate_file_name_argument(path)
|
291
|
+
raise ArgumentError, 'Argument must be a string' if not path.instance_of? String
|
292
|
+
raise ArgumentError, 'File path is not defined' if path.empty?
|
293
|
+
raise RuntimeError, 'File doesn\'t exists' if not File.exists?(path)
|
294
|
+
end
|
295
|
+
|
296
|
+
def validate_string_argument(str)
|
297
|
+
raise ArgumentError, 'Argument must be a string' unless str.instance_of? String
|
298
|
+
raise ArgumentError, 'String is not defined' if str.empty?
|
299
|
+
end
|
300
|
+
|
282
301
|
end
|
283
302
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module TraceVisualization
|
2
|
+
module RepetitionsScore
|
3
|
+
|
4
|
+
# Priority length when repetition score is calculated
|
5
|
+
ALPHA_SCORE = 0.5
|
6
|
+
|
7
|
+
# Priority positions.size when repetition score is calculated
|
8
|
+
BETA_SCORE = 1 - ALPHA_SCORE
|
9
|
+
|
10
|
+
# Options:
|
11
|
+
# *sort* true / false
|
12
|
+
# *order* order for sort (default 'asc')
|
13
|
+
# *version* version of importance function
|
14
|
+
def self.fill_score(rs, options = {})
|
15
|
+
|
16
|
+
opts = {
|
17
|
+
:sort => false,
|
18
|
+
:order => 'asc'
|
19
|
+
}.merge options
|
20
|
+
|
21
|
+
case opts[:version]
|
22
|
+
when 'relative'
|
23
|
+
function_relative(rs)
|
24
|
+
when 'linear'
|
25
|
+
function_linear(rs)
|
26
|
+
else
|
27
|
+
throw Exception.new("Unknown version")
|
28
|
+
end
|
29
|
+
|
30
|
+
if opts[:sort]
|
31
|
+
rs.sort! do |a, b|
|
32
|
+
opts[:order] == 'desc' ? b.score <=> a.score : a.score <=> b.score
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# f(len, size) = alpha * len' + beta * size'
|
38
|
+
# len', size' - relative to max values
|
39
|
+
def self.function_relative(rs)
|
40
|
+
len_max, size_max = 0, 0
|
41
|
+
|
42
|
+
rs.each do |r|
|
43
|
+
len = r.length
|
44
|
+
len_max = len if len > len_max
|
45
|
+
|
46
|
+
size = r.positions_size
|
47
|
+
size_max = size if size > size_max
|
48
|
+
end
|
49
|
+
|
50
|
+
rs.each do |r|
|
51
|
+
r.score = ALPHA_SCORE * r.strict_length / len_max +
|
52
|
+
BETA_SCORE * r.positions_size / size_max
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# f(len, size, k) = alpha * len + beta * size + gamma * k
|
57
|
+
def self.function_linear(rs)
|
58
|
+
len_max, len_min, size_max, size_min, k_max = 0, 2**32, 0, 2**32, 0
|
59
|
+
|
60
|
+
rs.each do |r|
|
61
|
+
len = r.length
|
62
|
+
len_max = len if len > len_max
|
63
|
+
len_min = len if len < len_min
|
64
|
+
|
65
|
+
size = r.positions_size
|
66
|
+
size_max = size if size > size_max
|
67
|
+
size_min = size if size < size_min
|
68
|
+
|
69
|
+
k_max = r.k if r.k > k_max
|
70
|
+
end
|
71
|
+
|
72
|
+
d = (len_max * size_min + size_max * k_max - size_max * len_min - len_max * k_max).to_f
|
73
|
+
|
74
|
+
alpha = (size_min + k_max * (size_max - 1)) / d
|
75
|
+
beta = - (len_min + k_max * (len_max - 1)) / d
|
76
|
+
gamma = (len_max * size_min - size_max * len_min - size_min + len_min) / d
|
77
|
+
|
78
|
+
puts "len_max = #{len_max}, len_min = #{len_min}, size_max = #{size_max}, size_min = #{size_min}, k_max = #{k_max}"
|
79
|
+
puts "alpha = #{alpha}, beta = #{beta}, gamma = #{gamma}"
|
80
|
+
|
81
|
+
rs.each do |r|
|
82
|
+
r.score = alpha * r.length + beta * r.positions_size + gamma * r.k
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|