Skip to content

Instantly share code, notes, and snippets.

@peteb
Last active May 24, 2020 11:12
Show Gist options
  • Save peteb/2dab3b5d46fcdaf43ffdcb6d3c55f159 to your computer and use it in GitHub Desktop.
Save peteb/2dab3b5d46fcdaf43ffdcb6d3c55f159 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'erb'
require 'open3'
# == Code generation ====================================================================================
def scenario_multi_call(callsite_count)
ERB.new(<<-HERE).result(binding)
#include "continuable/continuable.hpp"
__attribute__((noinline)) cti::continuable<int> sum(int a, int b) {
return cti::make_ready_continuable(a + b);
}
__attribute__((noinline)) void printSum(int) {}
int main() {
<% callsite_count.times %>
sum(5, 2)
.then([](int theSum) {
printSum(theSum);
});
<% end %>
}
HERE
end
def scenario_multi_then(then_count)
ERB.new(<<-HERE).result(binding)
#include "continuable/continuable.hpp"
__attribute__((noinline)) cti::continuable<int> sum(int a, int b) {
return cti::make_ready_continuable(a + b);
}
__attribute__((noinline)) void printSum(int) {}
int main() {
sum(5, 2)
<% then_count.times do %>
.then([](int theSum) {
printSum(theSum);
return theSum;
})
<% end %>
;
}
HERE
end
def scenario_combined(callsite_count)
then_count = 2 # Hardcoded, average number of .then/.fail per callsite
ERB.new(<<-HERE).result(binding)
#include "continuable/continuable.hpp"
__attribute__((noinline)) cti::continuable<int> sum(int a, int b) {
return cti::make_ready_continuable(a + b);
}
__attribute__((noinline)) void printSum(int) {}
int main() {
<% callsite_count.times do %>
sum(5, 2)
<% then_count.times do %>
.then([](int theSum) {
printSum(theSum);
return theSum;
})
<% end %>
;
<% end %>
}
HERE
end
# == Build ==============================================================================================
COMMAND_LINE = "g++ -O3 -o a.out -x c++ --std=c++17 -Ifunction2/include -Icontinuable/include -fno-exceptions -fno-rtti -fno-asynchronous-unwind-tables -fno-stack-protector -"
CompileResult = Struct.new(:bytecount, :bytecount_stripped, :compiletime)
def compile(sourcecode)
start = Time.now
_, error, _ = Open3.capture3(COMMAND_LINE, stdin_data: sourcecode)
finish = Time.now
raise error unless error.strip.empty?
unstripped_filesize = File.size('a.out')
system('strip a.out')
stripped_filesize = File.size('a.out')
CompileResult.new.tap do |result|
result.bytecount = unstripped_filesize
result.bytecount_stripped = stripped_filesize
result.compiletime = ((finish - start) * 1000).to_i
end
end
def best_compilation_result(results)
CompileResult.new.tap do |result|
result.bytecount = results.map(&:bytecount).min
result.bytecount_stripped = results.map(&:bytecount_stripped).min
result.compiletime = results.map(&:compiletime).min
end
end
# == Collection and reporting ===========================================================================
def execute_scenario(lower_bound, upper_bound, diff = 1)
puts 'n,compilation time,bytecount,bytecount stripped'
observations = lower_bound.step(upper_bound, diff).each do |n|
results = best_compilation_result(3.times.map { compile(yield(n)) })
puts [n, results.compiletime, results.bytecount, results.bytecount_stripped].join(',')
end
end
# == Execution ==========================================================================================
scenarios = {
'multi_call' => method(:scenario_multi_call),
'multi_then' => method(:scenario_multi_then),
'combined' => method(:scenario_combined)
}
scenario = scenarios[ARGV[0]] or raise 'Enter a valid scenario as first argument'
execute_scenario(0, 15, 1) { |n| scenario.call(n) }
# == Results multi_call =================================================================================
# gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)
#
# n,compilation time,bytecount,bytecount stripped
# 0,1448,34688,26840
# 1,1658,52784,35032
# 2,1747,60000,35032
# 3,1855,71032,39128
# 4,1943,82072,43224
# 5,1997,89008,43224
# 6,2146,100048,47320
# 7,2248,106984,47320
# 8,2334,118024,51416
# 9,2438,129056,55512
# 10,2543,136000,55512
# 11,2667,147032,59608
# 12,2798,153992,59608
# 13,2875,165048,63704
# 14,2997,176104,67800
# 15,3105,183056,67800
# == Results multi_then =================================================================================
# gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)
#
# n,compilation time,bytecount,bytecount stripped
# 0,1517,38136,26840
# 1,1705,52768,35032
# 2,1742,62648,39128
# 3,1905,82200,51416
# 4,2015,95080,59608
# 5,2172,108352,67800
# 6,2281,122016,75992
# 7,2468,136080,84184
# 8,2590,154624,96472
# 9,2719,173568,108760
# 10,2950,192904,121048
# 11,3116,212624,133336
# 12,3368,236848,149720
# 13,3574,257376,162008
# 14,3806,286504,182488
# 15,4023,307832,194776
# == Results combined ===================================================================================
# gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)
#
# n,compilation time,bytecount,bytecount stripped
# 0,1480,34688,26840
# 25,7614,568920,174296
# 50,14080,1093520,309464
# 75,20959,1619408,448728
# 100,28183,2142224,583896
# 125,35155,2665032,719064
# 150,43249,3192016,858328
# 175,50720,3714824,993496
# 200,58372,4237560,1128664
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment