require "benchmark" require "./utilities.cr" require "./db-cars.cr" # List of environment variables and default values: # ENV["CARNAME"] rescue "Corvet-#{(db_size/2).to_i}" # ENV["CARCOLOR"] rescue "red" # ENV["CARKEYWORD"] rescue "spacious" # ENV["DBSIZE"] rescue 50_000 # ENV["DBSIZE_START"] rescue 1_000 # ENV["DBSIZE_INCREMENT"] rescue 1_000 # ENV["REPORT_DIR"] rescue "results" # ENV["NBRUN"] rescue 100 # ENV["MAXINDEXES"] rescue 5_000 class DODB::Storage(V) def empty_db while pop end end end class Context class_property report_dir = "results" class_property max_indexes = 5_000 class_property nb_run = 100 class_property from = 1_000 class_property to = 50_000 class_property incr = 1_000 end # To simplify the creation of graphs, it's better to have fake data for # partitions and tags that won't be actually covered. # 0 means the absence of data. def fake_report(name) durations = Array(Int32).new Context.nb_run, 0 File.open("#{Context.report_dir}/#{name}.raw", "w") do |file| durations.each do |d| file.puts d end end puts "#{name}: no report" end def report(storage, name, &block) durations = run_n_times Context.nb_run, &block File.open("#{Context.report_dir}/#{name}.raw", "w") do |file| durations.each do |d| file.puts d end end avr = durations.reduce { |a, b| a + b } / Context.nb_run puts "#{name}: #{avr}" avr end def long_operation(text) STDOUT.write "#{text}\r".to_slice yield STDOUT.write " \r".to_slice end def verbose_add_cars(storage, nbcars, name, max_indexes) long_operation "add #{nbcars} values to #{name}" do add_cars storage, nbcars, max_indexes: max_indexes end end # Add first entries, then loop: speed tests, add entries. def prepare_env(storage, name, s_index, s_partition, s_tags, &) verbose_add_cars storage, Context.from, name, max_indexes: Context.max_indexes current = Context.from to = Context.to incr = Context.incr while current < to yield storage, current, name, s_index, s_partition, s_tags break if current + incr >= to verbose_add_cars storage, incr, name, max_indexes: Context.max_indexes current += incr end long_operation "removing #{name} data" { storage.rm_storage_dir } end def batch() cars_ram = DODB::RAMOnlySpecDataBase(Car).new cars_cached = DODB::CachedSpecDataBase(Car).new cars_semi = DODB::SpecDataBase(Car).new "-semi" cars_uncached = DODB::SpecDataBase(Car).new ram_Sby_name, ram_Sby_color, ram_Sby_keywords = ram_indexes cars_ram cached_Sby_name, cached_Sby_color, cached_Sby_keywords = cached_indexes cars_cached semi_Sby_name, semi_Sby_color, semi_Sby_keywords = cached_indexes cars_semi uncached_Sby_name, uncached_Sby_color, uncached_Sby_keywords = uncached_indexes cars_uncached fn = ->(storage : DODB::Storage(Car), current_db_size : Int32, name : String, search_name : DODB::Index(Car), search_color : DODB::Partition(Car), search_keywords : DODB::Tags(Car)) { name_to_search = ENV["CARNAME"] rescue "Corvet-#{(current_db_size/2).to_i}" color_to_search = ENV["CARCOLOR"] rescue "red" keyword_to_search = ENV["CARKEYWORD"] rescue "spacious" puts "NEW BATCH: db-size #{current_db_size}, name: '#{name_to_search}', color: '#{color_to_search}', tag: '#{keyword_to_search}'" report(storage, "#{name}_#{current_db_size}_index") do corvet = search_name.get name_to_search end if current_db_size <= Context.max_indexes report(storage, "#{name}_#{current_db_size}_partitions") do corvet = search_color.get? color_to_search end report(storage, "#{name}_#{current_db_size}_tags") do corvet = search_keywords.get? keyword_to_search end else fake_report("#{name}_#{current_db_size}_partitions") fake_report("#{name}_#{current_db_size}_tags") end } prepare_env cars_cached, "cached", cached_Sby_name, cached_Sby_color, cached_Sby_keywords, &fn prepare_env cars_ram, "ram", ram_Sby_name, ram_Sby_color, ram_Sby_keywords, &fn prepare_env cars_semi, "semi", semi_Sby_name, semi_Sby_color, semi_Sby_keywords, &fn prepare_env cars_uncached, "uncached", uncached_Sby_name, uncached_Sby_color, uncached_Sby_keywords, &fn end def perform_add(storage : DODB::Storage(Car)) corvet0 = Car.new "Corvet", "red", [ "shiny", "impressive", "fast", "elegant" ] i = 0 perform_benchmark_average Context.nb_run, do corvet = corvet0.clone corvet.name = "Corvet-#{i}" storage << corvet i += 1 end end def batch_add() cars_ram = DODB::RAMOnlySpecDataBase(Car).new cars_cached = DODB::CachedSpecDataBase(Car).new cars_semi = DODB::SpecDataBase(Car).new "-semi" cars_uncached = DODB::SpecDataBase(Car).new ram_indexes cars_ram cached_indexes cars_cached cached_indexes cars_semi uncached_indexes cars_uncached avr = perform_add(cars_ram) puts "(ram db and indexes) add a value (average on #{Context.nb_run} tries): #{avr}" avr = perform_add(cars_cached) puts "(cached db and indexes) add a value (average on #{Context.nb_run} tries): #{avr}" avr = perform_add(cars_semi) puts "(uncached db but cached indexes) add a value (average on #{Context.nb_run} tries): #{avr}" avr = perform_add(cars_uncached) puts "(uncached db and indexes) add a value (average on #{Context.nb_run} tries): #{avr}" cars_ram.rm_storage_dir cars_cached.rm_storage_dir cars_semi.rm_storage_dir cars_uncached.rm_storage_dir end ENV["REPORT_DIR"]?.try { |report_dir| Context.report_dir = report_dir } Dir.mkdir_p Context.report_dir ENV["MAXINDEXES"]?.try { |it| Context.max_indexes = it.to_i } ENV["NBRUN"]?.try { |it| Context.nb_run = it.to_i } ENV["DBSIZE"]?.try { |it| Context.to = it.to_i } ENV["DBSIZE_START"]?.try { |it| Context.from = it.to_i } ENV["DBSIZE_INCREMENT"]?.try { |it| Context.incr = it.to_i } pp! Context.nb_run pp! Context.from pp! Context.to pp! Context.incr pp! Context.max_indexes batch batch_add