Skip to content

Instantly share code, notes, and snippets.

@the-michael-toy
Created October 31, 2016 23:08
Show Gist options
  • Save the-michael-toy/24f2c79c0476f7c185d09e39a9a7135e to your computer and use it in GitHub Desktop.
Save the-michael-toy/24f2c79c0476f7c185d09e39a9a7135e to your computer and use it in GitHub Desktop.
create a big fake ruby project for testing purposes ...
# ruby makebigfakerubyapp.rb /tmp/bfrp
# cd /tmp/bfrp
# time bin/require_everything
# warble
# time java -jar require_everything.jar
require 'securerandom'
require 'fileutils'
require 'set'
class BigFakeApp
CLASS_COUNT = 1500
MAX_LEAF_SIZE = 15
METHOD_COUNT = 20
LOAD_DEPTH = 2
class MockClass
def initialize
@name = "Class_#{SecureRandom.hex(16)}"
end
def to_s
methods = (1..METHOD_COUNT).to_a.map do |n|
m = <<~RUBY
def method#{n}(arg)
var = SecureRandom.hex(8)
RUBY
5.times do
case rand(4)
when 0
m << "rand(n).times { var << 'x'}\n"
when 1
m += <<~RUBY
if n == 0
:zero
elsif n > 0
:positive
else
:negative
end
RUBY
when 2
m << Array.new(5) { " method_#{rand(METHOD_COUNT)+1}(arg)" }.join(" || ")+"\n"
when 3
m += ' "var is now #{var} and arg is #{arg}"' + "\n"
end
end
m + "\n end"
end
<<~RUBY
module M1
module M2
class #{@name}
#{ methods.join("\n") }
end
end
end
RUBY
end
def file_name
@name.downcase + ".rb"
end
end
def initialize
buckets = []
classes_left = CLASS_COUNT
while classes_left > 0 do
n_classes = [classes_left, MAX_LEAF_SIZE].min
buckets << Array.new(n_classes) { MockClass.new() }
classes_left -= n_classes
end
while buckets.size > MAX_LEAF_SIZE do
new_buckets = []
new_buckets << buckets.shift(MAX_LEAF_SIZE) until buckets.size == 0
buckets = new_buckets
end
@app = buckets
@requires = []
@loads = Set.new
end
def materialize
walk_tree(@app, []) do |type, stuff, path|
if type == :leaf
rfile = File.join(*path, stuff.file_name)
File.write(rfile, stuff.to_s)
else
FileUtils.mkdir_p path.join('/') unless path.empty?
end
end
end
def require_list
walk_tree(@app, []) do |type, obj, path|
if type == :leaf
dir = path.drop(LOAD_DEPTH)
@requires << "require '#{File.join(*dir, obj.file_name)}'"
elsif type == :node
@loads.add(path.join('/')) if path.size == LOAD_DEPTH
end
end
end
def walk_tree(root, path, &blk)
if root.is_a? MockClass
yield :leaf, root, path
else
yield :node, root, path
root.each_index do |i|
child = root[i]
if child.is_a? MockClass
walk_tree(child, path, &blk)
else
walk_tree(child, [*path, "depth=#{path.size},index=#{i}"], &blk)
end
end
end
end
def write(dest)
FileUtils.mkdir_p dest + "/bin"
FileUtils.mkdir_p dest + "/config"
FileUtils.chdir dest
app_file = "bin/require_everything"
gems = {
"jruby-jars" => "jruby-jars", "jruby-openssl" => "openssl", "sequel" => "sequel",
"rack" => "rack", "rack-protection" => "rack-protection", "rack-rewrite" => "rack-rewrite",
"activesupport" => nil, "useragent" => "useragent", "uri_template" => "uri_template",
"thor" => "thor", "slim" => "slim", "mail" => "mail", "write_xlsx" => "write_xlsx",
"warden" => "warden", "bcrypt-ruby" => "bcrypt", "rqrcode" => "rqrcode", "rotp" => "rotp", "ruby-openid" => nil,
"tzinfo" => "tzinfo", "trollop" => "trollop", "net-ldap" => "net-ldap", "net-ssh" => "net/ssh", "ruby-saml" => "ruby-saml", "rubyzip" => "zip", "liquid" => "liquid", "parse-cron" => "parse-cron", "zip-zip" => nil,
"chronic_duration" => "chronic_duration", "kramdown" => "kramdown", "loofah" => "loofah", "rouge" => nil, "geokit" => "geokit", "prawn" => "prawn", "diffy" => "diffy", "snowplow-tracker" => "snowplow-tracker", "therubyrhino" => "rhino",
"safe_yaml" => "safe_yaml", "pmap" => "pmap", "uuidtools" => "uuidtools", "sentry-raven" => "sentry-raven", "newrelic_rpm" => "newrelic_rpm", "jruby-jms" => "jms", "jmx4r" => "jmx4r"
}
@requires = gems.values.compact.map {|g| "require '#{g}'"}
materialize
require_list
File.write app_file, <<~RUBY
#! /usr/bin/env ruby
require 'pathname'
require 'bundler/setup'
root = Pathname.new(__FILE__).dirname.parent.expand_path.to_s
loads = %w[
#{@loads.to_a.join("\n ")}
]
$LOAD_PATH.concat(loads.map{|fn| File.join(root, fn)})
#{@requires.join("\n")}
RUBY
File.chmod(0755, app_file)
File.write "config/warble.rb", <<~RUBY
Warbler::Config.new do |config|
config.features = %w(compiled)
config.dirs = FileList["d*"]
config.includes = [ 'bin/require_everything' ]
config.jar_name = "require_everything"
config.bytecode_version = "1.8"
config.override_gem_home = true
end
RUBY
File.write "Gemfile", <<~RUBY
source "https://rubygems.org"
platform :jruby do
#{gems.keys.map{|n| "gem '#{n}'"}.join("\n ")}
end
RUBY
end
end
if ARGV.size == 1
b = BigFakeApp.new
b.write ARGV[0]
puts "app built, don't forget to bundle install in #{ARGV[0]}"
else
puts "usage: makebigfakerubyapp <directory>"
exit 1
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment