sumbur 0.0.2 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,22 @@
1
1
  #include "ruby.h"
2
2
 
3
3
  #define L 0xFFFFFFFF
4
+
5
+ static unsigned int L27_38[] = {L / 27, L / 28, L / 29, L / 30, L / 31, L / 32,
6
+ L / 33, L / 34, L / 35, L / 36, L / 37, L / 38,
7
+ L / 39, L / 40, L / 41, L / 42, L / 43, L / 44,
8
+ L / 45, L / 46, L / 47, L / 48, L / 49, L / 50,
9
+ L / 51, L / 52, L / 53, L / 54, L / 55, L / 56,
10
+ L / 57, L / 58, L / 59, L / 60, L / 61, L / 62
11
+ };
12
+ static unsigned int LL27_38[] = {L/(26*27), L/(27*28), L/(28*29), L/(29*30), L/(30*31), L/(31*32),
13
+ L/(32*33), L/(33*34), L/(34*35), L/(35*36), L/(36*37), L/(37*38),
14
+ L/(38*39), L/(39*40), L/(40*41), L/(41*42), L/(42*43), L/(43*44),
15
+ L/(44*45), L/(45*46), L/(46*47), L/(47*48), L/(48*49), L/(49*50),
16
+ L/(50*51), L/(51*52), L/(52*53), L/(53*54), L/(54*55), L/(55*56),
17
+ L/(56*57), L/(57*58), L/(58*59), L/(59*60), L/(60*61), L/(61*62)
18
+ };
19
+
4
20
  static VALUE
5
21
  rb_sumbur(VALUE self, VALUE hashed_int, VALUE capacity)
6
22
  {
@@ -8,13 +24,13 @@ rb_sumbur(VALUE self, VALUE hashed_int, VALUE capacity)
8
24
  unsigned int capa = NUM2UINT(capacity);
9
25
  unsigned int part, n, i, c;
10
26
 
11
- if (capacity == 0) {
27
+ if (capa == 0) {
12
28
  rb_raise(rb_eArgError, "Sumbur is not applicable to empty cluster");
13
29
  }
14
30
 
15
31
  part = L / capa;
16
32
 
17
- if (L - h <= part) return INT2FIX(0);
33
+ if (L - h < part) return INT2FIX(0);
18
34
 
19
35
  n = 1;
20
36
 
@@ -22,9 +38,9 @@ rb_sumbur(VALUE self, VALUE hashed_int, VALUE capacity)
22
38
  if (h >= L / 2) h -= L / 2;
23
39
  else {
24
40
  n = 2;
25
- if (L / 2 - h < part) break;
41
+ if (L / 2 - h < part) return INT2FIX(1);
26
42
  }
27
- if (capa == 2) break;
43
+ if (capa == 2) return INT2FIX(1);
28
44
 
29
45
  #define curslice(i) (L / (i * (i - 1)))
30
46
  #define unroll(i) \
@@ -32,17 +48,32 @@ rb_sumbur(VALUE self, VALUE hashed_int, VALUE capacity)
32
48
  else { \
33
49
  h += curslice(i) * (i - n - 1); \
34
50
  n = i; \
35
- if (L / i - h < part) break; \
51
+ if (L / i - h < part) return INT2FIX(n-1); \
36
52
  } \
37
- if (capa == i) break
53
+ if (capa == i) return INT2FIX(n-1)
54
+
55
+ unroll(3); unroll(4); unroll(5);
56
+ unroll(6); unroll(7); unroll(8);
57
+ unroll(9); unroll(10); unroll(11);
58
+ unroll(12); unroll(13); unroll(14);
59
+ unroll(15); unroll(16); unroll(17);
60
+ unroll(18); unroll(19); unroll(20);
61
+ unroll(21); unroll(22); unroll(23);
62
+ unroll(24); unroll(25); unroll(26);
38
63
 
39
- unroll(3); unroll(4); unroll(5); unroll(6); unroll(7);
40
- unroll(8); unroll(9); unroll(10); unroll(11); unroll(12);
41
- unroll(13); unroll(14); unroll(15); unroll(16); unroll(17);
42
- unroll(18); unroll(19); unroll(20); unroll(21); unroll(22);
43
- unroll(23); unroll(24);
64
+ for (i = 27; i <= capa && i <= 62; i++) {
65
+ c = LL27_38[i-27];
66
+ if (c <= h) {
67
+ h -= c;
68
+ }
69
+ else {
70
+ h += c * (i - n - 1);
71
+ n = i;
72
+ if (L27_38[i-27] - h < part) return INT2FIX(n-1);
73
+ }
74
+ }
44
75
 
45
- for(i = 25; i <= capa; i++) {
76
+ for(i = 63; i <= capa; i++) {
46
77
  c = L / (i * (i - 1));
47
78
  if (c <= h) {
48
79
  h -= c;
@@ -50,7 +81,7 @@ rb_sumbur(VALUE self, VALUE hashed_int, VALUE capacity)
50
81
  else {
51
82
  h += c * (i - n - 1);
52
83
  n = i;
53
- if (L / i - h < part) break;
84
+ if (L / i - h < part) return INT2FIX(n - 1);
54
85
  }
55
86
  }
56
87
  } while(0);
@@ -9,7 +9,7 @@ module Sumbur
9
9
  l = 0xFFFFFFFF
10
10
  part = l / cluster_capacity
11
11
 
12
- return 0 if l - hashed_integer <= part
12
+ return 0 if l - hashed_integer < part
13
13
 
14
14
  h = hashed_integer
15
15
  n = 1
@@ -1,3 +1,3 @@
1
1
  module Sumbur
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -3,11 +3,18 @@ require 'minitest/autorun'
3
3
 
4
4
  $spread_cache = {}
5
5
 
6
- HASHED = (1..1_000_000).map{|i| [i.hash & 0xFFFFFFFF, i]}
6
+ HASHED = (1..1_000_000).map{|i|
7
+ h = i ^ (i >> 16)
8
+ h = (h * 0x85ebca6b) & 0xFFffFFff
9
+ h ^= h >> 13
10
+ h = (h * 0xc2b2ae35) & 0xFFffFFff
11
+ [h ^ (h >> 16), i]
12
+ }
7
13
 
8
14
  def spread(num, capa, sumbur)
9
15
  start = Time.now
10
- v = $spread_cache[ [num, capa, sumbur] ] ||= HASHED[0, num].
16
+ #v = $spread_cache[ [num, capa, sumbur] ] ||=
17
+ v = HASHED[0, num].
11
18
  map{|hash, int| [sumbur.sumbur(hash, capa), int]}.
12
19
  group_by{|serv, int| serv}
13
20
  d = Time.now - start
@@ -17,17 +24,17 @@ end
17
24
 
18
25
  shared_example = proc do
19
26
  it "should spread capacity" do
20
- for num in [100_000, 1_000_000]
27
+ for num, eps in [[100_000, 0.05], [1_000_000, 0.011]]
21
28
  for capa in [2,3,7,8,17,18]
22
29
  spread(num, capa, sumbur).each{|serv, ints|
23
- ints.size.must_be_within_epsilon num/capa, 7000.0/num
30
+ ints.size.must_be_within_epsilon num/capa, eps
24
31
  }
25
32
  end
26
33
  end
27
34
  end
28
35
 
29
36
  it "should reshard values cleanly" do
30
- for num in [100_000, 1_000_000]
37
+ for num, eps in [[100_000, 0.2], [1_000_000, 0.05]]
31
38
  for capa in [2,3,7,8,17,18]
32
39
  cur = spread(num, capa, sumbur)
33
40
  nxt = spread(num, capa+1, sumbur)
@@ -35,9 +42,9 @@ shared_example = proc do
35
42
  for i in 0...capa
36
43
  (nxt[i] - cur[i]).must_be_empty
37
44
  moved += mvd = (cur[i] - nxt[i]).size
38
- mvd.must_be_within_epsilon (num/capa - num/(capa+1)), 40000.0/num
45
+ mvd.must_be_within_epsilon (num/capa - num/(capa+1)), eps
39
46
  end
40
- moved.must_be_within_epsilon num/(capa+1), 7000.0/num
47
+ moved.must_be_within_epsilon num/(capa+1), eps
41
48
  end
42
49
  end
43
50
  end
@@ -45,20 +52,32 @@ end
45
52
 
46
53
  require 'sumbur/pure_ruby'
47
54
  describe "Pure Ruby" do
48
- let(:sumbur){ Sumbur::PureRuby }
55
+ def sumbur
56
+ Sumbur::PureRuby
57
+ end
49
58
  class_exec &shared_example
50
59
  end
51
60
 
52
61
  begin
53
- require 'sumbur/native_sumbur'
62
+ if RUBY_ENGINE == 'jruby'
63
+ require 'sumbur/sumbur.jar'
64
+ else
65
+ require 'sumbur/native_sumbur'
66
+ end
54
67
 
55
68
  describe "Native" do
56
- let(:sumbur) { Sumbur::NativeSumbur }
69
+ def sumbur
70
+ if RUBY_ENGINE == 'jruby'
71
+ Sumbur::Java
72
+ else
73
+ Sumbur::NativeSumbur
74
+ end
75
+ end
57
76
  class_exec &shared_example
58
77
 
59
78
  it "should produce same spread as pure ruby version" do
60
- for capa in [2,3,4,7,8,9,17,18,19]
61
- spread(1_000_000, capa, Sumbur::NativeSumbur).must_equal spread(1_000_000, capa, Sumbur::PureRuby)
79
+ for capa in [2,3,4,7,8,9,17,18,19,100]
80
+ spread(1_000_000, capa, sumbur).must_equal spread(1_000_000, capa, Sumbur::PureRuby)
62
81
  end
63
82
  end
64
83
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sumbur
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,9 +10,9 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-08-03 00:00:00.000000000 Z
13
+ date: 2012-08-10 00:00:00.000000000 Z
14
14
  dependencies: []
15
- description: Sumbur - consistent spreading
15
+ description: Sumbur - consistent spreading for server balancing
16
16
  email:
17
17
  - funny.falcon@gmail.com
18
18
  - uint32@mail.ru
@@ -51,7 +51,6 @@ rubyforge_project:
51
51
  rubygems_version: 1.8.24
52
52
  signing_key:
53
53
  specification_version: 3
54
- summary: Sumbur - consistent spreading
54
+ summary: Sumbur - consistent spreading for server balancing
55
55
  test_files:
56
56
  - test/test_sumbur.rb
57
- has_rdoc: