-
-
Save hltbra/2fbf5310aabbecee68c5 to your computer and use it in GitHub Desktop.
Redis Essentials, chapter 3 benchmark
This file contains hidden or 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
var redis = require("redis"); | |
var client = redis.createClient(); | |
if (process.argv.length < 3) { | |
console.log("ERROR: You need to specify a data type!"); | |
console.log(" $ node using-timeseries.js [string|hash]"); | |
process.exit(1); | |
} | |
var getUsedMemory = function(value) { | |
return parseInt(value.match(/used_memory:(\d+)/)[1], 10); | |
}; | |
var dataType = process.argv[2]; | |
var timeseries = require("./timeseries-" + dataType); | |
client.flushall(function(err, reply) { | |
client.info("memory", function(err, reply) { | |
var initialMemory = getUsedMemory(reply); | |
var multi = client.multi(); | |
var benchmark = new timeseries.TimeSeries(multi, "benchmark"); | |
var beginTimestamp = new Date(2015, 0, 1, 0, 0, 0) / 1000; | |
var endTimestamp = new Date(2015, 0, 2, 0, 0, 0) / 1000; | |
for (var timestamp = beginTimestamp ; timestamp < endTimestamp ; timestamp++) { | |
benchmark.insert(timestamp); | |
} | |
multi.exec(function(err, replies) { | |
client.info("memory", function(err, reply){ | |
var totalMemory = getUsedMemory(reply); | |
var usedMemory = totalMemory - initialMemory; | |
console.log("Time Series", dataType, "approach used memory", usedMemory, "bytes"); | |
client.quit(); | |
}); | |
}); | |
}); | |
}); | |
/* | |
$ node benchmark.js string | |
Time Series string approach used memory 11938112 bytes | |
$ node benchmark.js hash | |
Time Series hash approach used memory 797696 bytes | |
*/ |
This file contains hidden or 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
function TimeSeries(client, namespace) { | |
this.namespace = namespace; | |
this.client = client; | |
this.units = { | |
second: 1, | |
minute: 60, | |
hour: 60 * 60, | |
day: 24 * 60 * 60 | |
}; | |
this.granularities = { // 1 | |
'1sec' : { name: '1sec', ttl: this.units.hour * 2, duration: 1, quantity: this.units.minute * 5 }, | |
'1min' : { name: '1min', ttl: this.units.day * 7, duration: this.units.minute, quantity: this.units.hour * 8 }, | |
'1hour': { name: '1hour', ttl: this.units.day * 60 , duration: this.units.hour, quantity: this.units.day * 10 }, | |
'1day' : { name: '1day', ttl: null, duration: this.units.day, quantity: this.units.day * 30 }, | |
}; | |
}; | |
TimeSeries.prototype.insert = function(timestampInSeconds) { | |
for (var granularityName in this.granularities) { | |
var granularity = this.granularities[granularityName]; | |
var key = this._getKeyName(granularity, timestampInSeconds); | |
var fieldName = this._getRoundedTimestamp(timestampInSeconds, granularity.duration); // 1 | |
this.client.hincrby(key, fieldName, 1); // 2 | |
if (granularity.ttl !== null) { | |
this.client.expire(key, granularity.ttl); | |
} | |
} | |
}; | |
TimeSeries.prototype._getKeyName = function(granularity, timestampInSeconds) { | |
var roundedTimestamp = this._getRoundedTimestamp(timestampInSeconds, granularity.quantity); // 1 | |
return [this.namespace, granularity.name, roundedTimestamp].join(':'); | |
}; | |
TimeSeries.prototype._getRoundedTimestamp = function(timestampInSeconds, precision) { | |
return Math.floor(timestampInSeconds/precision) * precision; | |
}; | |
TimeSeries.prototype.fetch = function(granularityName, beginTimestamp, endTimestamp, onComplete) { | |
var granularity = this.granularities[granularityName]; | |
var begin = this._getRoundedTimestamp(beginTimestamp, granularity.duration); | |
var end = this._getRoundedTimestamp(endTimestamp, granularity.duration); | |
var fields = []; // 1 | |
var multi = this.client.multi(); // 2 | |
for (var timestamp = begin; timestamp <= end; timestamp += granularity.duration) { | |
var key = this._getKeyName(granularity, timestamp); | |
var fieldName = this._getRoundedTimestamp(timestamp, granularity.duration); // 3 | |
multi.hget(key, fieldName); // 4 | |
} | |
multi.exec(function(err, replies) { // 5 | |
var results = []; | |
for (var i = 0 ; i < replies.length ; i++) { | |
var timestamp = beginTimestamp + i * granularity.duration; | |
var value = parseInt(replies[i], 10) || 0; | |
results.push({timestamp: timestamp , value: value}); | |
} | |
onComplete(granularityName, results); | |
}); | |
}; | |
exports.TimeSeries = TimeSeries; |
This file contains hidden or 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
function TimeSeries(client, namespace) { // 1 | |
this.namespace = namespace; // 2 | |
this.client = client; // 3 | |
this.units = { // 4 | |
second: 1, | |
minute: 60, | |
hour: 60 * 60, | |
day: 24 * 60 * 60 | |
}; | |
this.granularities = { // 5 | |
'1sec' : { name: '1sec', ttl: this.units.hour * 2, duration: this.units.second }, | |
'1min' : { name: '1min', ttl: this.units.day * 7, duration: this.units.minute }, | |
'1hour': { name: '1hour', ttl: this.units.day * 60 , duration: this.units.hour }, | |
'1day' : { name: '1day', ttl: null, duration: this.units.day } // 9 | |
}; | |
}; | |
TimeSeries.prototype.insert = function(timestampInSeconds) { // 1 | |
for (var granularityName in this.granularities) { // 2 | |
var granularity = this.granularities[granularityName]; // 3 | |
var key = this._getKeyName(granularity, timestampInSeconds); // 4 | |
this.client.incr(key); // 5 | |
if (granularity.ttl !== null) { // 6 | |
this.client.expire(key, granularity.ttl); // 7 | |
} | |
} | |
}; | |
TimeSeries.prototype._getKeyName = function(granularity, timestampInSeconds) { // 1 | |
var roundedTimestamp = this._getRoundedTimestamp(timestampInSeconds, granularity.duration); // 2 | |
return [this.namespace, granularity.name, roundedTimestamp].join(':'); // 3 | |
}; | |
TimeSeries.prototype._getRoundedTimestamp = function(timestampInSeconds, precision) { // 1 | |
return Math.floor(timestampInSeconds/precision) * precision; // 2 | |
}; | |
TimeSeries.prototype.fetch = function(granularityName, beginTimestamp, endTimestamp, onComplete) { // 1 | |
var granularity = this.granularities[granularityName]; // 2 | |
var begin = this._getRoundedTimestamp(beginTimestamp, granularity.duration); // 3 | |
var end = this._getRoundedTimestamp(endTimestamp, granularity.duration); // 4 | |
var keys = []; // 5 | |
for (var timestamp = begin; timestamp <= end; timestamp += granularity.duration) { // 6 | |
var key = this._getKeyName(granularity, timestamp); // 7 | |
keys.push(key); // 8 | |
} | |
this.client.mget(keys, function(err, replies) { // 9 | |
var results = []; // 10 | |
for (var i = 0 ; i < replies.length ; i++) { // 11 | |
var timestamp = beginTimestamp + i * granularity.duration; // 12 | |
var value = parseInt(replies[i], 10) || 0; // 13 | |
results.push({timestamp: timestamp , value: value}); // 14 | |
} | |
onComplete(granularityName, results); // 15 | |
}); | |
}; | |
exports.TimeSeries = TimeSeries; // 16 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment