From 171d886a4ac6cc691ddb5b062b57710bda7f3003 Mon Sep 17 00:00:00 2001 From: Edmund Li Date: Tue, 21 Mar 2017 10:34:04 -0700 Subject: [PATCH 1/5] each bang hash --- ...{each_bang_bm.rb => array_each_bang_bm.rb} | 1 - benchmark/each_slice_bang_bm.rb | 1 - benchmark/hash_each_bang_bm.rb | 104 ++++++++++++++++++ 3 files changed, 104 insertions(+), 2 deletions(-) rename benchmark/{each_bang_bm.rb => array_each_bang_bm.rb} (99%) create mode 100644 benchmark/hash_each_bang_bm.rb diff --git a/benchmark/each_bang_bm.rb b/benchmark/array_each_bang_bm.rb similarity index 99% rename from benchmark/each_bang_bm.rb rename to benchmark/array_each_bang_bm.rb index 3670529..f4d840e 100644 --- a/benchmark/each_bang_bm.rb +++ b/benchmark/array_each_bang_bm.rb @@ -13,7 +13,6 @@ class Thing; end puts '----------------------' arr = Array.new(100) { Thing.new } -line = '' arr.each do |el| GC.start diff --git a/benchmark/each_slice_bang_bm.rb b/benchmark/each_slice_bang_bm.rb index 154d78d..318c4cc 100644 --- a/benchmark/each_slice_bang_bm.rb +++ b/benchmark/each_slice_bang_bm.rb @@ -15,7 +15,6 @@ class Thing; end puts '----------------------' arr = Array.new(100) { Thing.new } -line = '' arr.each_slice(slize_size) do |slice| GC.start diff --git a/benchmark/hash_each_bang_bm.rb b/benchmark/hash_each_bang_bm.rb new file mode 100644 index 0000000..e6863d4 --- /dev/null +++ b/benchmark/hash_each_bang_bm.rb @@ -0,0 +1,104 @@ +require 'benchmark' +require_relative '../lib/hyper_iterator' + +class Key; end +class Val; end + +puts '---------------------------------------------------------' +puts '------------------------- each! -------------------------' + +puts '---------------------------------------------------------' +puts '------------------ Garbage Collection -------------------' + +puts 'Hash#each' +puts '----------------------' + +hash = {} +100.times do + hash[Key.new] = Val.new +end + +hash.each do |_| + GC.start + print ObjectSpace.each_object(Key).count + print ' ' + print ObjectSpace.each_object(Val).count + print ' ' +end + +puts +puts + +puts 'Hash#each!' +puts '----------------------' + +hash = {} +100.times do + hash[Key.new] = Val.new +end + +hash.each! do |_| + GC.start + print ObjectSpace.each_object(Key).count + print ' ' + print ObjectSpace.each_object(Val).count + print ' ' +end + +puts + +puts '---------------------------------------------------------' +puts '-------------------- Objects Created --------------------' + + +GC.disable +hash = {} +100.times do + hash[Key.new] = Val.new +end + +before = ObjectSpace.count_objects +hash.each do |_| +end +after = ObjectSpace.count_objects + +puts 'Hash#each' +puts '----------------------' +puts "# of arrays: %d" % (after[:T_ARRAY] - before[:T_ARRAY]) +puts "# of nodes: %d" % (after[:T_NODE] - before[:T_NODE]) + +puts + +hash = {} +100.times do + hash[Key.new] = Val.new +end + +before = ObjectSpace.count_objects +hash.each! do |el| +end +after = ObjectSpace.count_objects + +puts 'Hash#each!' +puts '----------------------' +puts "# of arrays: %d" % (after[:T_ARRAY] - before[:T_ARRAY]) +puts "# of nodes: %d" % (after[:T_NODE] - before[:T_NODE]) + +puts '---------------------------------------------------------' +puts '--------------- Execution Time Comparison ---------------' + +GC.enable +n = 10 +hash = {} +10_000.times do + hash[Key.new] = Val.new +end + +Benchmark.bmbm(7) do |x| + x.report('each!') { n.times { hash.each! { |el| nil } } } + x.report('each') { n.times { hash.each { |el| nil } } } +end + +puts '---------------------------------------------------------' + +puts \ No newline at end of file From 449a0fa7ee58438359801ee859eb8c44544d7c53 Mon Sep 17 00:00:00 2001 From: Edmund Li Date: Thu, 23 Mar 2017 09:45:21 -0700 Subject: [PATCH 2/5] bm for Hash#each! --- .../memory_bm/{each.rb => array_each.rb} | 0 .../{each_bang.rb => array_each_bang.rb} | 0 benchmark/memory_bm/hash_each.rb | 34 +++++++++++++++++++ benchmark/memory_bm/hash_each_bang.rb | 34 +++++++++++++++++++ bin/bm | 7 ++-- lib/hyper_iterator.rb | 3 +- lib/iterators/hash_each_bang.rb | 11 ++++++ 7 files changed, 86 insertions(+), 3 deletions(-) rename benchmark/memory_bm/{each.rb => array_each.rb} (100%) rename benchmark/memory_bm/{each_bang.rb => array_each_bang.rb} (100%) create mode 100644 benchmark/memory_bm/hash_each.rb create mode 100644 benchmark/memory_bm/hash_each_bang.rb create mode 100644 lib/iterators/hash_each_bang.rb diff --git a/benchmark/memory_bm/each.rb b/benchmark/memory_bm/array_each.rb similarity index 100% rename from benchmark/memory_bm/each.rb rename to benchmark/memory_bm/array_each.rb diff --git a/benchmark/memory_bm/each_bang.rb b/benchmark/memory_bm/array_each_bang.rb similarity index 100% rename from benchmark/memory_bm/each_bang.rb rename to benchmark/memory_bm/array_each_bang.rb diff --git a/benchmark/memory_bm/hash_each.rb b/benchmark/memory_bm/hash_each.rb new file mode 100644 index 0000000..7008fef --- /dev/null +++ b/benchmark/memory_bm/hash_each.rb @@ -0,0 +1,34 @@ +require 'benchmark' +require_relative '../../lib/hyper_iterator' +$stdout.sync = true + +puts +puts '----------------- Hash#each! -----------------' +puts '#i user system total real' + +base_hash = {} +1000.times { |i| base_hash["k#{i}"] = '-' * 10 } +hashes = [base_hash] + +i = 0 +while true + print "#{i} " + hash = {} + report = Benchmark.measure do + hashes[i].each do |k, v| + hash[k.dup] = v.dup + end + + # Try to use this line and see how many more iterations you can get + # Remember to uncomment line#24 as well. + # You need to pop the array so the reference goes away. + # arrs[0].each! { |el| arr << el.dup } + end + + # Uncomment this to use with the above line#22 + # arrs.pop + + puts report + hashes << hash + i += 1 +end diff --git a/benchmark/memory_bm/hash_each_bang.rb b/benchmark/memory_bm/hash_each_bang.rb new file mode 100644 index 0000000..1e6752c --- /dev/null +++ b/benchmark/memory_bm/hash_each_bang.rb @@ -0,0 +1,34 @@ +require 'benchmark' +require_relative '../../lib/hyper_iterator' +$stdout.sync = true + +puts +puts '----------------- Hash#each! -----------------' +puts '#i user system total real' + +base_hash = {} +1000.times { |i| base_hash["k#{i}"] = '-' * 10 } +hashes = [base_hash] + +i = 0 +while true + print "#{i} " + hash = {} + report = Benchmark.measure do + hashes[i].each! do |k, v| + hash[k.dup] = v.dup + end + + # Try to use this line and see how many more iterations you can get + # Remember to uncomment line#24 as well. + # You need to pop the array so the reference goes away. + # arrs[0].each! { |el| arr << el.dup } + end + + # Uncomment this to use with the above line#22 + # arrs.pop + + puts report + hashes << hash + i += 1 +end diff --git a/bin/bm b/bin/bm index df759c6..c4440eb 100755 --- a/bin/bm +++ b/bin/bm @@ -2,11 +2,14 @@ docker_command="docker run -m=4m -v `pwd`:`pwd` -w `pwd` hyper_iterator ruby ./benchmark/memory_bm" if [ "$1" = "each!" ] || [ "$1" = 1 ]; then - eval "$docker_command/each.rb" - eval "$docker_command/each_bang.rb" + eval "$docker_command/array_each.rb" + eval "$docker_command/array_each_bang.rb" elif [ "$1" = "each_slice!" ] || [ "$1" = 2 ]; then eval "$docker_command/each_slice.rb" eval "$docker_command/each_slice_bang.rb" +elif [ "$1" = 3 ]; then + eval "$docker_command/hash_each.rb" + eval "$docker_command/hash_each_bang.rb" else echo 'Please specify method for benchmarking. You can choose anyone from below:' echo '1. each!' diff --git a/lib/hyper_iterator.rb b/lib/hyper_iterator.rb index 077d54a..232395d 100644 --- a/lib/hyper_iterator.rb +++ b/lib/hyper_iterator.rb @@ -1,5 +1,6 @@ require_relative "./hyper_iterator/version" require_relative "./iterators/each_bang" +require_relative "./iterators/hash_each_bang" require_relative "./iterators/each_slice_bang" module HyperIterator @@ -14,5 +15,5 @@ def self.each!(iterable) end Array.include HyperIterator::EachBang -Hash.include HyperIterator::EachBang +Hash.include HyperIterator::HashEachBang Array.include HyperIterator \ No newline at end of file diff --git a/lib/iterators/hash_each_bang.rb b/lib/iterators/hash_each_bang.rb new file mode 100644 index 0000000..5e228c5 --- /dev/null +++ b/lib/iterators/hash_each_bang.rb @@ -0,0 +1,11 @@ +module HyperIterator + module HashEachBang + def each! + while count > 0 + yield first + delete first[0] + end + nil + end + end +end \ No newline at end of file From f7c1ac0c9ca780c7cae6025edec7a206612c29b8 Mon Sep 17 00:00:00 2001 From: Edmund Li Date: Sun, 26 Mar 2017 20:29:51 -0700 Subject: [PATCH 3/5] test Hash#each! implementation --- lib/iterators/hash_each_bang.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/iterators/hash_each_bang.rb b/lib/iterators/hash_each_bang.rb index 5e228c5..c1f8980 100644 --- a/lib/iterators/hash_each_bang.rb +++ b/lib/iterators/hash_each_bang.rb @@ -1,9 +1,9 @@ module HyperIterator module HashEachBang def each! - while count > 0 - yield first - delete first[0] + each do |pair| + yield pair + self[pair[0]] = nil end nil end From 7494d362682d5d9b6948a16d5947c328d0204d00 Mon Sep 17 00:00:00 2001 From: Edmund Li Date: Mon, 27 Mar 2017 10:23:45 -0700 Subject: [PATCH 4/5] typo fix --- benchmark/memory_bm/hash_each.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benchmark/memory_bm/hash_each.rb b/benchmark/memory_bm/hash_each.rb index 7008fef..9a9b29d 100644 --- a/benchmark/memory_bm/hash_each.rb +++ b/benchmark/memory_bm/hash_each.rb @@ -3,7 +3,7 @@ $stdout.sync = true puts -puts '----------------- Hash#each! -----------------' +puts '----------------- Hash#each -----------------' puts '#i user system total real' base_hash = {} From 7440e011c9bbcae127519a08ec2652759c34cf28 Mon Sep 17 00:00:00 2001 From: Edmund Li Date: Mon, 27 Mar 2017 10:32:49 -0700 Subject: [PATCH 5/5] fix specs --- test/iterators/hash_each_bang_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/iterators/hash_each_bang_test.rb b/test/iterators/hash_each_bang_test.rb index 94ae383..d0eb841 100644 --- a/test/iterators/hash_each_bang_test.rb +++ b/test/iterators/hash_each_bang_test.rb @@ -23,9 +23,9 @@ def test_that_it_yield_block assert vals == ord_range end - def test_that_it_remove_elements_from_array_on_the_fly + def test_that_it_sets_all_values_to_nil_on_the_fly @hash.each! {} - assert @hash.count == 0 + assert @hash.values.all?(&:nil?) end def test_that_it_returns_nil @@ -83,6 +83,6 @@ def test_that_it_can_use_class_method assert keys_1 == keys_2 assert vals_1 == vals_2 - assert hash_2.empty? + assert hash_2.values.all?(&:nil?) end end