]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/benchmark/measure.in.rb
3 # Copyright Louis Dionne 2013-2017
4 # Distributed under the Boost Software License, Version 1.0.
5 # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 # When called as a program, this script runs the command line given in
9 # arguments and returns the total time. This is similar to the `time`
12 # This file can also be required as a Ruby module to gain access to the
13 # methods defined below.
16 # This file must not be used as-is. It must be processed by CMake first.
21 require 'ruby-progressbar'
26 before
= list
[0...n
] || []
27 after
= list
[n
..-1] || []
28 return [before
, after
]
31 # types : A sequence of strings to put in the mpl::vector.
32 # Using this method requires including
33 # - <boost/mpl/vector.hpp>
34 # - <boost/mpl/push_back.hpp>
36 fast
, rest
= split_at(20, types
)
37 rest
.inject("boost::mpl::vector#{fast.length}<#{fast.join(', ')}>") { |v
, t
|
38 "boost::mpl::push_back<#{v}, #{t}>::type"
42 # types : A sequence of strings to put in the mpl::list.
43 # Using this method requires including
44 # - <boost/mpl/list.hpp>
45 # - <boost/mpl/push_front.hpp>
47 prefix
, fast
= split_at([types
.length
- 20, 0].max
, types
)
48 prefix
.reverse
.inject("boost::mpl::list#{fast.length}<#{fast.join(', ')}>") { |l
, t
|
49 "boost::mpl::push_front<#{l}, #{t}>::type"
53 # values : A sequence of strings representing values to put in the fusion::vector.
54 # Using this method requires including
55 # - <boost/fusion/include/make_vector.hpp>
56 # - <boost/fusion/include/push_back.hpp>
57 def fusion_vector(values
)
58 fast
, rest
= split_at(10, values
)
59 rest
.inject("boost::fusion::make_vector(#{fast.join(', ')})") { |xs
, v
|
60 "boost::fusion::push_back(#{xs}, #{v})"
64 # values : A sequence of strings representing values to put in the fusion::list.
65 # Using this method requires including
66 # - <boost/fusion/include/make_list.hpp>
67 # - <boost/fusion/include/push_back.hpp>
68 def fusion_list(values
)
69 fast
, rest
= split_at(10, values
)
70 rest
.inject("boost::fusion::make_list(#{fast.join(', ')})") { |xs
, v
|
71 "boost::fusion::push_back(#{xs}, #{v})"
75 # Turns a CMake-style boolean into a Ruby boolean.
77 return true if b
.is_a
? String
and ["true", "yes", "1"].include?(b
.downcase
)
78 return true if b
.is_a
? Integer
and b
> 0
79 return false # otherwise
82 # aspect must be one of :compilation_time, :bloat, :execution_time
83 def measure(aspect
, template_relative
, range
, env = {})
84 measure_file
= Pathname
.new("#{MEASURE_FILE}")
85 template
= Pathname
.new(template_relative
).expand_path
88 if ENV["BOOST_HANA_JUST_CHECK_BENCHMARKS"] && range
.length
>= 2
89 range
= [range
[0], range
[-1]]
93 command
= "@CMAKE_COMMAND@ --build @CMAKE_BINARY_DIR@ --target #{target}"
94 stdout, stderr, status
= Open3
.capture3(command
)
97 progress
= ProgressBar
.create(format
: '%p%% %t | %B |',
98 title
: template_relative
,
102 # Evaluate the ERB template with the given environment, and save
103 # the result in the `measure.cpp` file.
104 code
= Tilt
::ERBTemplate.new(template
).render(nil, input_size
: n
, env: env)
105 measure_file
.write(code
)
107 # Compile the file and get timing statistics. The timing statistics
108 # are output to stdout when we compile the file because of the way
109 # the `compile.benchmark.measure` CMake target is setup.
110 stdout, stderr, status
= make
["#{MEASURE_TARGET}"]
111 raise "compilation error: #{stdout}\n\n#{stderr}\n\n#{code}" if not status
.success
?
112 ctime
= stdout.match(/\[compilation time: (.+)\]/i
)
113 # Size of the generated executable in KB
114 size
= File
.size("@CMAKE_CURRENT_BINARY_DIR@/#{MEASURE_TARGET}").to_f
/ 1000
116 # If we didn't match anything, that's because we went too fast, CMake
117 # did not have the time to see the changes to the measure file and
118 # the target was not rebuilt. So we sleep for a bit and then retry
120 (sleep
0.2; redo) if ctime
.nil?
121 stat
= ctime
.captures
[0].to_f
if aspect
== :compilation_time
122 stat
= size
if aspect
== :bloat
124 # Run the resulting program and get timing statistics. The statistics
125 # should be written to stdout by the `measure` function of the
126 # `measure.hpp` header.
127 if aspect
== :execution_time
128 stdout, stderr, status
= make
["#{MEASURE_TARGET}.run"]
129 raise "runtime error: #{stderr}\n\n#{code}" if not status
.success
?
130 match
= stdout.match(/\[execution time: (.+)\]/i
)
132 raise ("Could not find [execution time: ...] bit in the output. " +
133 "Did you use the `measure` function in the `measure.hpp` header? " +
134 "stdout follows:\n#{stdout}")
136 stat
= match
.captures
[0].to_f
143 measure_file
.write("")
144 progress
.finish
if progress
147 def time_execution(erb_file
, range
, env = {})
148 measure(:execution_time, erb_file
, range
, env)
151 def time_compilation(erb_file
, range
, env = {})
152 measure(:compilation_time, erb_file
, range
, env)
156 command
= ARGV.join(' ')
157 time
= Benchmark
.realtime
{ `#{command}` }
159 puts
"[command line: #{command}]"
160 puts
"[compilation time: #{time}]"