min_max 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Cargo.lock +2 -2
- data/Cargo.toml +2 -1
- data/README.md +4 -4
- data/benchmarks/benchmarks.rb +85 -0
- data/ext/min_max/src/lib.rs +3 -3
- data/lib/min_max/version.rb +1 -1
- data/lib/min_max.rb +20 -32
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6d739946dcb0939e2e05893222c927f4dea0eda65da5c0a00156402de3e49c29
|
4
|
+
data.tar.gz: 61b4453a94b93bb2ccefd0787a751cef5d3ef380ac0ed591c73c3b0afddc394b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70dd4402ca82a60cffbc451ea134ca9fc34391f28311d23726d22055bfc01db9ba62002f0d54c76282888993613f2bf5618dcfa7a964da39c6995747401f3a3f
|
7
|
+
data.tar.gz: 31ada4f8ed50624701e389c6a1d50b83b75a585ef703d2f18c6511498dc9373647fa1f88d959ccdcbf56336d38dc550e1ce96710644f65970f2341549f843d53
|
data/Cargo.lock
CHANGED
@@ -270,9 +270,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
|
|
270
270
|
|
271
271
|
[[package]]
|
272
272
|
name = "shlex"
|
273
|
-
version = "1.
|
273
|
+
version = "1.3.0"
|
274
274
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
275
|
-
checksum = "
|
275
|
+
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
276
276
|
|
277
277
|
[[package]]
|
278
278
|
name = "syn"
|
data/Cargo.toml
CHANGED
data/README.md
CHANGED
@@ -24,10 +24,6 @@ Add this line to your application's Gemfile:
|
|
24
24
|
|
25
25
|
```ruby
|
26
26
|
gem 'min_max'
|
27
|
-
|
28
|
-
# or manually specify target . E.g.
|
29
|
-
|
30
|
-
CARGO_BUILD_TARGET=x86_64-apple-darwin gem install min_max
|
31
27
|
```
|
32
28
|
|
33
29
|
|
@@ -40,6 +36,10 @@ bundle install
|
|
40
36
|
Or install it yourself as:
|
41
37
|
```bash
|
42
38
|
gem install min_max
|
39
|
+
|
40
|
+
# or manually specify target . E.g.
|
41
|
+
|
42
|
+
CARGO_BUILD_TARGET=x86_64-apple-darwin gem install min_max
|
43
43
|
```
|
44
44
|
|
45
45
|
## Usage
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
require "min_max"
|
3
|
+
|
4
|
+
require 'bundler/inline'
|
5
|
+
|
6
|
+
gemfile do
|
7
|
+
source 'https://rubygems.org'
|
8
|
+
gem 'rb_heap'
|
9
|
+
gem 'algorithms'
|
10
|
+
gem 'ruby-heap'
|
11
|
+
gem 'pqueue'
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'benchmark'
|
15
|
+
require 'rb_heap'
|
16
|
+
require 'min_max'
|
17
|
+
|
18
|
+
|
19
|
+
data = 100_000.times.map{ Random.rand(0...1000_000_000) }
|
20
|
+
rb_hp = Heap.new(:<)
|
21
|
+
mm_hp = MinMax[]
|
22
|
+
|
23
|
+
Benchmark.bm do |x|
|
24
|
+
x.report("push_rb_heap"){ data.each{|d| rb_hp.add(d) } }
|
25
|
+
x.report("push_mm_heap"){ data.each{|d| mm_hp.push(d) } }
|
26
|
+
x.report("push_mm_heap_batches"){ mm_hp = MinMax[]; data.each_slice(1000){|d| mm_hp.push(*d) } }
|
27
|
+
end
|
28
|
+
|
29
|
+
Benchmark.bm do |x|
|
30
|
+
x.report("pop_rb_heap"){ 100_000.times{|d| rb_hp.pop } }
|
31
|
+
x.report("pop_mm_heap"){ 100_000.times{|d| mm_hp.pop_min } }
|
32
|
+
x.report("pop_mm_heap_batches"){ 1000.times{|d| mm_hp.pop_min(100) } }
|
33
|
+
end
|
34
|
+
|
35
|
+
Object.send(:remove_const, :Heap)
|
36
|
+
|
37
|
+
require 'Heap'
|
38
|
+
puts "# ruby-heap vs min_max"
|
39
|
+
ruby_hp = Heap::BinaryHeap::MinHeap.new
|
40
|
+
mm_hp = MinMax[]
|
41
|
+
|
42
|
+
Benchmark.bm do |x|
|
43
|
+
x.report("push_ruby_heap"){ data.each{|d| ruby_hp.add(d) } }
|
44
|
+
x.report("push_mm_heap"){ data.each{|d| mm_hp.push(d) } }
|
45
|
+
x.report("push_mm_heap_batches"){ mm_hp = MinMax[]; data.each_slice(1000){|d| mm_hp.push(*d) } }
|
46
|
+
end
|
47
|
+
|
48
|
+
Benchmark.bm do |x|
|
49
|
+
x.report("pop_ruby_heap"){ 100_000.times{|d| ruby_hp.extract_min! } }
|
50
|
+
x.report("pop_mm_heap"){ 100_000.times{|d| mm_hp.pop_min } }
|
51
|
+
x.report("pop_mm_heap_batches"){ 1000.times{|d| mm_hp.pop_min(100) } }
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
require 'algorithms'
|
56
|
+
minheap = Containers::MinHeap.new()
|
57
|
+
mm_hp = MinMax[]
|
58
|
+
|
59
|
+
Benchmark.bm do |x|
|
60
|
+
x.report("push_algos_heap"){ data.each{|d| minheap.push(d) } }
|
61
|
+
x.report("push_mm_heap"){ data.each{|d| mm_hp.push(d) } }
|
62
|
+
x.report("push_mm_heap_batches"){ mm_hp = MinMax[]; data.each_slice(1000){|d| mm_hp.push(*d) } }
|
63
|
+
end
|
64
|
+
|
65
|
+
Benchmark.bm do |x|
|
66
|
+
x.report("pop_algos_heap"){ 100_000.times{|d| minheap.pop } }
|
67
|
+
x.report("pop_mm_heap"){ 100_000.times{|d| mm_hp.pop_min } }
|
68
|
+
x.report("pop_mm_heap_batches"){ 1000.times{|d| mm_hp.pop_min(100) } }
|
69
|
+
end
|
70
|
+
|
71
|
+
require 'pqueue'
|
72
|
+
pqueue = PQueue.new()
|
73
|
+
mm_hp = MinMax[]
|
74
|
+
|
75
|
+
Benchmark.bm do |x|
|
76
|
+
x.report("push_algos_heap"){ data.each{|d| pqueue.push(d) } }
|
77
|
+
x.report("push_mm_heap"){ data.each{|d| mm_hp.push(d) } }
|
78
|
+
x.report("push_mm_heap_batches"){ mm_hp = MinMax[]; data.each_slice(1000){|d| mm_hp.push(*d) } }
|
79
|
+
end
|
80
|
+
|
81
|
+
Benchmark.bm do |x|
|
82
|
+
x.report("pop_algos_heap"){ 100_000.times{|d| minheap.pop } }
|
83
|
+
x.report("pop_mm_heap"){ 100_000.times{|d| mm_hp.pop_min } }
|
84
|
+
x.report("pop_mm_heap_batches"){ 1000.times{|d| mm_hp.pop_min(100) } }
|
85
|
+
end
|
data/ext/min_max/src/lib.rs
CHANGED
@@ -52,9 +52,9 @@ impl RubyMinMaxHeap {
|
|
52
52
|
|
53
53
|
fn push(&self, values: RArray) -> Result<(), Error> {
|
54
54
|
let mut hp = self.heap.borrow_mut();
|
55
|
-
let values_vec = values.to_vec::<(i64, i64)>()
|
56
|
-
values_vec.
|
57
|
-
hp.push(PriorityOrderableValue(priority, key));
|
55
|
+
let values_vec = values.to_vec::<(i64, i64)>()?;
|
56
|
+
values_vec.iter().for_each(|(priority, key)| {
|
57
|
+
hp.push(PriorityOrderableValue(*priority, *key));
|
58
58
|
});
|
59
59
|
Ok(())
|
60
60
|
}
|
data/lib/min_max/version.rb
CHANGED
data/lib/min_max.rb
CHANGED
@@ -6,7 +6,7 @@ require_relative "min_max/min_max"
|
|
6
6
|
class MinMax
|
7
7
|
class Error < StandardError; end
|
8
8
|
|
9
|
-
attr_reader :priority_blk, :storage, :
|
9
|
+
attr_reader :priority_blk, :storage, :mtx
|
10
10
|
|
11
11
|
def self.[](*args, &blk)
|
12
12
|
new(*args, &blk)
|
@@ -15,9 +15,8 @@ class MinMax
|
|
15
15
|
def self.new(*args, &blk)
|
16
16
|
self._new.tap{|s|
|
17
17
|
s.instance_eval{
|
18
|
-
@priority_blk = (blk || proc{|x|
|
19
|
-
@storage = Hash.new
|
20
|
-
@counts = Hash.new(0)
|
18
|
+
@priority_blk = (blk || proc{|x| x.respond_to?(:priority) ? x.priority : x.to_i })
|
19
|
+
@storage = Hash.new{|h,k| h[k] = [0, nil] }
|
21
20
|
@mtx ||= Mutex.new
|
22
21
|
}
|
23
22
|
s.push(*args)
|
@@ -25,18 +24,17 @@ class MinMax
|
|
25
24
|
end
|
26
25
|
|
27
26
|
def push(*args)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
_push(mapped)
|
27
|
+
mapped = args.map do |a|
|
28
|
+
hash = a.hash
|
29
|
+
entry = self.storage[hash]
|
30
|
+
entry[0] += 1
|
31
|
+
entry[1] ||= a
|
32
|
+
[
|
33
|
+
(self.priority_blk.call(a) rescue 0),
|
34
|
+
hash
|
35
|
+
]
|
38
36
|
end
|
39
|
-
|
37
|
+
_push(mapped)
|
40
38
|
end
|
41
39
|
|
42
40
|
def add(*args)
|
@@ -44,17 +42,13 @@ class MinMax
|
|
44
42
|
end
|
45
43
|
|
46
44
|
def pop_max(*args)
|
47
|
-
|
48
|
-
|
49
|
-
popped.kind_of?(Array) ? popped.map{|p| retrieve(p) } : retrieve(popped)
|
50
|
-
}
|
45
|
+
popped = _pop_max(*args)
|
46
|
+
popped.kind_of?(Array) ? popped.map{|p| retrieve(p) } : retrieve(popped)
|
51
47
|
end
|
52
48
|
|
53
49
|
def pop_min(*args)
|
54
|
-
|
55
|
-
|
56
|
-
popped.kind_of?(Array) ? popped.map{|p| retrieve(p) } : retrieve(popped)
|
57
|
-
}
|
50
|
+
popped = _pop_min(*args)
|
51
|
+
popped.kind_of?(Array) ? popped.map{|p| retrieve(p) } : retrieve(popped)
|
58
52
|
end
|
59
53
|
|
60
54
|
def peek_min(*args)
|
@@ -101,15 +95,9 @@ class MinMax
|
|
101
95
|
|
102
96
|
private
|
103
97
|
def retrieve(hash, remove=true)
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
else
|
108
|
-
self.storage[hash]
|
109
|
-
end
|
110
|
-
else
|
111
|
-
self.storage[hash]
|
112
|
-
end
|
98
|
+
entry = self.storage[hash]
|
99
|
+
self.storage.delete(hash) if remove && (entry[0] -= 1) == 0
|
100
|
+
entry[1]
|
113
101
|
end
|
114
102
|
|
115
103
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: min_max
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- LICENSE.txt
|
67
67
|
- README.md
|
68
68
|
- Rakefile
|
69
|
+
- benchmarks/benchmarks.rb
|
69
70
|
- ext/min_max/Cargo.toml
|
70
71
|
- ext/min_max/extconf.rb
|
71
72
|
- ext/min_max/src/lib.rs
|