Permalink
Browse files

Memory usage dump script now create pretty graphs.

  • Loading branch information...
1 parent 6878cf9 commit 467a1d6aa2c15bcca540f02633aed42ea1c8a4ba @Sannis committed Jun 5, 2012
Showing with 155 additions and 126 deletions.
  1. +1 −0 package.json
  2. +8 −8 tools/memory-helper.js
  3. +23 −24 tools/memory-leaks-finder-repl.js
  4. +18 −0 tools/memory-usage-dump.gle
  5. +105 −0 tools/memory-usage-dump.js
  6. +0 −94 tools/memory-usage-show.js
View
@@ -66,5 +66,6 @@
, "devDependencies" :
{ "nodeunit" : ">= 0.7"
, "nodelint" : ">= 0.6"
+ , "async" : ">= 0.1.22"
}
}
View
@@ -21,7 +21,7 @@ function heavyGc() {
exports.heavyGc = heavyGc;
var initialMemoryUsage = null;
-function showMemoryUsageLine(title, value0, value1) {
+function showMemoryUsageDeltaLine(title, value0, value1) {
if (value1) {
process.stdin.write(title + ": " + value1
+ (value1 > value0 ? " (+" : " (")
@@ -30,7 +30,7 @@ function showMemoryUsageLine(title, value0, value1) {
process.stdin.write(title + ": " + value0 + "\n");
}
}
-function showMemoryUsage() {
+function showMemoryUsageDelta() {
if (!initialMemoryUsage) {
initialMemoryUsage = process.memoryUsage();
@@ -42,14 +42,14 @@ function showMemoryUsage() {
var memoryUsage = process.memoryUsage();
process.stdin.write("Currect memory usage:\n");
- showMemoryUsageLine("rss", initialMemoryUsage.rss, memoryUsage.rss );
- showMemoryUsageLine("heapUsed", initialMemoryUsage.heapUsed, memoryUsage.heapUsed );
- showMemoryUsageLine("heapTotal", initialMemoryUsage.heapTotal, memoryUsage.heapTotal);
+ showMemoryUsageDeltaLine("rss", initialMemoryUsage.rss, memoryUsage.rss );
+ showMemoryUsageDeltaLine("heapUsed", initialMemoryUsage.heapUsed, memoryUsage.heapUsed );
+ showMemoryUsageDeltaLine("heapTotal", initialMemoryUsage.heapTotal, memoryUsage.heapTotal);
}
}
-function resetMemoryUsage() {
+function resetMemoryUsageDelta() {
initialMemoryUsage = null;
}
-exports.showMemoryUsage = showMemoryUsage;
-exports.resetMemoryUsage = resetMemoryUsage;
+exports.showMemoryUsageDelta = showMemoryUsageDelta;
+exports.resetMemoryUsageDelta = resetMemoryUsageDelta;
@@ -24,21 +24,21 @@ commands = {
quit: function () {
process.exit(0);
},
- showMemoryUsage: function () {
- helper.showMemoryUsage();
+ showMemoryUsageDelta: function () {
+ helper.showMemoryUsageDelta();
},
- resetMemoryUsage: function () {
- helper.resetMemoryUsage();
+ resetMemoryUsageDelta: function () {
+ helper.resetMemoryUsageDelta();
},
gc: function () {
helper.heavyGc();
},
help: function () {
var cmd;
- process.stdin.write("List of commands:\n");
+ process.stdout.write("List of commands:\n");
for (cmd in commands) {
if (commands.hasOwnProperty(cmd)) {
- process.stdin.write(" " + cmd + "\n");
+ process.stdout.write(" " + cmd + "\n");
}
}
},
@@ -158,17 +158,17 @@ commands = {
commands.manyQueries.passTimesAsArgument = true;
// Main program
-process.stdin.write("Starting WebKit development tools agent...\n");
-process.stdin.write("Open http://c4milo.github.com/node-webkit-agent/19.0.1084.46/inspector.html?host=localhost:1337&page=0 to use it.\n");
+process.stdout.write("Starting WebKit development tools agent...\n");
+process.stdout.write("Open http://c4milo.github.com/node-webkit-agent/19.0.1084.46/inspector.html?host=localhost:1337&page=0 to use it.\n");
require('webkit-devtools-agent');
process.emit('SIGUSR2');
-process.stdin.write("\n");
+process.stdout.write("\n");
-process.stdin.write("Welcome to the memory leaks finder!\n");
-process.stdin.write("Type 'help' for options.\n");
+process.stdout.write("Welcome to the memory leaks finder!\n");
+process.stdout.write("Type 'help' for options.\n");
helper.heavyGc();
-helper.showMemoryUsage();
+helper.showMemoryUsageDelta();
rli = readline.createInterface(process.stdin, process.stdout, function completer (text) {
var
@@ -191,25 +191,23 @@ rli.on("SIGINT", function () {
});
rli.on('close', function () {
- process.stdin.write("\n");
- helper.showMemoryUsage();
+ process.stdout.write("\n");
+ helper.showMemoryUsageDelta();
process.stdin.destroy();
});
rli.on('line', function (cmd) {
- var
- pair = cmd.trim().split(/\s+/),
- i;
+ var pair = cmd.trim().split(/\s+/), i;
pair[0] = pair[0].trim();
pair[1] = parseInt(pair[1], 10) > 0 ? parseInt(pair[1], 10) : 1;
if (commands[pair[0]]) {
- if (pair[0] === "help" || pair[0] === "showMemoryUsage") {
+ if (pair[0] === "help" || pair[0] === "quit" || pair[0] === "showMemoryUsage") {
commands[pair[0]]();
} else {
try {
- process.stdin.write("Run " + pair[0] + " for " + pair[1] + " times:");
+ process.stdout.write("Run " + pair[0] + " for " + pair[1] + " times:");
if (commands[pair[0]].passTimesAsArgument) {
commands[pair[0]](pair[1]);
@@ -219,15 +217,16 @@ rli.on('line', function (cmd) {
}
}
- process.stdin.write(" done.\n");
+ process.stdout.write(" done.\n");
} catch (e) {
- process.stdin.write("Exception caused!\n");
- process.stdin.write(util.inspect(e.stack) + "\n");
+ process.stdout.write("Exception caused!\n");
+ process.stdout.write(util.inspect(e.stack) + "\n");
}
- helper.showMemoryUsage();
+
+ helper.showMemoryUsageDelta();
}
} else if (pair[0] !== "") {
- process.stdin.write("Unrecognized command: " + pair[0] + "\n");
+ process.stdout.write("Unrecognized command: " + pair[0] + "\n");
commands.help();
}
@@ -0,0 +1,18 @@
+size 50 12
+begin graph
+ size 50 11.5
+
+ xaxis min 0 hei 0.5
+ yaxis min 0 hei 0.5
+
+ title "Memory usage (Mb)" hei 1 dist 0.8
+ data memory-usage-dump.dat
+
+ xtitle "Time, seconds" hei 0.5 dist 0.5
+
+ d1 line lwidth 0.05 color blue key "RSS"
+ d2 line lwidth 0.05 color green key "Heap used"
+ d3 line lwidth 0.05 color red key "Heap total"
+
+ key pos rc compact offset -0.1 0 nobox hei 0.5
+end graph
View
@@ -0,0 +1,105 @@
+#!/usr/bin/env node --expose-gc
+/*
+Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors
+See contributors list in README
+
+See license text in LICENSE file
+*/
+
+var
+// Require modules
+ mysql = require("../"),
+ async = require("async"),
+ helper = require("./memory-helper"),
+// Load configuration
+ cfg = require("../tests/config"),
+// Parameters
+ timeLimitInSec = 10*60*60,
+ forceGc = false,
+ pauseBetweenOperationsInMs = 1,
+ logMemoryUsageIntervalInMs = 400,
+ logMemoryUsageInterval = null,
+ // Start time
+ startHrTime = [0, 0];
+
+function logMemoryUsage() {
+ var
+ currentHrTime = process.hrtime(),
+ timeDelta = '',
+ memoryUsage = process.memoryUsage(),
+ Mb = 1024*1024;
+
+ if (currentHrTime[1] >= startHrTime[1]) {
+ timeDelta = (currentHrTime[0] - startHrTime[0]) + (currentHrTime[1] - startHrTime[1])/1e9;
+ } else {
+ timeDelta = (currentHrTime[0] - startHrTime[0] - 1) + (currentHrTime[1] - startHrTime[1] + 1e9)/1e9;
+ }
+
+ console.log(timeDelta + '\t' + memoryUsage.rss/Mb + '\t' + memoryUsage.heapUsed/Mb + '\t' + memoryUsage.heapTotal/Mb);
+}
+
+function performOperation(callback) {
+ var connection = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database);
+
+ if (!connection.connectedSync()) {
+ setTimeout(callback, pauseBetweenOperationsInMs);
+ return;
+ }
+
+ connection.query("SELECT 'some string' AS `str`;", function (error, result) {
+ if (error) throw error;
+
+ result.fetchAll(function (error, rows) {
+ if (error) throw error;
+
+ rows = null;
+
+ process.nextTick(callback);
+ });
+ });
+}
+
+// Main program
+console.log("time\tRSS\theapUsed\theapTotal");
+
+startHrTime = process.hrtime();
+logMemoryUsage();
+
+if (logMemoryUsageIntervalInMs > 0) {
+ logMemoryUsageInterval = setInterval(logMemoryUsage, logMemoryUsageIntervalInMs);
+}
+
+async.whilst(
+ function () {
+ var currentHrTime = process.hrtime();
+
+ return (currentHrTime[0] - startHrTime[0]) < timeLimitInSec;
+ },
+ function (callback) {
+ performOperation(function () {
+ if (forceGc) {
+ helper.heavyGc();
+ }
+
+ if (logMemoryUsageIntervalInMs == 0) {
+ logMemoryUsage();
+ }
+
+ if (pauseBetweenOperationsInMs > 0) {
+ setTimeout(callback, pauseBetweenOperationsInMs);
+ } else {
+ process.nextTick(callback);
+ }
+ });
+ },
+ function (error) {
+ if (error) throw error;
+
+ // All ok
+ if (logMemoryUsageInterval) {
+ clearInterval(logMemoryUsageInterval);
+ }
+
+ process.exit(0);
+ }
+);
View
@@ -1,94 +0,0 @@
-#!/usr/bin/env node --expose-gc
-/*
-Copyright by Oleg Efimov and node-mysql-libmysqlclient contributors
-See contributors list in README
-
-See license text in LICENSE file
-*/
-
-var
-// Require modules
- mysql = require("../"),
- helper = require("./memory-helper"),
-// Load configuration
- cfg = require("../tests/config"),
-// Params
- tries = 10,
- i;
-
-function showMemoryUsage() {
- helper.heavyGc();
- helper.showMemoryUsage();
-}
-
-function showConnectionsMemoryUsage() {
- var connections = [], i;
-
- console.log("Initial value:");
- showMemoryUsage();
-
- for (i = 0; i < cfg.slow_connects_inloop; i++) {
- connections[i] = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database);
- }
-
- console.log("Connections created:");
- showMemoryUsage();
-
- for (i = 0; i < cfg.slow_connects_inloop; i++) {
- if (connections[i].connectedSync()) {
- connections[i].closeSync();
- }
- connections[i] = null;
- }
-
- connections = null;
-
- console.log("Connections closed:");
- showMemoryUsage();
-}
-
-function showQueriesMemoryUsage() {
- var connection, i, res, rows;
-
- console.log("Initial value:");
- showMemoryUsage();
-
- connection = mysql.createConnectionSync(cfg.host, cfg.user, cfg.password, cfg.database);
-
- for (i = 0; i < cfg.slow_fetches_inloop; i++) {
- res = connection.querySync("SELECT 'some string' as str;");
- rows = res.fetchAllSync();
- }
-
- rows = null;
- res = null;
- connection = null;
-
- console.log("Connection closed:");
- showMemoryUsage();
-}
-
-// Start!
-console.log("Show memory usage information for NodeJS MySQL/libmysqlclient bindings...");
-
-for (i = 0; i < tries; i++) {
- console.log("\n" + i + ":\n");
- showConnectionsMemoryUsage();
-}
-
-for (i = 0; i < tries; i++) {
- console.log("\n" + i + ":\n");
- showQueriesMemoryUsage();
-}
-
-setTimeout(function () {
- showMemoryUsage();
-
- setTimeout(function () {
- showMemoryUsage();
-
- setTimeout(function () {
- showMemoryUsage();
- }, 5000);
- }, 5000);
-}, 5000);

0 comments on commit 467a1d6

Please sign in to comment.