|
1
|
# Benchmark for the cost of resolving inline attachments while formatting a text.
|
|
2
|
#
|
|
3
|
# bin/rails r bench_inline_attachments_scrubber.rb
|
|
4
|
#
|
|
5
|
# Formats a text of about 100 nodes whose container has 100 attachments.
|
|
6
|
# It goes through textilizable, so it measures the same thing on 6.x, where
|
|
7
|
# inline attachments are resolved by ApplicationHelper#parse_inline_attachments,
|
|
8
|
# and on 7.x, where they are resolved by InlineAttachmentsScrubber.
|
|
9
|
#
|
|
10
|
# Nothing is written: the attachments are unsaved in-memory records and the
|
|
11
|
# text formatting setting is overridden in this process only.
|
|
12
|
|
|
13
|
CHUNKS = 4 # about 100 nodes
|
|
14
|
FILES = 100
|
|
15
|
REPS = 20
|
|
16
|
|
|
17
|
def Setting.text_formatting = 'common_mark'
|
|
18
|
|
|
19
|
CHUNK = <<~MD
|
|
20
|
## Section %<i>d
|
|
21
|
|
|
22
|
Some paragraph with *emphasis*, `code` and a [link](https://example.com).
|
|
23
|
|
|
24
|
* first item
|
|
25
|
* second item
|
|
26
|
|
|
27
|

|
|
28
|
MD
|
|
29
|
|
|
30
|
TEXT = (1..CHUNKS).map {|i| format(CHUNK, :i => i)}.join("\n")
|
|
31
|
|
|
32
|
# Elements and text nodes alike: the formatter walks both.
|
|
33
|
def node_count(html)
|
|
34
|
count = 0
|
|
35
|
Loofah.fragment(html).scrub!(Loofah::Scrubber.new {|_node| count += 1})
|
|
36
|
count
|
|
37
|
end
|
|
38
|
|
|
39
|
attachments =
|
|
40
|
Array.new(FILES) do |i|
|
|
41
|
Attachment.new(:filename => "img#{i}.png", :created_on => Time.now - i).tap {|a| a.id = i + 1}
|
|
42
|
end
|
|
43
|
|
|
44
|
controller = ApplicationController.new
|
|
45
|
controller.request = ActionDispatch::TestRequest.create
|
|
46
|
view = controller.view_context
|
|
47
|
|
|
48
|
render = -> {view.textilizable(TEXT, :attachments => attachments, :only_path => true)}
|
|
49
|
|
|
50
|
html = render.call # warm up
|
|
51
|
|
|
52
|
GC.start
|
|
53
|
objects = GC.stat(:total_allocated_objects)
|
|
54
|
started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
55
|
REPS.times {render.call}
|
|
56
|
elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - started
|
|
57
|
objects = GC.stat(:total_allocated_objects) - objects
|
|
58
|
|
|
59
|
abort 'the inline attachment was not resolved' unless html.include?('/attachments/download/1/img0.png')
|
|
60
|
|
|
61
|
puts "Redmine #{Redmine::VERSION}, Ruby #{RUBY_VERSION}, #{Setting.text_formatting}"
|
|
62
|
puts "#{node_count(html)} nodes, #{FILES} attachments, #{REPS} renderings"
|
|
63
|
puts format('%.1f ms and %d objects allocated per rendering', elapsed / REPS * 1000, objects / REPS)
|