keight 0.0.1
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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +263 -0
- data/Rakefile +92 -0
- data/bench/bench.rb +278 -0
- data/bench/benchmarker.rb +502 -0
- data/bin/k8rb +496 -0
- data/keight.gemspec +36 -0
- data/lib/keight/skeleton/.gitignore +10 -0
- data/lib/keight/skeleton/app/action.rb +98 -0
- data/lib/keight/skeleton/app/api/hello.rb +39 -0
- data/lib/keight/skeleton/app/form/.keep +0 -0
- data/lib/keight/skeleton/app/helper/.keep +0 -0
- data/lib/keight/skeleton/app/model/.keep +0 -0
- data/lib/keight/skeleton/app/model.rb +144 -0
- data/lib/keight/skeleton/app/page/welcome.rb +17 -0
- data/lib/keight/skeleton/app/template/_layout.html.eruby +56 -0
- data/lib/keight/skeleton/app/template/welcome.html.eruby +6 -0
- data/lib/keight/skeleton/app/usecase/.keep +0 -0
- data/lib/keight/skeleton/config/app.rb +29 -0
- data/lib/keight/skeleton/config/app_dev.private +11 -0
- data/lib/keight/skeleton/config/app_dev.rb +8 -0
- data/lib/keight/skeleton/config/app_prod.rb +7 -0
- data/lib/keight/skeleton/config/app_stg.rb +5 -0
- data/lib/keight/skeleton/config/app_test.private +11 -0
- data/lib/keight/skeleton/config/app_test.rb +8 -0
- data/lib/keight/skeleton/config/server_puma.rb +22 -0
- data/lib/keight/skeleton/config/server_unicorn.rb +21 -0
- data/lib/keight/skeleton/config/urlpath_mapping.rb +16 -0
- data/lib/keight/skeleton/config.rb +44 -0
- data/lib/keight/skeleton/config.ru +21 -0
- data/lib/keight/skeleton/index.txt +38 -0
- data/lib/keight/skeleton/static/lib/jquery/1.11.3/jquery.min.js +6 -0
- data/lib/keight/skeleton/static/lib/jquery/1.11.3/jquery.min.js.gz +0 -0
- data/lib/keight/skeleton/static/lib/modernizr/2.8.3/modernizr.min.js +4 -0
- data/lib/keight/skeleton/static/lib/modernizr/2.8.3/modernizr.min.js.gz +0 -0
- data/lib/keight/skeleton/tmp/upload/.keep +0 -0
- data/lib/keight.rb +2017 -0
- data/test/data/example1.jpg +0 -0
- data/test/data/example1.png +0 -0
- data/test/data/multipart.form +0 -0
- data/test/data/wabisabi.js +77 -0
- data/test/data/wabisabi.js.gz +0 -0
- data/test/keight_test.rb +3161 -0
- data/test/oktest.rb +1537 -0
- metadata +114 -0
@@ -0,0 +1,502 @@
|
|
1
|
+
###
|
2
|
+
### $Release: 0.0.1 $
|
3
|
+
### $Copyright: copyright(c) 2014-2015 kuwata-lab.com all rights reserved $
|
4
|
+
### $License: MIT License $
|
5
|
+
###
|
6
|
+
|
7
|
+
|
8
|
+
module Benchmarker
|
9
|
+
|
10
|
+
VERSION = "$Release: 0.0.1 $".split(/ /)[1]
|
11
|
+
|
12
|
+
def self.new(opts={}, &block)
|
13
|
+
#: creates runner object and returns it.
|
14
|
+
runner = RUNNER.new(opts)
|
15
|
+
if block
|
16
|
+
runner._before_all()
|
17
|
+
runner._run(&block)
|
18
|
+
runner._after_all()
|
19
|
+
end
|
20
|
+
runner
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.bm(width=30, &block) # for compatibility with benchmark.rb
|
24
|
+
return self.new(:width=>30, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.platform()
|
28
|
+
#: returns platform information.
|
29
|
+
return <<END
|
30
|
+
benchmarker.rb: release #{VERSION}
|
31
|
+
RUBY_VERSION: #{RUBY_VERSION}
|
32
|
+
RUBY_PATCHLEVEL: #{RUBY_PATCHLEVEL}
|
33
|
+
RUBY_PLATFORM: #{RUBY_PLATFORM}
|
34
|
+
END
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
class Runner
|
39
|
+
|
40
|
+
def initialize(opts={})
|
41
|
+
#: takes :loop, :cycle, and :extra options.
|
42
|
+
@loop = opts[:loop]
|
43
|
+
@cycle = opts[:cycle]
|
44
|
+
@extra = opts[:extra]
|
45
|
+
#:
|
46
|
+
@tasks = []
|
47
|
+
@report = REPORTER.new(opts)
|
48
|
+
@stats = STATS.new(@report, opts)
|
49
|
+
@_section_title = ""
|
50
|
+
@_section_started = false
|
51
|
+
end
|
52
|
+
|
53
|
+
attr_accessor :tasks, :report, :stats
|
54
|
+
|
55
|
+
def task(label, opts={}, &block)
|
56
|
+
#: prints section title if not printed yet.
|
57
|
+
#: creates task objet and returns it.
|
58
|
+
#: runs task when :skip option is not specified.
|
59
|
+
#: skip block and prints message when :skip option is specified.
|
60
|
+
#: subtracts times of empty task if exists.
|
61
|
+
skip_message = opts[:skip]
|
62
|
+
t = _new_task(label, skip_message, &block)
|
63
|
+
#: saves created task object unless :skip optin is not specified.
|
64
|
+
@tasks << t unless skip_message
|
65
|
+
t
|
66
|
+
end
|
67
|
+
|
68
|
+
alias report task # for compatibility with benchmark.rb
|
69
|
+
|
70
|
+
def empty_task(label="(Empty)", &block)
|
71
|
+
#:: clear @_empty_task.
|
72
|
+
@_empty_task = nil
|
73
|
+
#: prints section title if not printed yet.
|
74
|
+
#: creates empty task object and returns it.
|
75
|
+
t = _new_task(label, &block)
|
76
|
+
#: saves empty task object.
|
77
|
+
#:: don't add empty task to @tasks.
|
78
|
+
@_empty_task = t
|
79
|
+
t
|
80
|
+
end
|
81
|
+
|
82
|
+
#--
|
83
|
+
#def skip_task(label, message=" ** skipped **")
|
84
|
+
# #: prints section title if not printed yet.
|
85
|
+
# t = _new_task(label)
|
86
|
+
# #: prints task label and message instead of times.
|
87
|
+
# @report.write(message + "\n")
|
88
|
+
# #: don't change @tasks.
|
89
|
+
#end
|
90
|
+
#++
|
91
|
+
|
92
|
+
def _before_all # :nodoc:
|
93
|
+
#: prints Benchmarker.platform().
|
94
|
+
print Benchmarker.platform()
|
95
|
+
end
|
96
|
+
|
97
|
+
def _after_all # :nodoc:
|
98
|
+
#: prints statistics out benchmarks.
|
99
|
+
@stats.all(@tasks)
|
100
|
+
end
|
101
|
+
|
102
|
+
def _run # :nodoc:
|
103
|
+
#: when @cycle > 1...
|
104
|
+
if @cycle && @cycle > 1
|
105
|
+
@all_tasks = []
|
106
|
+
#: prints output of cycle into stderr.
|
107
|
+
@report._switch_out_to_err do
|
108
|
+
#: yields block @cycle times when @extra is not specified.
|
109
|
+
#: yields block @cycle + 2*@extra times when @extra is specified.
|
110
|
+
i = 0
|
111
|
+
cycle = @cycle
|
112
|
+
cycle += 2 * @extra if @extra
|
113
|
+
cycle.times do
|
114
|
+
_reset_section("(##{i+=1})")
|
115
|
+
@all_tasks << (@tasks = [])
|
116
|
+
#: yields block with self as block paramter.
|
117
|
+
yield self
|
118
|
+
end
|
119
|
+
end
|
120
|
+
#: reports average of results.
|
121
|
+
@tasks = _calc_averages(@all_tasks, @extra)
|
122
|
+
_report_average_section(@tasks)
|
123
|
+
#: when @cycle == 0 or not specified...
|
124
|
+
else
|
125
|
+
#: yields block only once.
|
126
|
+
_reset_section("")
|
127
|
+
#: yields block with self as block paramter.
|
128
|
+
yield self
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def _reset_section(section_title)
|
135
|
+
@_section_started = false
|
136
|
+
@_section_title = section_title
|
137
|
+
end
|
138
|
+
|
139
|
+
def _new_task(label, skip_message=nil, &block)
|
140
|
+
#: prints section title if not printed yet.
|
141
|
+
_report_section_title_if_not_printed_yet()
|
142
|
+
#: creates task objet and returns it.
|
143
|
+
t = TASK.new(label, @loop)
|
144
|
+
@report.task_label(label)
|
145
|
+
#: skip block and prints message when :skip option is specified.
|
146
|
+
if skip_message
|
147
|
+
@report.write(skip_message + "\n")
|
148
|
+
#: runs task when :skip option is not specified.
|
149
|
+
elsif block
|
150
|
+
t.run(&block)
|
151
|
+
#: subtracts times of empty task if exists.
|
152
|
+
t.sub(@_empty_task) if @_empty_task
|
153
|
+
@report.task_times(t.user, t.sys, t.total, t.real)
|
154
|
+
end
|
155
|
+
t
|
156
|
+
end
|
157
|
+
|
158
|
+
def _report_section_title_if_not_printed_yet
|
159
|
+
if ! @_section_started
|
160
|
+
@_section_started = true
|
161
|
+
@report.section_title(@_section_title)\
|
162
|
+
.section_headers("user", "sys", "total", "real")
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def _calc_averages(all_tasks, extra)
|
167
|
+
#: calculates average times of tasks.
|
168
|
+
tasks_list = _transform_all_tasks(all_tasks)
|
169
|
+
if extra
|
170
|
+
@report.section_title("Remove Min & Max").section_headers("min", "cycle", "max", "cycle")
|
171
|
+
tasks_list = tasks_list.collect {|tasks| _remove_min_max(tasks, extra) }
|
172
|
+
end
|
173
|
+
avg_tasks = tasks_list.collect {|tasks| Task.average(tasks) }
|
174
|
+
avg_tasks
|
175
|
+
end
|
176
|
+
|
177
|
+
def _transform_all_tasks(all_tasks)
|
178
|
+
tasks_list = []
|
179
|
+
all_tasks.each do |tasks|
|
180
|
+
tasks.each_with_index do |task, i|
|
181
|
+
(tasks_list[i] ||= []) << task
|
182
|
+
end
|
183
|
+
end
|
184
|
+
tasks_list
|
185
|
+
end
|
186
|
+
|
187
|
+
def _remove_min_max(tasks, extra)
|
188
|
+
#: reports min and max tasks.
|
189
|
+
idx = -1
|
190
|
+
pairs = tasks.collect {|task| [task, idx+=1] }
|
191
|
+
pairs = pairs.sort_by {|task, idx| task.real } # 1.8 doesn't support sort_by!
|
192
|
+
j = -1
|
193
|
+
while (j += 1) < extra
|
194
|
+
@report.task_label(j == 0 ? pairs[j].first.label : '')
|
195
|
+
task, idx = pairs[j] # min
|
196
|
+
@report.task_time(task.real).task_index(idx+1)
|
197
|
+
task, idx = pairs[-j-1] # max
|
198
|
+
@report.task_time(task.real).task_index(idx+1)
|
199
|
+
@report.text("\n")
|
200
|
+
end
|
201
|
+
#: removes min and max tasks, and returns remained tasks.
|
202
|
+
remained_tasks = pairs[extra...-extra].collect {|task, idx| task }
|
203
|
+
remained_tasks
|
204
|
+
end
|
205
|
+
|
206
|
+
def _report_average_section(tasks)
|
207
|
+
title = _get_average_section_title()
|
208
|
+
@report.section_title(title).section_headers("user", "sys", "total", "real")
|
209
|
+
tasks.each do |t|
|
210
|
+
@report.task_label(t.label).task_times(t.user, t.sys, t.total, t.real)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def _get_average_section_title()
|
215
|
+
#: returns 'Average of N (=x-2*y)' string if label width is enough wide.
|
216
|
+
#: returns 'Average of N' string if label width is not enough wide.
|
217
|
+
title = "Average of #{@cycle}"
|
218
|
+
if @extra
|
219
|
+
s = " (=#{@cycle+2*@extra}-2*#{@extra})"
|
220
|
+
title << s if "## #{title}#{s}".length <= @report.label_width
|
221
|
+
end
|
222
|
+
title
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
RUNNER = Runner
|
228
|
+
|
229
|
+
|
230
|
+
class Task
|
231
|
+
|
232
|
+
def initialize(label, loop=1, &block)
|
233
|
+
#: takes label and loop.
|
234
|
+
@label = label
|
235
|
+
@loop = loop
|
236
|
+
#: sets all times to zero.
|
237
|
+
@user = @sys = @total = @real = 0.0
|
238
|
+
end
|
239
|
+
|
240
|
+
attr_accessor :label, :loop, :user, :sys, :total, :real
|
241
|
+
|
242
|
+
def run
|
243
|
+
#: yields block for @loop times.
|
244
|
+
ntimes = @loop || 1
|
245
|
+
pt1 = Process.times
|
246
|
+
t1 = Time.now
|
247
|
+
if ntimes > 1
|
248
|
+
ntimes.times { yield }
|
249
|
+
else
|
250
|
+
yield
|
251
|
+
end
|
252
|
+
pt2 = Process.times
|
253
|
+
t2 = Time.now
|
254
|
+
#: measures times.
|
255
|
+
@user = pt2.utime - pt1.utime
|
256
|
+
@sys = pt2.stime - pt1.stime
|
257
|
+
@total = @user + @sys
|
258
|
+
@real = t2 - t1
|
259
|
+
return self
|
260
|
+
end
|
261
|
+
|
262
|
+
def add(other)
|
263
|
+
#: adds other's times into self.
|
264
|
+
@user += other.user
|
265
|
+
@sys += other.sys
|
266
|
+
@total += other.total
|
267
|
+
@real += other.real
|
268
|
+
#: returns self.
|
269
|
+
return self
|
270
|
+
end
|
271
|
+
|
272
|
+
def sub(other)
|
273
|
+
#: substracts other's times from self.
|
274
|
+
@user -= other.user
|
275
|
+
@sys -= other.sys
|
276
|
+
@total -= other.total
|
277
|
+
@real -= other.real
|
278
|
+
#: returns self.
|
279
|
+
return self
|
280
|
+
end
|
281
|
+
|
282
|
+
def mul(n)
|
283
|
+
#: multiplies times with n.
|
284
|
+
@user *= n
|
285
|
+
@sys *= n
|
286
|
+
@total *= n
|
287
|
+
@real *= n
|
288
|
+
#: returns self.
|
289
|
+
return self
|
290
|
+
end
|
291
|
+
|
292
|
+
def div(n)
|
293
|
+
#: divides times by n.
|
294
|
+
@user /= n
|
295
|
+
@sys /= n
|
296
|
+
@total /= n
|
297
|
+
@real /= n
|
298
|
+
#: returns self.
|
299
|
+
return self
|
300
|
+
end
|
301
|
+
|
302
|
+
def self.average(tasks)
|
303
|
+
#: returns empty task when argument is empty.
|
304
|
+
n = tasks.length
|
305
|
+
return self.new(nil) if n == 0
|
306
|
+
#: create new task with label.
|
307
|
+
task = self.new(tasks.first.label)
|
308
|
+
#: returns averaged task.
|
309
|
+
tasks.each {|t| task.add(t) }
|
310
|
+
task.div(n)
|
311
|
+
return task
|
312
|
+
end
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
TASK = Task
|
317
|
+
|
318
|
+
|
319
|
+
class Reporter
|
320
|
+
|
321
|
+
def initialize(opts={})
|
322
|
+
#: takes :out, :err, :width, and :format options.
|
323
|
+
@out = opts[:out] || $stdout
|
324
|
+
@err = opts[:err] || $stderr
|
325
|
+
self.label_width = opts[:width] || 30
|
326
|
+
self.format_time = opts[:format] || "%9.4f"
|
327
|
+
end
|
328
|
+
|
329
|
+
attr_accessor :out, :err
|
330
|
+
attr_reader :label_width, :format_time
|
331
|
+
|
332
|
+
def _switch_out_to_err() # :nodoc:
|
333
|
+
#: switches @out to @err temporarily.
|
334
|
+
begin
|
335
|
+
out = @out
|
336
|
+
@out = @err
|
337
|
+
yield
|
338
|
+
ensure
|
339
|
+
@out = out
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def label_width=(width)
|
344
|
+
#: sets @label_width.
|
345
|
+
@label_width = width
|
346
|
+
#: sets @format_label, too.
|
347
|
+
@format_label = "%-#{width}s"
|
348
|
+
end
|
349
|
+
|
350
|
+
def format_time=(format)
|
351
|
+
#: sets @format_time.
|
352
|
+
@format_time = format
|
353
|
+
#: sets @format_header, too.
|
354
|
+
m = /%-?(\d+)\.\d+/.match(format)
|
355
|
+
@format_header = "%#{$1.to_i}s" if m
|
356
|
+
end
|
357
|
+
|
358
|
+
def write(*args)
|
359
|
+
#: writes arguments to @out with '<<' operator.
|
360
|
+
args.each {|x| @out << x.to_s }
|
361
|
+
#: saves the last argument.
|
362
|
+
@_prev = args[-1]
|
363
|
+
#: returns self.
|
364
|
+
return self
|
365
|
+
end
|
366
|
+
alias text write
|
367
|
+
|
368
|
+
def report_section_title(title)
|
369
|
+
#: prints newline at first.
|
370
|
+
write "\n"
|
371
|
+
#: prints section title with @format_label.
|
372
|
+
write @format_label % "## #{title}"
|
373
|
+
#: returns self.
|
374
|
+
return self
|
375
|
+
end
|
376
|
+
alias section_title report_section_title
|
377
|
+
|
378
|
+
def report_section_headers(*headers)
|
379
|
+
#: prints headers.
|
380
|
+
headers.each do |header|
|
381
|
+
report_section_header(header)
|
382
|
+
end
|
383
|
+
#: prints newline at end.
|
384
|
+
write "\n"
|
385
|
+
#: returns self.
|
386
|
+
return self
|
387
|
+
end
|
388
|
+
alias section_headers report_section_headers
|
389
|
+
|
390
|
+
def report_section_header(header)
|
391
|
+
#: prints header with @format_header.
|
392
|
+
write " ", @format_header % header
|
393
|
+
#: returns self.
|
394
|
+
return self
|
395
|
+
end
|
396
|
+
alias section_header report_section_header
|
397
|
+
|
398
|
+
def report_task_label(label)
|
399
|
+
#: prints task label with @format_label.
|
400
|
+
write @format_label % label
|
401
|
+
#: returns self.
|
402
|
+
return self
|
403
|
+
end
|
404
|
+
alias task_label report_task_label
|
405
|
+
|
406
|
+
def report_task_times(user, sys, total, real)
|
407
|
+
#: prints task times with @format_time.
|
408
|
+
fmt = @format_time
|
409
|
+
write " ", fmt % user, " ", fmt % sys, " ", fmt % total, " ", fmt % real, "\n"
|
410
|
+
#: returns self.
|
411
|
+
return self
|
412
|
+
end
|
413
|
+
alias task_times report_task_times
|
414
|
+
|
415
|
+
def report_task_time(time)
|
416
|
+
#: prints task time with @format_titme.
|
417
|
+
write " ", @format_time % time
|
418
|
+
#: returns self.
|
419
|
+
return self
|
420
|
+
end
|
421
|
+
alias task_time report_task_time
|
422
|
+
|
423
|
+
def report_task_index(index)
|
424
|
+
#: prints task time with @format_titme.
|
425
|
+
write " ", @format_header % "(##{index})"
|
426
|
+
#: returns self.
|
427
|
+
return self
|
428
|
+
end
|
429
|
+
alias task_index report_task_index
|
430
|
+
|
431
|
+
end
|
432
|
+
|
433
|
+
REPORTER = Reporter
|
434
|
+
|
435
|
+
|
436
|
+
class Stats
|
437
|
+
|
438
|
+
def initialize(reporter, opts={})
|
439
|
+
#: takes reporter object.
|
440
|
+
@report = reporter
|
441
|
+
@key = opts[:key] || 'real'
|
442
|
+
@sort_key = opts[:sort_key] || 'real'
|
443
|
+
@loop = opts[:loop]
|
444
|
+
@numerator = opts[:numerator]
|
445
|
+
end
|
446
|
+
|
447
|
+
def all(tasks)
|
448
|
+
ranking(tasks)
|
449
|
+
ratio_matrix(tasks)
|
450
|
+
end
|
451
|
+
|
452
|
+
def ranking(tasks)
|
453
|
+
tasks = tasks.sort_by {|t| t.__send__(@sort_key) } if @sort_key
|
454
|
+
#: prints ranking.
|
455
|
+
key = @key
|
456
|
+
@report.section_title("Ranking").section_headers(key.to_s)
|
457
|
+
#base = tasks.min_by {|t| t.__send__(key) }.__send__(key) # min_by() is available since 1.8.7
|
458
|
+
base = tasks.collect {|t| t.__send__(key) }.min
|
459
|
+
tasks.each do |task|
|
460
|
+
sec = task.__send__(key).to_f
|
461
|
+
val = 100.0 * base / sec
|
462
|
+
@report.task_label(task.label).task_time(sec).text(" (%5.1f%%) " % val)
|
463
|
+
#: prints barchart if @numerator is not specified.
|
464
|
+
if ! @numerator
|
465
|
+
bar = '*' * (val / 5.0).round
|
466
|
+
@report.text(bar).text("\n")
|
467
|
+
#: prints inverse number if @numerator specified.
|
468
|
+
else
|
469
|
+
@report.text("%12.2f per sec" % (@numerator/ sec)).text("\n")
|
470
|
+
end
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
def ratio_matrix(tasks)
|
475
|
+
tasks = tasks.sort_by {|t| t.__send__(@sort_key) } if @sort_key
|
476
|
+
#: prints matrix.
|
477
|
+
key = @key
|
478
|
+
@report.section_title("Matrix").section_header("real")
|
479
|
+
tasks.each_with_index do |t, i|
|
480
|
+
@report.text(" %8s" % ("[%02d]" % (i+1)))
|
481
|
+
end
|
482
|
+
@report.text("\n")
|
483
|
+
i = 0
|
484
|
+
tasks.each do |base_task|
|
485
|
+
i += 1
|
486
|
+
base = base_task.__send__(key).to_f
|
487
|
+
@report.task_label("[%02d] %s" % [i, base_task.label]).task_time(base)
|
488
|
+
tasks.each do |t|
|
489
|
+
sec = t.__send__(key).to_f
|
490
|
+
val = 100.0 * sec / base
|
491
|
+
@report.text(" %7.1f%%" % val)
|
492
|
+
end
|
493
|
+
@report.text("\n")
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
end
|
498
|
+
|
499
|
+
STATS = Stats
|
500
|
+
|
501
|
+
|
502
|
+
end
|