splitclient-rb 4.4.0 → 4.5.1.pre.dev
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +7 -0
- data/CHANGES.txt +9 -0
- data/NEWS +4 -0
- data/README.md +2 -0
- data/Rakefile +23 -3
- data/ext/murmurhash/3_x86_32.c +88 -0
- data/ext/murmurhash/extconf.rb +3 -0
- data/ext/murmurhash/murmurhash.c +251 -0
- data/ext/murmurhash/murmurhash.h +94 -0
- data/lib/murmurhash/base.rb +58 -0
- data/lib/murmurhash/murmurhash.jar +0 -0
- data/lib/murmurhash/murmurhash_mri.rb +3 -0
- data/lib/splitclient-rb/cache/repositories/impressions_repository.rb +0 -2
- data/lib/splitclient-rb/engine/evaluator/splitter.rb +97 -92
- data/lib/splitclient-rb/engine/parser/evaluator.rb +3 -2
- data/lib/splitclient-rb/version.rb +1 -1
- data/lib/splitclient-rb.rb +5 -0
- data/splitclient-rb.gemspec +16 -5
- data/tasks/{console.rake → irb.rake} +1 -1
- metadata +18 -55
- data/console +0 -2
- data/runTests +0 -2
- data/tasks/benchmark_hashing_algorithm.rake +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 35f1c408826430c3833af34b39b302e005b0e3d3
|
4
|
+
data.tar.gz: ee0fa5c89c7cb7a30dd0a18fa63dc645673170d9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a324c37b240280be2de970a9f028095bb27cacf59bfc41c8408c509c19997933cfa90211953856c2840df9c9683e128c281b3ba33c8a2296d236cb1d97f920bc
|
7
|
+
data.tar.gz: a129c6547c71383840c78e5520d4ce544a483bea9eb5b05c09d7c1e87dfdc79b141afe0c73645e4f5b861adafd18230a341d095005cc1e455d63d0053e2b98d6
|
data/.gitignore
CHANGED
data/CHANGES.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
4.5.1 (Mar 23rd, 2018)
|
2
|
+
- Fix Forwardable load issue
|
3
|
+
- Fix native extension path issue
|
4
|
+
|
5
|
+
4.5.0 (Mar 2nd, 2018)
|
6
|
+
|
7
|
+
- Move MurmurHash3 implementation inside the gem
|
8
|
+
- Add native Java MurmurHash3 implementation -> now support JRuby
|
9
|
+
|
1
10
|
4.4.0 (Feb 5th, 2018)
|
2
11
|
- Add track API
|
3
12
|
|
data/NEWS
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
[ ![Codeship Status for splitio/ruby-client](https://app.codeship.com/projects/306c6b60-c164-0133-e179-16471d4e6045/status?branch=master)](https://app.codeship.com/projects/137510)
|
2
|
+
|
1
3
|
# Split Ruby SDK
|
2
4
|
|
3
5
|
This SDK is designed to work with [Split](https://www.split.io), the platform for controlled rollouts, serving features to your users via the Split feature flag to manage your complete customer experience.
|
data/Rakefile
CHANGED
@@ -1,4 +1,24 @@
|
|
1
|
-
require
|
2
|
-
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
Dir['tasks/**/*.rake'].each { |rake| load rake }
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
3
7
|
|
4
|
-
|
8
|
+
task :spec => :compile
|
9
|
+
case RUBY_PLATFORM
|
10
|
+
when 'java'
|
11
|
+
require 'rake/javaextensiontask'
|
12
|
+
Rake::JavaExtensionTask.new 'murmurhash' do |ext|
|
13
|
+
ext.lib_dir = 'lib/murmurhash'
|
14
|
+
ext.target_version = '1.7'
|
15
|
+
ext.source_version = '1.7'
|
16
|
+
end
|
17
|
+
else
|
18
|
+
require 'rake/extensiontask'
|
19
|
+
Rake::ExtensionTask.new 'murmurhash' do |ext|
|
20
|
+
ext.lib_dir = 'lib/murmurhash'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
task :default => :spec
|
@@ -0,0 +1,88 @@
|
|
1
|
+
/*
|
2
|
+
* MurmurHash3_x86_32 (C) Austin Appleby
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "murmurhash.h"
|
6
|
+
|
7
|
+
uint32_t
|
8
|
+
murmur_hash_process3_x86_32(const char * key, uint32_t len, uint32_t seed)
|
9
|
+
{
|
10
|
+
const uint8_t * data = (const uint8_t*)key;
|
11
|
+
const int nblocks = len / 4;
|
12
|
+
int i;
|
13
|
+
|
14
|
+
uint32_t h1 = seed;
|
15
|
+
|
16
|
+
const uint32_t c1 = 0xcc9e2d51;
|
17
|
+
const uint32_t c2 = 0x1b873593;
|
18
|
+
|
19
|
+
//----------
|
20
|
+
// body
|
21
|
+
|
22
|
+
const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
|
23
|
+
|
24
|
+
for(i = -nblocks; i; i++)
|
25
|
+
{
|
26
|
+
uint32_t k1 = getblock32(blocks,i);
|
27
|
+
|
28
|
+
k1 *= c1;
|
29
|
+
k1 = ROTL32(k1,15);
|
30
|
+
k1 *= c2;
|
31
|
+
|
32
|
+
h1 ^= k1;
|
33
|
+
h1 = ROTL32(h1,13);
|
34
|
+
h1 = h1*5+0xe6546b64;
|
35
|
+
}
|
36
|
+
|
37
|
+
//----------
|
38
|
+
// tail
|
39
|
+
|
40
|
+
const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
|
41
|
+
|
42
|
+
uint32_t k1 = 0;
|
43
|
+
|
44
|
+
switch(len & 3)
|
45
|
+
{
|
46
|
+
case 3: k1 ^= tail[2] << 16;
|
47
|
+
case 2: k1 ^= tail[1] << 8;
|
48
|
+
case 1: k1 ^= tail[0];
|
49
|
+
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
50
|
+
};
|
51
|
+
|
52
|
+
//----------
|
53
|
+
// finalization
|
54
|
+
|
55
|
+
h1 ^= len;
|
56
|
+
|
57
|
+
h1 = fmix32(h1);
|
58
|
+
|
59
|
+
return h1;
|
60
|
+
}
|
61
|
+
|
62
|
+
VALUE
|
63
|
+
murmur3_x86_32_finish(VALUE self)
|
64
|
+
{
|
65
|
+
uint8_t digest[4];
|
66
|
+
uint32_t h;
|
67
|
+
|
68
|
+
h = _murmur_finish32(self, murmur_hash_process3_x86_32);
|
69
|
+
assign_by_endian_32(digest, h);
|
70
|
+
return rb_str_new((const char*) digest, 4);
|
71
|
+
}
|
72
|
+
|
73
|
+
VALUE
|
74
|
+
murmur3_x86_32_s_digest(int argc, VALUE *argv, VALUE klass)
|
75
|
+
{
|
76
|
+
uint8_t digest[4];
|
77
|
+
uint32_t h;
|
78
|
+
|
79
|
+
h = _murmur_s_digest32(argc, argv, klass, murmur_hash_process3_x86_32);
|
80
|
+
assign_by_endian_32(digest, h);
|
81
|
+
return rb_str_new((const char*) digest, 4);
|
82
|
+
}
|
83
|
+
|
84
|
+
VALUE
|
85
|
+
murmur3_x86_32_s_rawdigest(int argc, VALUE *argv, VALUE klass)
|
86
|
+
{
|
87
|
+
return ULL2NUM(_murmur_s_digest32(argc, argv, klass, murmur_hash_process3_x86_32));
|
88
|
+
}
|
@@ -0,0 +1,251 @@
|
|
1
|
+
#include "murmurhash.h"
|
2
|
+
|
3
|
+
ID id_DEFAULT_SEED;
|
4
|
+
ID iv_seed;
|
5
|
+
ID iv_buffer;
|
6
|
+
|
7
|
+
|
8
|
+
inline uint32_t rotl32 ( uint32_t x, int8_t r )
|
9
|
+
{
|
10
|
+
return (x << r) | (x >> (32 - r));
|
11
|
+
}
|
12
|
+
inline uint64_t rotl64 ( uint64_t x, int8_t r )
|
13
|
+
{
|
14
|
+
return (x << r) | (x >> (64 - r));
|
15
|
+
}
|
16
|
+
|
17
|
+
FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
|
18
|
+
{
|
19
|
+
return p[i];
|
20
|
+
}
|
21
|
+
|
22
|
+
FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
|
23
|
+
{
|
24
|
+
return p[i];
|
25
|
+
}
|
26
|
+
|
27
|
+
FORCE_INLINE uint32_t fmix32 ( uint32_t h )
|
28
|
+
{
|
29
|
+
h ^= h >> 16;
|
30
|
+
h *= 0x85ebca6b;
|
31
|
+
h ^= h >> 13;
|
32
|
+
h *= 0xc2b2ae35;
|
33
|
+
h ^= h >> 16;
|
34
|
+
|
35
|
+
return h;
|
36
|
+
}
|
37
|
+
|
38
|
+
FORCE_INLINE uint64_t fmix64 ( uint64_t k )
|
39
|
+
{
|
40
|
+
k ^= k >> 33;
|
41
|
+
k *= BIG_CONSTANT(0xff51afd7ed558ccd);
|
42
|
+
k ^= k >> 33;
|
43
|
+
k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
|
44
|
+
k ^= k >> 33;
|
45
|
+
|
46
|
+
return k;
|
47
|
+
}
|
48
|
+
|
49
|
+
void
|
50
|
+
assign_by_endian_32(uint8_t *digest, uint32_t h)
|
51
|
+
{
|
52
|
+
if (BIGENDIAN_P()) {
|
53
|
+
digest[0] = h >> 24;
|
54
|
+
digest[1] = h >> 16;
|
55
|
+
digest[2] = h >> 8;
|
56
|
+
digest[3] = h;
|
57
|
+
}
|
58
|
+
else {
|
59
|
+
digest[3] = h >> 24;
|
60
|
+
digest[2] = h >> 16;
|
61
|
+
digest[1] = h >> 8;
|
62
|
+
digest[0] = h;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
void
|
67
|
+
assign_by_endian_64(uint8_t *digest, uint64_t h)
|
68
|
+
{
|
69
|
+
if (BIGENDIAN_P()) {
|
70
|
+
digest[0] = h >> 56;
|
71
|
+
digest[1] = h >> 48;
|
72
|
+
digest[2] = h >> 40;
|
73
|
+
digest[3] = h >> 32;
|
74
|
+
digest[4] = h >> 24;
|
75
|
+
digest[5] = h >> 16;
|
76
|
+
digest[6] = h >> 8;
|
77
|
+
digest[7] = h;
|
78
|
+
}
|
79
|
+
else {
|
80
|
+
digest[7] = h >> 56;
|
81
|
+
digest[6] = h >> 48;
|
82
|
+
digest[5] = h >> 40;
|
83
|
+
digest[4] = h >> 32;
|
84
|
+
digest[3] = h >> 24;
|
85
|
+
digest[2] = h >> 16;
|
86
|
+
digest[1] = h >> 8;
|
87
|
+
digest[0] = h;
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
void
|
92
|
+
assign_by_endian_128(uint8_t *digest, void *out)
|
93
|
+
{
|
94
|
+
int i;
|
95
|
+
|
96
|
+
if (BIGENDIAN_P()) {
|
97
|
+
for (i = 0; i < 4; i++) {
|
98
|
+
digest[(i*4) ] = ((uint32_t*)out)[i] >> 24;
|
99
|
+
digest[(i*4)+1] = ((uint32_t*)out)[i] >> 16;
|
100
|
+
digest[(i*4)+2] = ((uint32_t*)out)[i] >> 8;
|
101
|
+
digest[(i*4)+3] = ((uint32_t*)out)[i];
|
102
|
+
}
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
for (i = 0; i < 4; i++) {
|
106
|
+
digest[16-(i*4)-1] = ((uint32_t*)out)[i] >> 24;
|
107
|
+
digest[16-(i*4)-2] = ((uint32_t*)out)[i] >> 16;
|
108
|
+
digest[16-(i*4)-3] = ((uint32_t*)out)[i] >> 8;
|
109
|
+
digest[16-(i*4)-4] = ((uint32_t*)out)[i];
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
static uint32_t
|
115
|
+
rstring2uint32_t(VALUE str)
|
116
|
+
{
|
117
|
+
long len = RSTRING_LEN(str);
|
118
|
+
if (UINT32_MAX < len) {
|
119
|
+
rb_raise(rb_eRangeError, "String length=%ld will overflow from long to uint32_t", len);
|
120
|
+
}
|
121
|
+
return (uint32_t)len;
|
122
|
+
}
|
123
|
+
|
124
|
+
uint32_t
|
125
|
+
_murmur_finish32(VALUE self, uint32_t (*process)(const char*, uint32_t, uint32_t))
|
126
|
+
{
|
127
|
+
const char *seed = RSTRING_PTR(rb_ivar_get(self, iv_seed));
|
128
|
+
VALUE buffer = rb_ivar_get(self, iv_buffer);
|
129
|
+
return process(RSTRING_PTR(buffer), rstring2uint32_t(buffer), *(uint32_t*)seed);
|
130
|
+
}
|
131
|
+
|
132
|
+
uint64_t
|
133
|
+
_murmur_finish64(VALUE self, uint64_t (*process)(const char*, uint32_t, uint64_t))
|
134
|
+
{
|
135
|
+
const char *seed = RSTRING_PTR(rb_ivar_get(self, iv_seed));
|
136
|
+
VALUE buffer = rb_ivar_get(self, iv_buffer);
|
137
|
+
return process(RSTRING_PTR(buffer), rstring2uint32_t(buffer), *(uint64_t*)seed);
|
138
|
+
}
|
139
|
+
|
140
|
+
void
|
141
|
+
_murmur_finish128(VALUE self, void *out, void (*process)(const char*, uint32_t, uint32_t, void*))
|
142
|
+
{
|
143
|
+
const char *seed = RSTRING_PTR(rb_ivar_get(self, iv_seed));
|
144
|
+
VALUE buffer = rb_ivar_get(self, iv_buffer);
|
145
|
+
process(RSTRING_PTR(buffer), rstring2uint32_t(buffer), *(uint32_t*)seed, out);
|
146
|
+
}
|
147
|
+
|
148
|
+
uint32_t
|
149
|
+
_murmur_s_digest32(int argc, VALUE *argv, VALUE klass, uint32_t (*process)(const char *, uint32_t, uint32_t))
|
150
|
+
{
|
151
|
+
VALUE str;
|
152
|
+
const char *seed;
|
153
|
+
|
154
|
+
if (argc < 1)
|
155
|
+
rb_raise(rb_eArgError, "no data given");
|
156
|
+
|
157
|
+
str = *argv;
|
158
|
+
|
159
|
+
StringValue(str);
|
160
|
+
|
161
|
+
if (1 < argc) {
|
162
|
+
StringValue(argv[1]);
|
163
|
+
if (RSTRING_LEN(argv[1]) != 4) {
|
164
|
+
rb_raise(rb_eArgError, "seed string should be 4 length");
|
165
|
+
}
|
166
|
+
seed = RSTRING_PTR(argv[1]);
|
167
|
+
} else {
|
168
|
+
seed = RSTRING_PTR(rb_const_get(klass, id_DEFAULT_SEED));
|
169
|
+
}
|
170
|
+
|
171
|
+
return process(RSTRING_PTR(str), rstring2uint32_t(str), *(uint32_t*)seed);
|
172
|
+
}
|
173
|
+
|
174
|
+
uint64_t
|
175
|
+
_murmur_s_digest64(int argc, VALUE *argv, VALUE klass, uint64_t (*process)(const char *, uint32_t, uint64_t))
|
176
|
+
{
|
177
|
+
VALUE str;
|
178
|
+
const char *seed;
|
179
|
+
|
180
|
+
if (argc < 1)
|
181
|
+
rb_raise(rb_eArgError, "no data given");
|
182
|
+
|
183
|
+
str = *argv;
|
184
|
+
|
185
|
+
StringValue(str);
|
186
|
+
|
187
|
+
if (1 < argc) {
|
188
|
+
StringValue(argv[1]);
|
189
|
+
if (RSTRING_LEN(argv[1]) != 8) {
|
190
|
+
rb_raise(rb_eArgError, "seed string should be 8 length");
|
191
|
+
}
|
192
|
+
seed = RSTRING_PTR(argv[1]);
|
193
|
+
} else {
|
194
|
+
seed = RSTRING_PTR(rb_const_get(klass, id_DEFAULT_SEED));
|
195
|
+
}
|
196
|
+
|
197
|
+
return process(RSTRING_PTR(str), rstring2uint32_t(str), *(uint64_t*)seed);
|
198
|
+
}
|
199
|
+
|
200
|
+
void
|
201
|
+
_murmur_s_digest128(int argc, VALUE *argv, VALUE klass, void *out, void (*process)(const char *, uint32_t, uint32_t, void *))
|
202
|
+
{
|
203
|
+
VALUE str;
|
204
|
+
const char *seed;
|
205
|
+
int seed_length = 4;
|
206
|
+
|
207
|
+
if (argc < 1)
|
208
|
+
rb_raise(rb_eArgError, "no data given");
|
209
|
+
|
210
|
+
str = *argv;
|
211
|
+
|
212
|
+
StringValue(str);
|
213
|
+
|
214
|
+
if (1 < argc) {
|
215
|
+
StringValue(argv[1]);
|
216
|
+
if (RSTRING_LEN(argv[1]) != seed_length) {
|
217
|
+
rb_raise(rb_eArgError, "seed string should be %d length", seed_length);
|
218
|
+
}
|
219
|
+
seed = RSTRING_PTR(argv[1]);
|
220
|
+
} else {
|
221
|
+
seed = RSTRING_PTR(rb_const_get(klass, id_DEFAULT_SEED));
|
222
|
+
}
|
223
|
+
|
224
|
+
process(RSTRING_PTR(str), rstring2uint32_t(str), *(uint32_t*)seed, out);
|
225
|
+
}
|
226
|
+
|
227
|
+
|
228
|
+
void
|
229
|
+
Init_murmurhash(void)
|
230
|
+
{
|
231
|
+
VALUE cDigest_MurmurHash1,
|
232
|
+
cDigest_MurmurHash2,
|
233
|
+
cDigest_MurmurHash2A,
|
234
|
+
cDigest_MurmurHash64A,
|
235
|
+
cDigest_MurmurHash64B,
|
236
|
+
cDigest_MurmurHashNeutral2,
|
237
|
+
cDigest_MurmurHashAligned2,
|
238
|
+
cDigest_MurmurHash3_x86_32,
|
239
|
+
cDigest_MurmurHash3_x86_128,
|
240
|
+
cDigest_MurmurHash3_x64_128;
|
241
|
+
|
242
|
+
id_DEFAULT_SEED = rb_intern("DEFAULT_SEED");
|
243
|
+
iv_seed = rb_intern("@seed");
|
244
|
+
iv_buffer = rb_intern("@buffer");
|
245
|
+
|
246
|
+
|
247
|
+
cDigest_MurmurHash3_x86_32 = rb_path2class("Digest::MurmurHashMRI3_x86_32");
|
248
|
+
rb_define_singleton_method(cDigest_MurmurHash3_x86_32, "digest", murmur3_x86_32_s_digest, -1);
|
249
|
+
rb_define_singleton_method(cDigest_MurmurHash3_x86_32, "rawdigest", murmur3_x86_32_s_rawdigest, -1);
|
250
|
+
rb_define_private_method(cDigest_MurmurHash3_x86_32, "finish", murmur3_x86_32_finish, 0);
|
251
|
+
}
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#ifndef MURMURHASH_INCLUDED
|
2
|
+
# define MURMURHASH_INCLUDED
|
3
|
+
|
4
|
+
#include "ruby.h"
|
5
|
+
|
6
|
+
// Microsoft Visual Studio
|
7
|
+
|
8
|
+
#if defined(_MSC_VER)
|
9
|
+
#define FORCE_INLINE __forceinline
|
10
|
+
#include <stdlib.h>
|
11
|
+
#define ROTL32(x,y) _rotl(x,y)
|
12
|
+
#define ROTL64(x,y) _rotl64(x,y)
|
13
|
+
#define BIG_CONSTANT(x) (x)
|
14
|
+
#else // defined(_MSC_VER)
|
15
|
+
#define FORCE_INLINE inline __attribute__((always_inline))
|
16
|
+
#define ROTL32(x,y) rotl32(x,y)
|
17
|
+
#define ROTL64(x,y) rotl64(x,y)
|
18
|
+
#define BIG_CONSTANT(x) (x##LLU)
|
19
|
+
#endif // !defined(_MSC_VER)
|
20
|
+
|
21
|
+
#ifdef DYNAMIC_ENDIAN
|
22
|
+
/* for universal binary of NEXTSTEP and MacOS X */
|
23
|
+
/* useless since autoconf 2.63? */
|
24
|
+
static int
|
25
|
+
is_bigendian(void)
|
26
|
+
{
|
27
|
+
static int init = 0;
|
28
|
+
static int endian_value;
|
29
|
+
char *p;
|
30
|
+
|
31
|
+
if (init) return endian_value;
|
32
|
+
init = 1;
|
33
|
+
p = (char*)&init;
|
34
|
+
return endian_value = p[0] ? 0 : 1;
|
35
|
+
}
|
36
|
+
# define BIGENDIAN_P() (is_bigendian())
|
37
|
+
#elif defined(WORDS_BIGENDIAN)
|
38
|
+
# define BIGENDIAN_P() 1
|
39
|
+
#else
|
40
|
+
# define BIGENDIAN_P() 0
|
41
|
+
#endif
|
42
|
+
|
43
|
+
#define MURMURHASH_MAGIC 0x5bd1e995
|
44
|
+
#define MURMURHASH_MAGIC64A BIG_CONSTANT(0xc6a4a7935bd1e995)
|
45
|
+
|
46
|
+
void assign_by_endian_32(uint8_t *digest, uint32_t h);
|
47
|
+
void assign_by_endian_64(uint8_t *digest, uint64_t h);
|
48
|
+
void assign_by_endian_128(uint8_t*, void*);
|
49
|
+
|
50
|
+
uint32_t rotl32(uint32_t, int8_t);
|
51
|
+
uint64_t rotl64(uint64_t, int8_t);
|
52
|
+
uint32_t getblock32(const uint32_t*, int);
|
53
|
+
uint64_t getblock64(const uint64_t*, int);
|
54
|
+
uint32_t fmix32(uint32_t);
|
55
|
+
uint64_t fmix64(uint64_t);
|
56
|
+
uint32_t _murmur_finish32(VALUE, uint32_t (*)(const char*, uint32_t, uint32_t));
|
57
|
+
uint64_t _murmur_finish64(VALUE, uint64_t (*)(const char*, uint32_t, uint64_t));
|
58
|
+
void _murmur_finish128(VALUE, void*, void (*)(const char*, uint32_t, uint32_t, void*));
|
59
|
+
uint32_t _murmur_s_digest32(int, VALUE*, VALUE, uint32_t (*)(const char*, uint32_t, uint32_t));
|
60
|
+
uint64_t _murmur_s_digest64(int, VALUE*, VALUE, uint64_t (*)(const char*, uint32_t, uint64_t));
|
61
|
+
void _murmur_s_digest128(int, VALUE*, VALUE, void*, void (*)(const char*, uint32_t, uint32_t, void*));
|
62
|
+
|
63
|
+
VALUE murmur1_finish(VALUE);
|
64
|
+
VALUE murmur1_s_digest(int, VALUE*, VALUE);
|
65
|
+
VALUE murmur1_s_rawdigest(int, VALUE*, VALUE);
|
66
|
+
VALUE murmur2_finish(VALUE);
|
67
|
+
VALUE murmur2_s_digest(int, VALUE*, VALUE);
|
68
|
+
VALUE murmur2_s_rawdigest(int, VALUE*, VALUE);
|
69
|
+
VALUE murmur2a_finish(VALUE);
|
70
|
+
VALUE murmur2a_s_digest(int, VALUE*, VALUE);
|
71
|
+
VALUE murmur2a_s_rawdigest(int, VALUE*, VALUE);
|
72
|
+
VALUE murmur64a_finish(VALUE);
|
73
|
+
VALUE murmur64a_s_digest(int, VALUE*, VALUE);
|
74
|
+
VALUE murmur64a_s_rawdigest(int, VALUE*, VALUE);
|
75
|
+
VALUE murmur64b_finish(VALUE);
|
76
|
+
VALUE murmur64b_s_digest(int, VALUE*, VALUE);
|
77
|
+
VALUE murmur64b_s_rawdigest(int, VALUE*, VALUE);
|
78
|
+
VALUE murmur_neutral2_finish(VALUE);
|
79
|
+
VALUE murmur_neutral2_s_digest(int, VALUE*, VALUE);
|
80
|
+
VALUE murmur_neutral2_s_rawdigest(int, VALUE*, VALUE);
|
81
|
+
VALUE murmur_aligned2_finish(VALUE);
|
82
|
+
VALUE murmur_aligned2_s_digest(int, VALUE*, VALUE);
|
83
|
+
VALUE murmur_aligned2_s_rawdigest(int, VALUE*, VALUE);
|
84
|
+
VALUE murmur3_x86_32_finish(VALUE);
|
85
|
+
VALUE murmur3_x86_32_s_digest(int, VALUE*, VALUE);
|
86
|
+
VALUE murmur3_x86_32_s_rawdigest(int, VALUE*, VALUE);
|
87
|
+
VALUE murmur3_x86_128_finish(VALUE);
|
88
|
+
VALUE murmur3_x86_128_s_digest(int, VALUE*, VALUE);
|
89
|
+
VALUE murmur3_x86_128_s_rawdigest(int, VALUE*, VALUE);
|
90
|
+
VALUE murmur3_x64_128_finish(VALUE);
|
91
|
+
VALUE murmur3_x64_128_s_digest(int, VALUE*, VALUE);
|
92
|
+
VALUE murmur3_x64_128_s_rawdigest(int, VALUE*, VALUE);
|
93
|
+
|
94
|
+
#endif /* ifndef MURMURHASH_INCLUDED */
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Digest
|
2
|
+
ds = Struct.new(:digest_length, :seed_length)
|
3
|
+
s1 = ds.new(4, 4)
|
4
|
+
s2 = ds.new(8, 8)
|
5
|
+
s3 = ds.new(16, 4)
|
6
|
+
{
|
7
|
+
'1' => s1,
|
8
|
+
'2' => s1,
|
9
|
+
'2A' => s1,
|
10
|
+
'64A' => s2,
|
11
|
+
'64B' => s2,
|
12
|
+
'Aligned2' => s1,
|
13
|
+
'Neutral2' => s1,
|
14
|
+
'3_x86_32' => s1,
|
15
|
+
'3_x86_128' => s3,
|
16
|
+
'3_x64_128' => s3,
|
17
|
+
}.each do |name, s|
|
18
|
+
class_eval %Q{
|
19
|
+
class MurmurHashMRI#{name} < Digest::Class
|
20
|
+
DEFAULT_SEED = "#{"\x00" * s.seed_length}".b
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
@buffer = ""
|
24
|
+
@seed = DEFAULT_SEED
|
25
|
+
end
|
26
|
+
|
27
|
+
def update(str)
|
28
|
+
@buffer << str
|
29
|
+
self
|
30
|
+
end
|
31
|
+
alias << update
|
32
|
+
|
33
|
+
def reset
|
34
|
+
@buffer.clear
|
35
|
+
@seed = DEFAULT_SEED
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def seed
|
40
|
+
@seed
|
41
|
+
end
|
42
|
+
|
43
|
+
def seed=(s)
|
44
|
+
raise ArgumentError, "seed string should be #{s.seed_length} length" if #{s.seed_length} != s.length
|
45
|
+
@seed = s
|
46
|
+
end
|
47
|
+
|
48
|
+
def digest_length
|
49
|
+
#{s.digest_length}
|
50
|
+
end
|
51
|
+
|
52
|
+
def block_length
|
53
|
+
0
|
54
|
+
end
|
55
|
+
end
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
Binary file
|
@@ -1,118 +1,123 @@
|
|
1
|
-
require 'digest/murmurhash'
|
2
|
-
|
3
1
|
module SplitIoClient
|
4
2
|
# Misc class in charge of providing hash functions and
|
5
3
|
# determination of treatment based on concept of buckets
|
6
4
|
# based on provided key
|
7
5
|
#
|
8
6
|
class Splitter < NoMethodError
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# @return [boolean] true if partition is 100% false otherwise
|
16
|
-
def hundred_percent_one_treatment?(partitions)
|
17
|
-
(partitions.size != 1) ? false : (partitions.first.size == 100)
|
7
|
+
def initialize
|
8
|
+
@murmur_hash = case RUBY_PLATFORM
|
9
|
+
when 'java'
|
10
|
+
Proc.new { |key, seed| Java::MurmurHash3.murmurhash3_x86_32(key, seed) }
|
11
|
+
else
|
12
|
+
Proc.new { |key, seed| Digest::MurmurHashMRI3_x86_32.rawdigest(key, [seed].pack('L')) }
|
18
13
|
end
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Checks if the partiotion size is 100%
|
18
|
+
#
|
19
|
+
# @param partitions [object] array of partitions
|
20
|
+
#
|
21
|
+
# @return [boolean] true if partition is 100% false otherwise
|
22
|
+
def hundred_percent_one_treatment?(partitions)
|
23
|
+
(partitions.size != 1) ? false : (partitions.first.size == 100)
|
24
|
+
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
|
35
|
-
if hundred_percent_one_treatment?(partitions)
|
36
|
-
return (partitions.first).treatment
|
37
|
-
end
|
38
|
-
|
39
|
-
return get_treatment_for_key(bucket(count_hash(id, seed, legacy_algo)), partitions)
|
26
|
+
#
|
27
|
+
# gets the appropriate treatment based on id, seed and partition value
|
28
|
+
#
|
29
|
+
# @param id [string] user key
|
30
|
+
# @param seed [number] seed for the user key
|
31
|
+
# @param partitions [object] array of partitions
|
32
|
+
#
|
33
|
+
# @return traetment [object] treatment value
|
34
|
+
def get_treatment(id, seed, partitions, legacy_algo)
|
35
|
+
legacy = [1, nil].include?(legacy_algo)
|
36
|
+
|
37
|
+
if partitions.empty?
|
38
|
+
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
40
39
|
end
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
# @param key [String] user key
|
45
|
-
# @param seed [Fixnum] seed for the user key
|
46
|
-
#
|
47
|
-
# @return hash [String] hash value
|
48
|
-
def count_hash(key, seed, legacy)
|
49
|
-
legacy ? legacy_hash(key, seed) : murmur_hash(key, seed)
|
41
|
+
if hundred_percent_one_treatment?(partitions)
|
42
|
+
return (partitions.first).treatment
|
50
43
|
end
|
51
44
|
|
52
|
-
|
53
|
-
|
54
|
-
end
|
45
|
+
return get_treatment_for_key(bucket(count_hash(id, seed, legacy_algo)), partitions)
|
46
|
+
end
|
55
47
|
|
56
|
-
|
57
|
-
|
48
|
+
# returns a hash value for the give key, seed pair
|
49
|
+
#
|
50
|
+
# @param key [String] user key
|
51
|
+
# @param seed [Fixnum] seed for the user key
|
52
|
+
#
|
53
|
+
# @return hash [String] hash value
|
54
|
+
def count_hash(key, seed, legacy)
|
55
|
+
legacy ? legacy_hash(key, seed) : murmur_hash(key, seed)
|
56
|
+
end
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
def murmur_hash(key, seed)
|
59
|
+
@murmur_hash.call(key, seed)
|
60
|
+
end
|
62
61
|
|
63
|
-
|
64
|
-
|
62
|
+
def legacy_hash(key, seed)
|
63
|
+
h = 0
|
65
64
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
# @param number [number] ruby number value
|
70
|
-
#
|
71
|
-
# @return [int] returns the int 32 value of the provided number
|
72
|
-
def to_int32(number)
|
73
|
-
begin
|
74
|
-
sign = number < 0 ? -1 : 1
|
75
|
-
abs = number.abs
|
76
|
-
return 0 if abs == 0 || abs == Float::INFINITY
|
77
|
-
rescue
|
78
|
-
return 0
|
79
|
-
end
|
65
|
+
for i in 0..key.length-1
|
66
|
+
h = to_int32(31 * h + key[i].ord)
|
67
|
+
end
|
80
68
|
|
81
|
-
|
82
|
-
|
69
|
+
h^seed
|
70
|
+
end
|
83
71
|
|
84
|
-
|
85
|
-
|
72
|
+
#
|
73
|
+
# misc method to convert ruby number to int 32 since overflow is handled different to java
|
74
|
+
#
|
75
|
+
# @param number [number] ruby number value
|
76
|
+
#
|
77
|
+
# @return [int] returns the int 32 value of the provided number
|
78
|
+
def to_int32(number)
|
79
|
+
begin
|
80
|
+
sign = number < 0 ? -1 : 1
|
81
|
+
abs = number.abs
|
82
|
+
return 0 if abs == 0 || abs == Float::INFINITY
|
83
|
+
rescue
|
84
|
+
return 0
|
86
85
|
end
|
87
86
|
|
88
|
-
|
89
|
-
|
90
|
-
#
|
91
|
-
# @param bucket [number] bucket value
|
92
|
-
# @param parittions [object] array of partitions
|
93
|
-
#
|
94
|
-
# @return treatment [treatment] treatment value for this bucket and partitions
|
95
|
-
def get_treatment_for_key(bucket, partitions)
|
96
|
-
buckets_covered_thus_far = 0
|
97
|
-
partitions.each do |p|
|
98
|
-
unless p.is_empty?
|
99
|
-
buckets_covered_thus_far += p.size
|
100
|
-
return p.treatment if buckets_covered_thus_far >= bucket
|
101
|
-
end
|
102
|
-
end
|
87
|
+
pos_int = sign * abs.floor
|
88
|
+
int_32bit = pos_int % 2**32
|
103
89
|
|
104
|
-
|
105
|
-
|
90
|
+
return int_32bit - 2**32 if int_32bit >= 2**31
|
91
|
+
int_32bit
|
92
|
+
end
|
106
93
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
94
|
+
#
|
95
|
+
# returns the treatment for a bucket given the partitions
|
96
|
+
#
|
97
|
+
# @param bucket [number] bucket value
|
98
|
+
# @param parittions [object] array of partitions
|
99
|
+
#
|
100
|
+
# @return treatment [treatment] treatment value for this bucket and partitions
|
101
|
+
def get_treatment_for_key(bucket, partitions)
|
102
|
+
buckets_covered_thus_far = 0
|
103
|
+
partitions.each do |p|
|
104
|
+
unless p.is_empty?
|
105
|
+
buckets_covered_thus_far += p.size
|
106
|
+
return p.treatment if buckets_covered_thus_far >= bucket
|
107
|
+
end
|
115
108
|
end
|
109
|
+
|
110
|
+
return SplitIoClient::Engine::Models::Treatment::CONTROL
|
111
|
+
end
|
112
|
+
|
113
|
+
#
|
114
|
+
# returns bucket value for the given hash value
|
115
|
+
#
|
116
|
+
# @param hash_value [string] hash value
|
117
|
+
#
|
118
|
+
# @return bucket [number] bucket number
|
119
|
+
def bucket(hash_value)
|
120
|
+
(hash_value.abs % 100) + 1
|
116
121
|
end
|
117
122
|
end
|
118
123
|
end
|
@@ -40,6 +40,7 @@ module SplitIoClient
|
|
40
40
|
in_rollout = false
|
41
41
|
key = keys[:bucketing_key] ? keys[:bucketing_key] : keys[:matching_key]
|
42
42
|
legacy_algo = (split[:algo] == 1 || split[:algo] == nil) ? true : false
|
43
|
+
splitter = Splitter.new
|
43
44
|
|
44
45
|
split[:conditions].each do |c|
|
45
46
|
condition = SplitIoClient::Condition.new(c)
|
@@ -48,7 +49,7 @@ module SplitIoClient
|
|
48
49
|
|
49
50
|
if !in_rollout && condition.type == SplitIoClient::Condition::TYPE_ROLLOUT
|
50
51
|
if split[:trafficAllocation] < 100
|
51
|
-
bucket =
|
52
|
+
bucket = splitter.bucket(splitter.count_hash(key, split[:trafficAllocationSeed].to_i, legacy_algo))
|
52
53
|
|
53
54
|
if bucket >= split[:trafficAllocation]
|
54
55
|
return treatment_hash(Models::Label::NOT_IN_SPLIT, split[:defaultTreatment], split[:changeNumber])
|
@@ -67,7 +68,7 @@ module SplitIoClient
|
|
67
68
|
|
68
69
|
next unless condition_matched
|
69
70
|
|
70
|
-
result =
|
71
|
+
result = splitter.get_treatment(key, split[:seed], condition.partitions, split[:algo])
|
71
72
|
|
72
73
|
if result.nil?
|
73
74
|
return treatment_hash(Models::Label::NO_RULE_MATCHED, split[:defaultTreatment], split[:changeNumber])
|
data/lib/splitclient-rb.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
1
3
|
require 'splitclient-rb/version'
|
2
4
|
|
3
5
|
require 'splitclient-rb/exceptions/impressions_shutdown_exception'
|
@@ -78,6 +80,9 @@ require 'splitclient-rb/engine/models/label'
|
|
78
80
|
require 'splitclient-rb/engine/models/treatment'
|
79
81
|
require 'splitclient-rb/utilitites'
|
80
82
|
|
83
|
+
# C extension
|
84
|
+
require 'murmurhash/murmurhash_mri'
|
85
|
+
|
81
86
|
module SplitIoClient
|
82
87
|
def self.root
|
83
88
|
File.dirname(__dir__)
|
data/splitclient-rb.gemspec
CHANGED
@@ -14,18 +14,30 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = "https://github.com/splitio/ruby-client"
|
15
15
|
spec.license = "Apache 2.0"
|
16
16
|
|
17
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|features|ext)/}) }
|
18
|
+
|
18
19
|
spec.bindir = "exe"
|
19
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
21
|
spec.require_paths = ["lib"]
|
21
22
|
|
23
|
+
if defined?(JRUBY_VERSION)
|
24
|
+
spec.platform = 'java'
|
25
|
+
spec.files << 'ext/murmurhash/MurmurHash3.java'
|
26
|
+
else
|
27
|
+
spec.files.concat(%w(
|
28
|
+
ext/murmurhash/3_x86_32.c
|
29
|
+
ext/murmurhash/extconf.rb
|
30
|
+
ext/murmurhash/murmurhash.c
|
31
|
+
ext/murmurhash/murmurhash.h)
|
32
|
+
)
|
33
|
+
spec.extensions = ["ext/murmurhash/extconf.rb"]
|
34
|
+
end
|
35
|
+
|
22
36
|
spec.add_development_dependency "bundler", "~> 1.11"
|
23
37
|
spec.add_development_dependency "rake", "~> 10.0"
|
38
|
+
spec.add_development_dependency "rake-compiler"
|
24
39
|
spec.add_development_dependency "rspec"
|
25
40
|
spec.add_development_dependency "webmock"
|
26
|
-
spec.add_development_dependency "byebug"
|
27
|
-
spec.add_development_dependency "pry"
|
28
|
-
spec.add_development_dependency "pry-byebug"
|
29
41
|
spec.add_development_dependency "simplecov"
|
30
42
|
spec.add_development_dependency "allocation_stats"
|
31
43
|
|
@@ -35,5 +47,4 @@ Gem::Specification.new do |spec|
|
|
35
47
|
spec.add_runtime_dependency "faraday", ">= 0.8"
|
36
48
|
spec.add_runtime_dependency "net-http-persistent", "~> 2.9"
|
37
49
|
spec.add_runtime_dependency "redis", ">= 3.2"
|
38
|
-
spec.add_runtime_dependency "digest-murmurhash", ">= 1.1"
|
39
50
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: splitclient-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.5.1.pre.dev
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Split Software
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,21 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '10.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: webmock
|
42
|
+
name: rake-compiler
|
57
43
|
requirement: !ruby/object:Gem::Requirement
|
58
44
|
requirements:
|
59
45
|
- - ">="
|
@@ -67,21 +53,7 @@ dependencies:
|
|
67
53
|
- !ruby/object:Gem::Version
|
68
54
|
version: '0'
|
69
55
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
72
|
-
requirements:
|
73
|
-
- - ">="
|
74
|
-
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
76
|
-
type: :development
|
77
|
-
prerelease: false
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
79
|
-
requirements:
|
80
|
-
- - ">="
|
81
|
-
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: pry
|
56
|
+
name: rspec
|
85
57
|
requirement: !ruby/object:Gem::Requirement
|
86
58
|
requirements:
|
87
59
|
- - ">="
|
@@ -95,7 +67,7 @@ dependencies:
|
|
95
67
|
- !ruby/object:Gem::Version
|
96
68
|
version: '0'
|
97
69
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
70
|
+
name: webmock
|
99
71
|
requirement: !ruby/object:Gem::Requirement
|
100
72
|
requirements:
|
101
73
|
- - ">="
|
@@ -220,26 +192,13 @@ dependencies:
|
|
220
192
|
- - ">="
|
221
193
|
- !ruby/object:Gem::Version
|
222
194
|
version: '3.2'
|
223
|
-
- !ruby/object:Gem::Dependency
|
224
|
-
name: digest-murmurhash
|
225
|
-
requirement: !ruby/object:Gem::Requirement
|
226
|
-
requirements:
|
227
|
-
- - ">="
|
228
|
-
- !ruby/object:Gem::Version
|
229
|
-
version: '1.1'
|
230
|
-
type: :runtime
|
231
|
-
prerelease: false
|
232
|
-
version_requirements: !ruby/object:Gem::Requirement
|
233
|
-
requirements:
|
234
|
-
- - ">="
|
235
|
-
- !ruby/object:Gem::Version
|
236
|
-
version: '1.1'
|
237
195
|
description: Ruby client for using split SDK.
|
238
196
|
email:
|
239
197
|
- pato@split.io
|
240
198
|
executables:
|
241
199
|
- splitio
|
242
|
-
extensions:
|
200
|
+
extensions:
|
201
|
+
- ext/murmurhash/extconf.rb
|
243
202
|
extra_rdoc_files: []
|
244
203
|
files:
|
245
204
|
- ".gitignore"
|
@@ -250,8 +209,14 @@ files:
|
|
250
209
|
- NEWS
|
251
210
|
- README.md
|
252
211
|
- Rakefile
|
253
|
-
- console
|
254
212
|
- exe/splitio
|
213
|
+
- ext/murmurhash/3_x86_32.c
|
214
|
+
- ext/murmurhash/extconf.rb
|
215
|
+
- ext/murmurhash/murmurhash.c
|
216
|
+
- ext/murmurhash/murmurhash.h
|
217
|
+
- lib/murmurhash/base.rb
|
218
|
+
- lib/murmurhash/murmurhash.jar
|
219
|
+
- lib/murmurhash/murmurhash_mri.rb
|
255
220
|
- lib/splitclient-rb.rb
|
256
221
|
- lib/splitclient-rb/cache/adapters/memory_adapter.rb
|
257
222
|
- lib/splitclient-rb/cache/adapters/memory_adapters/map_adapter.rb
|
@@ -328,12 +293,10 @@ files:
|
|
328
293
|
- lib/splitclient-rb/split_factory_builder.rb
|
329
294
|
- lib/splitclient-rb/utilitites.rb
|
330
295
|
- lib/splitclient-rb/version.rb
|
331
|
-
- runTests
|
332
296
|
- splitclient-rb.gemspec
|
333
297
|
- splitio.yml.example
|
334
298
|
- tasks/benchmark_get_treatment.rake
|
335
|
-
- tasks/
|
336
|
-
- tasks/console.rake
|
299
|
+
- tasks/irb.rake
|
337
300
|
- tasks/rspec.rake
|
338
301
|
homepage: https://github.com/splitio/ruby-client
|
339
302
|
licenses:
|
@@ -350,12 +313,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
350
313
|
version: '0'
|
351
314
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
352
315
|
requirements:
|
353
|
-
- - "
|
316
|
+
- - ">"
|
354
317
|
- !ruby/object:Gem::Version
|
355
|
-
version:
|
318
|
+
version: 1.3.1
|
356
319
|
requirements: []
|
357
320
|
rubyforge_project:
|
358
|
-
rubygems_version: 2.
|
321
|
+
rubygems_version: 2.6.8
|
359
322
|
signing_key:
|
360
323
|
specification_version: 4
|
361
324
|
summary: Ruby client for split SDK.
|
data/console
DELETED
data/runTests
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'benchmark'
|
2
|
-
require 'digest/murmurhash'
|
3
|
-
|
4
|
-
desc 'Benchmark murmur32 hashing algorithm'
|
5
|
-
|
6
|
-
task :benchmark_hashing_algorithm do
|
7
|
-
iterations = 200_000
|
8
|
-
key = SecureRandom.uuid
|
9
|
-
|
10
|
-
Benchmark.bmbm do |x|
|
11
|
-
x.report('MurmurHash1') do
|
12
|
-
iterations.times { Digest::MurmurHash1.rawdigest(key) }
|
13
|
-
end
|
14
|
-
|
15
|
-
x.report('MurmurHash2') do
|
16
|
-
iterations.times { Digest::MurmurHash2.rawdigest(key) }
|
17
|
-
end
|
18
|
-
|
19
|
-
x.report('MurmurHash2A') do
|
20
|
-
iterations.times { Digest::MurmurHash2A.rawdigest(key) }
|
21
|
-
end
|
22
|
-
|
23
|
-
x.report('LegacyHash') do
|
24
|
-
iterations.times { legacy_hash(key, 123) }
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def legacy_hash(key, seed)
|
30
|
-
h = 0
|
31
|
-
for i in 0..key.length-1
|
32
|
-
h = to_int32(31 * h + key[i].ord)
|
33
|
-
end
|
34
|
-
h^seed
|
35
|
-
end
|
36
|
-
|
37
|
-
def to_int32(number)
|
38
|
-
begin
|
39
|
-
sign = number < 0 ? -1 : 1
|
40
|
-
abs = number.abs
|
41
|
-
return 0 if abs == 0 || abs == Float::INFINITY
|
42
|
-
rescue
|
43
|
-
return 0
|
44
|
-
end
|
45
|
-
|
46
|
-
pos_int = sign * abs.floor
|
47
|
-
int_32bit = pos_int % 2**32
|
48
|
-
|
49
|
-
return int_32bit - 2**32 if int_32bit >= 2**31
|
50
|
-
int_32bit
|
51
|
-
end
|