Skip to content

Instantly share code, notes, and snippets.

@epitron
Created September 10, 2012 06:35
Show Gist options
  • Save epitron/154be8f4aae4b1769362 to your computer and use it in GitHub Desktop.
Save epitron/154be8f4aae4b1769362 to your computer and use it in GitHub Desktop.
Faster 'require' method
echo -n "with: "
time ruby -I. -rfast-require -e 'require "epitools"'
echo -n "without: "
time ruby -e 'require "epitools"'
load "fast-require.rb"
# require 'pry-rescue'
# Pry.rescue { load "/home/epi/.gem/bin/rails" }
load "/home/epi/.gem/bin/rails"
require 'rubygems'
$:.unshift File.dirname(__FILE__)
require 'cdb'
class Gem::Database
DBFILE = File.expand_path "~/.gems.cdb"
def self.find(file)
DB[file] || DB[file+".rb"] || DB[file+".so"]
end
def self.rebuild!
CDBMake.open(DBFILE) do |db|
stdlibs = RbConfig::CONFIG.values_at("rubylibdir", "archdir", "sitelibdir", "sitearchdir", "vendorlibdir", "vendorarchdir")
paths = stdlibs + Gem.all_load_paths
p paths
paths.each do |path|
Dir["#{path}/**/*"].each do |filepath|
unless File.directory? filepath
filepath["#{path}/"] = ""
db[filepath] = path
end
end
end
end # CDBMake
end
def self.exists?
File.exists? DBFILE
end
rebuild! if not exists?
DB = CDB.new DBFILE
end
alias gem_original_autoload autoload
# def eagerload(const, path, &block)
# if block_given?
# yield
# else
# require(path)
# end
# end
# alias autoload eagerload
def autoload(const, path=nil, &block)
raise "Error: autoreq must be supplied with a file to load, or a block." unless !!path ^ block_given?
if block_given?
Module.autoreqs[const] = block
else
Module.autoreqs[const] = path
end
end
class Module
@@autoreq_is_searching_for = nil
alias const_missing_without_autoreq const_missing
def const_missing(const)
return if const == @@autoreq_is_searching_for
if thing = autoreqs[const]
case thing
when String, Symbol
require thing
when Proc
Object.class_eval(&thing)
else
raise "Error: Don't know how to autoload a #{thing.class}: #{thing.inspect}"
end
end
@@autoreq_is_searching_for = const
const_get(const) || const_missing_without_autoreq(const)
end
def autoreqs
@@autoreqs ||= {}
end
end
def require path
p [:require, path]
if loadpath = Gem::Database.find(path+".rb")
p :found_it
require_relative("#{loadpath}/#{path}.rb")
return
end
if Gem.unresolved_deps.empty? then
p :resolved
gem_original_require path
else
p :unresolved
spec = Gem::Specification.find { |s|
s.activated? and s.contains_requirable_file? path
}
unless spec then
found_specs = Gem::Specification.find_in_unresolved path
unless found_specs.empty? then
found_specs = [found_specs.last]
else
found_specs = Gem::Specification.find_in_unresolved_tree path
end
found_specs.each do |found_spec|
found_spec.activate
end
end
return gem_original_require path
end
rescue LoadError => load_error
if load_error.message.start_with?("Could not find") or
(load_error.message.end_with?(path) and Gem.try_activate(path)) then
return gem_original_require(path)
end
raise load_error
end
$:.unshift "."
require 'epitools'
require 'cdb'
require 'dbm'
dbfile = Path["gems.marshal"]
if dbfile.exists?
time { $db = dbfile.unmarshal }
else
time do
db = {}
Gem.all_load_paths.each do |path|
puts path
Dir["#{path}/**/*"].each do |file|
unless File.directory? file
file["#{path}/"] = ""
db[file] = path
end
end
end
dbfile.write db.marshal
$db = db
end
end
#$db = Hash[$db.to_a.take(50)]
class Abstract
def benchit
$db.keys.each do |k|
@db[k]
end
end
end
class MarshalDB < Abstract
def create
Path["db.marshal"].write $db.marshal
end
def load
@db = Path["db.marshal"].unmarshal
end
end
class DBMDB < Abstract
def create
db = DBM.new("db.dbm")
$db.each { |k,v| db[k] = v }
db.close
end
def load
@db = DBM.open("db.dbm")
end
end
class CDBDB < Abstract
def create
CDBMake.open("db.cdb") do |db|
$db.each { |k,v| db[k] = v }
end
end
def load
@db = CDB.new("db.cdb")
end
end
class JSONDB < Abstract
def create
Path["db.json"].write $db.to_json
end
def load
@db = Path["db.json"].read_json
end
end
dbclasses = [MarshalDB, JSONDB, DBMDB, CDBDB]
dbs = dbclasses.map(&:new)
benches = {}
actions = %w[create load benchit]
dbs.each do |dbobj|
actions.each do |action|
benches["#{dbobj.class.name}-#{action}"] = proc { dbobj.send(action) }
end
end
bench 1, benches
echo -n "with: "
strace -o >(wc -l) ruby -I. -rfast-require -e 'require "epitools"'
echo -n "without: "
strace -o >(wc -l) ruby -e 'require "epitools"'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment