splitclient-rb 4.4.0 → 4.5.1.pre.dev
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/.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
|
+
[ ](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
|