Last active
December 16, 2015 06:19
-
-
Save lpinca/5390693 to your computer and use it in GitHub Desktop.
SRANDMEMBER lacks randomness
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Module dependencies. | |
*/ | |
var crypto = require('crypto') | |
, rrange = 4294967296; | |
/** | |
* Return an integer, pseudo-random number in the range [0, 2^32). | |
*/ | |
var nextInt = function() { | |
return crypto.randomBytes(4).readUInt32BE(0); | |
}; | |
/** | |
* Return a floating-point, pseudo-random number in the range [0, 1). | |
*/ | |
var rand = function() { | |
return nextInt() / rrange; | |
}; | |
/** | |
* Return an integer, pseudo-random number in the range [0, max). | |
*/ | |
var randInt = function(max) { | |
return Math.floor(rand() * max); | |
}; | |
exports.randInt = randInt; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SRANDMEMBER results | |
=================== | |
least_extracted: {elem: 14, count: 35} most_extracted: {elem: 99, count: 65} mean_value: 50 std_dev: 6.989992846920518 | |
least_extracted: {elem: 38, count: 34} most_extracted: {elem: 27, count: 72} mean_value: 50 std_dev: 7.135825109964509 | |
least_extracted: {elem: 58, count: 32} most_extracted: {elem: 0, count: 69} mean_value: 50 std_dev: 7.173562573784381 | |
least_extracted: {elem: 0, count: 37} most_extracted: {elem: 68, count: 66} mean_value: 50 std_dev: 6.619667665374147 | |
least_extracted: {elem: 88, count: 36} most_extracted: {elem: 31, count: 71} mean_value: 50 std_dev: 6.592419889539804 | |
least_extracted: {elem: 98, count: 35} most_extracted: {elem: 19, count: 71} mean_value: 50 std_dev: 7.2 | |
least_extracted: {elem: 78, count: 28} most_extracted: {elem: 5, count: 65} mean_value: 50 std_dev: 7.67984374841051 | |
least_extracted: {elem: 39, count: 34} most_extracted: {elem: 8, count: 67} mean_value: 50 std_dev: 6.685805860178712 | |
least_extracted: {elem: 62, count: 32} most_extracted: {elem: 0, count: 66} mean_value: 50 std_dev: 6.777905281132217 | |
least_extracted: {elem: 57, count: 34} most_extracted: {elem: 31, count: 65} mean_value: 50 std_dev: 6.606057825965498 | |
least_extracted: {elem: 87, count: 35} most_extracted: {elem: 53, count: 68} mean_value: 50 std_dev: 6.871681017043792 | |
least_extracted: {elem: 89, count: 35} most_extracted: {elem: 40, count: 68} mean_value: 50 std_dev: 6.37808748764079 | |
least_extracted: {elem: 31, count: 38} most_extracted: {elem: 46, count: 64} mean_value: 50 std_dev: 6.348228099241551 | |
least_extracted: {elem: 5, count: 32} most_extracted: {elem: 8, count: 66} mean_value: 50 std_dev: 6.592419889539804 | |
least_extracted: {elem: 9, count: 35} most_extracted: {elem: 0, count: 67} mean_value: 50 std_dev: 7.052659073002182 | |
least_extracted: {elem: 76, count: 34} most_extracted: {elem: 80, count: 69} mean_value: 50 std_dev: 6.925315877272314 | |
least_extracted: {elem: 20, count: 37} most_extracted: {elem: 54, count: 64} mean_value: 50 std_dev: 5.854912467321779 | |
least_extracted: {elem: 77, count: 33} most_extracted: {elem: 7, count: 68} mean_value: 50 std_dev: 6.606057825965498 | |
least_extracted: {elem: 64, count: 32} most_extracted: {elem: 61, count: 66} mean_value: 50 std_dev: 6.442049363362563 | |
least_extracted: {elem: 22, count: 33} most_extracted: {elem: 15, count: 71} mean_value: 50 std_dev: 7.500666637039671 | |
least_extracted: {elem: 29, count: 29} most_extracted: {elem: 15, count: 71} mean_value: 50 std_dev: 6.820557161991974 | |
least_extracted: {elem: 29, count: 36} most_extracted: {elem: 42, count: 72} mean_value: 50 std_dev: 7.12460525222275 | |
least_extracted: {elem: 14, count: 35} most_extracted: {elem: 22, count: 74} mean_value: 50 std_dev: 7.994998436522674 | |
least_extracted: {elem: 54, count: 31} most_extracted: {elem: 83, count: 75} mean_value: 50 std_dev: 7.96994353806851 | |
least_extracted: {elem: 17, count: 37} most_extracted: {elem: 91, count: 70} mean_value: 50 std_dev: 7.1693793315739685 | |
least_extracted: {elem: 72, count: 32} most_extracted: {elem: 32, count: 72} mean_value: 50 std_dev: 6.841052550594828 | |
least_extracted: {elem: 55, count: 33} most_extracted: {elem: 97, count: 68} mean_value: 50 std_dev: 6.143289021363068 | |
least_extracted: {elem: 7, count: 33} most_extracted: {elem: 40, count: 68} mean_value: 50 std_dev: 7.183313998427188 | |
least_extracted: {elem: 11, count: 34} most_extracted: {elem: 55, count: 66} mean_value: 50 std_dev: 7.222188034107115 | |
least_extracted: {elem: 58, count: 32} most_extracted: {elem: 74, count: 71} mean_value: 50 std_dev: 7.677239087067694 | |
PRNG + ZRANGE results | |
===================== | |
least_extracted: {elem: 38, count: 34} most_extracted: {elem: 19, count: 75} mean_value: 50 std_dev: 7.725283166331186 | |
least_extracted: {elem: 66, count: 32} most_extracted: {elem: 88, count: 72} mean_value: 50 std_dev: 7.386474125047755 | |
least_extracted: {elem: 85, count: 30} most_extracted: {elem: 13, count: 67} mean_value: 50 std_dev: 6.387487769068525 | |
least_extracted: {elem: 70, count: 35} most_extracted: {elem: 55, count: 62} mean_value: 50 std_dev: 6.041522986797286 | |
least_extracted: {elem: 21, count: 33} most_extracted: {elem: 11, count: 65} mean_value: 50 std_dev: 6.81175454637056 | |
least_extracted: {elem: 66, count: 34} most_extracted: {elem: 20, count: 69} mean_value: 50 std_dev: 7.3006848993775915 | |
least_extracted: {elem: 41, count: 36} most_extracted: {elem: 23, count: 69} mean_value: 50 std_dev: 7.035623639735144 | |
least_extracted: {elem: 60, count: 29} most_extracted: {elem: 8, count: 72} mean_value: 50 std_dev: 6.789698078707183 | |
least_extracted: {elem: 36, count: 35} most_extracted: {elem: 80, count: 64} mean_value: 50 std_dev: 6.6257075093909785 | |
least_extracted: {elem: 65, count: 34} most_extracted: {elem: 2, count: 70} mean_value: 50 std_dev: 7.15122367151245 | |
least_extracted: {elem: 8, count: 33} most_extracted: {elem: 54, count: 66} mean_value: 50 std_dev: 6.395310782127793 | |
least_extracted: {elem: 64, count: 29} most_extracted: {elem: 54, count: 68} mean_value: 50 std_dev: 6.502307282803543 | |
least_extracted: {elem: 70, count: 33} most_extracted: {elem: 61, count: 68} mean_value: 50 std_dev: 6.860029154456998 | |
least_extracted: {elem: 3, count: 29} most_extracted: {elem: 73, count: 70} mean_value: 50 std_dev: 6.955573304911681 | |
least_extracted: {elem: 36, count: 35} most_extracted: {elem: 43, count: 76} mean_value: 50 std_dev: 7.603946343840151 | |
least_extracted: {elem: 29, count: 35} most_extracted: {elem: 75, count: 69} mean_value: 50 std_dev: 7.12460525222275 | |
least_extracted: {elem: 34, count: 33} most_extracted: {elem: 58, count: 68} mean_value: 50 std_dev: 8.027452896155792 | |
least_extracted: {elem: 71, count: 35} most_extracted: {elem: 22, count: 62} mean_value: 50 std_dev: 6.281719509815764 | |
least_extracted: {elem: 8, count: 30} most_extracted: {elem: 29, count: 66} mean_value: 50 std_dev: 7.6589816555466435 | |
least_extracted: {elem: 29, count: 34} most_extracted: {elem: 16, count: 67} mean_value: 50 std_dev: 5.96322060635023 | |
least_extracted: {elem: 25, count: 36} most_extracted: {elem: 26, count: 74} mean_value: 50 std_dev: 7.645913941446111 | |
least_extracted: {elem: 42, count: 34} most_extracted: {elem: 56, count: 71} mean_value: 50 std_dev: 7.487322618933954 | |
least_extracted: {elem: 82, count: 34} most_extracted: {elem: 10, count: 67} mean_value: 50 std_dev: 7.240165743959181 | |
least_extracted: {elem: 92, count: 32} most_extracted: {elem: 71, count: 70} mean_value: 50 std_dev: 7.567033764957046 | |
least_extracted: {elem: 0, count: 30} most_extracted: {elem: 49, count: 67} mean_value: 50 std_dev: 6.739436178197699 | |
least_extracted: {elem: 7, count: 38} most_extracted: {elem: 97, count: 80} mean_value: 50 std_dev: 6.865857557508749 | |
least_extracted: {elem: 51, count: 38} most_extracted: {elem: 8, count: 70} mean_value: 50 std_dev: 6.473020933072903 | |
least_extracted: {elem: 41, count: 27} most_extracted: {elem: 34, count: 68} mean_value: 50 std_dev: 7.397296803562772 | |
least_extracted: {elem: 50, count: 36} most_extracted: {elem: 52, count: 69} mean_value: 50 std_dev: 6.590902821313632 | |
least_extracted: {elem: 12, count: 33} most_extracted: {elem: 24, count: 73} mean_value: 50 std_dev: 7.385120175054703 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SRANDMEMBER results | |
=================== | |
least_extracted: {elem: 286, count: 10} most_extracted: {elem: 706, count: 103} mean_value: 50 std_dev: 23.725808732264532 | |
least_extracted: {elem: 669, count: 7} most_extracted: {elem: 108, count: 108} mean_value: 50 std_dev: 23.422126291180312 | |
least_extracted: {elem: 295, count: 5} most_extracted: {elem: 645, count: 110} mean_value: 50 std_dev: 24.2488350235635 | |
least_extracted: {elem: 983, count: 7} most_extracted: {elem: 648, count: 104} mean_value: 50 std_dev: 23.780832617887878 | |
least_extracted: {elem: 286, count: 7} most_extracted: {elem: 689, count: 110} mean_value: 50 std_dev: 23.937167752263427 | |
least_extracted: {elem: 286, count: 7} most_extracted: {elem: 116, count: 105} mean_value: 50 std_dev: 23.733225655186445 | |
least_extracted: {elem: 605, count: 7} most_extracted: {elem: 130, count: 103} mean_value: 50 std_dev: 23.860553220744904 | |
least_extracted: {elem: 901, count: 8} most_extracted: {elem: 247, count: 104} mean_value: 50 std_dev: 23.62773793658631 | |
least_extracted: {elem: 535, count: 8} most_extracted: {elem: 657, count: 112} mean_value: 50 std_dev: 23.700928251863893 | |
least_extracted: {elem: 798, count: 7} most_extracted: {elem: 422, count: 105} mean_value: 50 std_dev: 23.603813251252433 | |
least_extracted: {elem: 983, count: 7} most_extracted: {elem: 42, count: 109} mean_value: 50 std_dev: 23.718811100053056 | |
least_extracted: {elem: 295, count: 8} most_extracted: {elem: 308, count: 101} mean_value: 50 std_dev: 23.525305524052182 | |
least_extracted: {elem: 605, count: 4} most_extracted: {elem: 589, count: 111} mean_value: 50 std_dev: 23.548630533430178 | |
least_extracted: {elem: 759, count: 4} most_extracted: {elem: 405, count: 105} mean_value: 50 std_dev: 24.09207338524437 | |
least_extracted: {elem: 798, count: 4} most_extracted: {elem: 342, count: 106} mean_value: 50 std_dev: 24.119286888297506 | |
least_extracted: {elem: 259, count: 5} most_extracted: {elem: 825, count: 104} mean_value: 50 std_dev: 24.01478711127792 | |
least_extracted: {elem: 592, count: 5} most_extracted: {elem: 67, count: 104} mean_value: 50 std_dev: 23.789241265748682 | |
least_extracted: {elem: 798, count: 7} most_extracted: {elem: 634, count: 104} mean_value: 50 std_dev: 23.723111094458076 | |
least_extracted: {elem: 605, count: 9} most_extracted: {elem: 655, count: 105} mean_value: 50 std_dev: 23.751336804483238 | |
least_extracted: {elem: 286, count: 6} most_extracted: {elem: 446, count: 107} mean_value: 50 std_dev: 23.792435772740884 | |
least_extracted: {elem: 259, count: 3} most_extracted: {elem: 711, count: 103} mean_value: 50 std_dev: 23.670065483644105 | |
least_extracted: {elem: 759, count: 6} most_extracted: {elem: 845, count: 107} mean_value: 50 std_dev: 23.82217454389922 | |
least_extracted: {elem: 901, count: 4} most_extracted: {elem: 345, count: 103} mean_value: 50 std_dev: 23.711937921646133 | |
least_extracted: {elem: 259, count: 7} most_extracted: {elem: 924, count: 104} mean_value: 50 std_dev: 23.810753872987725 | |
least_extracted: {elem: 605, count: 8} most_extracted: {elem: 238, count: 105} mean_value: 50 std_dev: 23.951033380628903 | |
least_extracted: {elem: 295, count: 7} most_extracted: {elem: 97, count: 103} mean_value: 50 std_dev: 23.80294099475945 | |
least_extracted: {elem: 759, count: 4} most_extracted: {elem: 54, count: 108} mean_value: 50 std_dev: 23.780201849437695 | |
least_extracted: {elem: 798, count: 6} most_extracted: {elem: 872, count: 104} mean_value: 50 std_dev: 23.61855203013089 | |
least_extracted: {elem: 916, count: 5} most_extracted: {elem: 449, count: 101} mean_value: 50 std_dev: 23.82565843791101 | |
least_extracted: {elem: 266, count: 7} most_extracted: {elem: 28, count: 105} mean_value: 50 std_dev: 23.510253082431927 | |
PRNG + ZRANGE results | |
===================== | |
least_extracted: {elem: 371, count: 31} most_extracted: {elem: 111, count: 75} mean_value: 50 std_dev: 7.1442284397967 | |
least_extracted: {elem: 639, count: 32} most_extracted: {elem: 745, count: 73} mean_value: 50 std_dev: 7.13792686989717 | |
least_extracted: {elem: 119, count: 31} most_extracted: {elem: 644, count: 78} mean_value: 50 std_dev: 7.252172088415994 | |
least_extracted: {elem: 890, count: 25} most_extracted: {elem: 769, count: 74} mean_value: 50 std_dev: 6.8625068305976935 | |
least_extracted: {elem: 43, count: 30} most_extracted: {elem: 553, count: 78} mean_value: 50 std_dev: 7.0861837402088295 | |
least_extracted: {elem: 398, count: 26} most_extracted: {elem: 350, count: 73} mean_value: 50 std_dev: 7.022962337931196 | |
least_extracted: {elem: 432, count: 29} most_extracted: {elem: 393, count: 77} mean_value: 50 std_dev: 7.471679864662297 | |
least_extracted: {elem: 319, count: 27} most_extracted: {elem: 830, count: 75} mean_value: 50 std_dev: 7.141568455178456 | |
least_extracted: {elem: 634, count: 24} most_extracted: {elem: 758, count: 76} mean_value: 50 std_dev: 6.822316322188527 | |
least_extracted: {elem: 513, count: 29} most_extracted: {elem: 137, count: 73} mean_value: 50 std_dev: 6.925027075759344 | |
least_extracted: {elem: 240, count: 29} most_extracted: {elem: 119, count: 71} mean_value: 50 std_dev: 6.948812848249692 | |
least_extracted: {elem: 754, count: 28} most_extracted: {elem: 180, count: 75} mean_value: 50 std_dev: 7.033775657497188 | |
least_extracted: {elem: 491, count: 28} most_extracted: {elem: 211, count: 72} mean_value: 50 std_dev: 7.031073886683314 | |
least_extracted: {elem: 993, count: 31} most_extracted: {elem: 384, count: 74} mean_value: 50 std_dev: 7.208883408684039 | |
least_extracted: {elem: 544, count: 25} most_extracted: {elem: 356, count: 86} mean_value: 50 std_dev: 7.2280011068067775 | |
least_extracted: {elem: 87, count: 31} most_extracted: {elem: 120, count: 72} mean_value: 50 std_dev: 7.11083680026479 | |
least_extracted: {elem: 334, count: 29} most_extracted: {elem: 403, count: 76} mean_value: 50 std_dev: 6.993711461019821 | |
least_extracted: {elem: 693, count: 26} most_extracted: {elem: 489, count: 74} mean_value: 50 std_dev: 7.240165743959181 | |
least_extracted: {elem: 414, count: 29} most_extracted: {elem: 216, count: 76} mean_value: 50 std_dev: 7.253826576366436 | |
least_extracted: {elem: 167, count: 28} most_extracted: {elem: 140, count: 78} mean_value: 50 std_dev: 7.237679186037469 | |
least_extracted: {elem: 4, count: 29} most_extracted: {elem: 643, count: 74} mean_value: 50 std_dev: 7.01612428624237 | |
least_extracted: {elem: 867, count: 27} most_extracted: {elem: 156, count: 72} mean_value: 50 std_dev: 7.338255923582933 | |
least_extracted: {elem: 568, count: 28} most_extracted: {elem: 524, count: 80} mean_value: 50 std_dev: 7.120954992134131 | |
least_extracted: {elem: 96, count: 30} most_extracted: {elem: 536, count: 76} mean_value: 50 std_dev: 6.928347566339322 | |
least_extracted: {elem: 262, count: 29} most_extracted: {elem: 383, count: 75} mean_value: 50 std_dev: 7.188741197177709 | |
least_extracted: {elem: 26, count: 32} most_extracted: {elem: 663, count: 72} mean_value: 50 std_dev: 6.835641886465382 | |
least_extracted: {elem: 239, count: 29} most_extracted: {elem: 194, count: 74} mean_value: 50 std_dev: 6.782477423478828 | |
least_extracted: {elem: 645, count: 28} most_extracted: {elem: 378, count: 73} mean_value: 50 std_dev: 7.131199057662042 | |
least_extracted: {elem: 991, count: 31} most_extracted: {elem: 327, count: 81} mean_value: 50 std_dev: 7.124184163818338 | |
least_extracted: {elem: 67, count: 31} most_extracted: {elem: 338, count: 73} mean_value: 50 std_dev: 6.81850423480106 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Return the element extracted the smallest number of times. | |
*/ | |
var leastExtracted = function(values) { | |
var item = { | |
elem: Number.MAX_VALUE, | |
count: Number.MAX_VALUE | |
}; | |
values.forEach(function(val, i) { | |
if (val < item.count) { | |
item.elem = i; | |
item.count = val; | |
} | |
}); | |
return item; | |
}; | |
/** | |
* Return the average of the values. | |
*/ | |
var mean = function(values) { | |
var sum = 0; | |
values.forEach(function(val) { | |
sum += val; | |
}); | |
return sum / values.length; | |
}; | |
/** | |
* Return the element extracted the biggest number of times. | |
*/ | |
var mostEtracted = function(values) { | |
var item = { | |
elem: Number.MIN_VALUE, | |
count: Number.MIN_VALUE | |
}; | |
values.forEach(function(val, i) { | |
if (val > item.count) { | |
item.elem = i; | |
item.count = val; | |
} | |
}); | |
return item; | |
}; | |
/** | |
* Return the standard deviation of the values. | |
*/ | |
var std_dev = function(values) { | |
var average = mean(values) | |
, sum = 0 | |
, variance; | |
values.forEach(function(val) { | |
sum += Math.pow(val - average, 2); | |
}); | |
variance = sum / values.length; | |
return Math.sqrt(variance); | |
}; | |
exports.leastExtracted = leastExtracted; | |
exports.mean = mean; | |
exports.mostEtracted = mostEtracted; | |
exports.std_dev = std_dev; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Module dependencies. | |
*/ | |
var async = require('async') | |
, rc = require('redis').createClient() | |
, sample = [] | |
, number_of_samples = 30 | |
, mode = 'SRANDMEMBER' | |
, randInt = require('./prng').randInt | |
, sample_size = 1000 | |
, draws_per_sample = sample_size * 50 | |
, stat = require('./stat'); | |
/** | |
* Add an element in the set. | |
*/ | |
var addElement = function(element) { | |
var args = ['set', element] | |
, command = 'SADD'; | |
if (mode === 'PRNG + ZRANGE') { | |
args.push(element); | |
command = 'ZADD'; | |
} | |
return function(callback) { | |
rc.send_command(command, args, callback); | |
}; | |
}; | |
/** | |
* Get sample data and print the result. | |
*/ | |
var getSample = function() { | |
if (!number_of_samples) { | |
if (mode === 'SRANDMEMBER') { | |
mode = 'PRNG + ZRANGE'; | |
number_of_samples = 30; | |
console.log('\nPRNG + ZRANGE results\n=====================\n'); | |
return start(); | |
} | |
rc.quit(); | |
console.log(); | |
return; | |
} | |
number_of_samples--; | |
resetSample(); | |
var tasks = []; | |
for (var i = 0; i < draws_per_sample; i++) { | |
tasks.push(randElement); | |
} | |
async.parallel(tasks, function(err, elements) { | |
if (err) { | |
throw err; | |
} | |
var least = stat.leastExtracted(sample) | |
, most = stat.mostEtracted(sample) | |
, meanval = stat.mean(sample) | |
, stddev = stat.std_dev(sample); | |
console.log('least_extracted: {elem: '+least.elem+', count: '+least.count+'}' | |
+' most_extracted: {elem: '+most.elem+', count: '+most.count+'}' | |
+' mean_value: '+meanval+' std_dev: '+stddev); | |
getSample(); | |
}); | |
}; | |
/** | |
* Return a random element from the set. | |
*/ | |
var randElement = function(callback) { | |
var args = ['set'] | |
, command = 'SRANDMEMBER'; | |
if (mode === 'PRNG + ZRANGE') { | |
var start = randInt(sample_size) | |
, stop = start; | |
args = args.concat([start, stop]); | |
command = 'ZRANGE'; | |
} | |
rc.send_command(command, args, function(err, element) { | |
if (err) { | |
return callback(err); | |
} | |
if (typeof element === 'object') { | |
element = element[0]; | |
} | |
element = parseInt(element, 10); | |
sample[element]++; | |
callback(null, element); | |
}); | |
}; | |
/** | |
* Reset the sample. | |
*/ | |
var resetSample = function() { | |
for (var i = 0; i < sample_size; i++) { | |
sample[i] = 0; | |
} | |
}; | |
/** | |
* Start the test. | |
*/ | |
var start = function() { | |
rc.send_command('DEL', ['set'], function(err, result) { | |
if (err) { | |
throw err; | |
} | |
var tasks = []; | |
for (var i = 0; i < sample_size; i++) { | |
tasks.push(addElement(i)); | |
} | |
async.parallel(tasks, function(err, results) { | |
if (err) { | |
throw err; | |
} | |
getSample(); | |
}); | |
}); | |
}; | |
console.log('\nSRANDMEMBER results\n===================\n'); | |
start(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment