Skip to content

Instantly share code, notes, and snippets.

@lpinca
Last active December 16, 2015 06:19
Show Gist options
  • Save lpinca/5390693 to your computer and use it in GitHub Desktop.
Save lpinca/5390693 to your computer and use it in GitHub Desktop.
SRANDMEMBER lacks randomness
/**
* 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;
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
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
/**
* 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;
/**
* 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