Move memoryUsage() into C on Linux
This commit is contained in:
parent
3a70129a9c
commit
b3b3cfe007
61
lib/sys.js
61
lib/sys.js
@ -67,64 +67,3 @@ exports.exec = function (command) {
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
exports.memoryUsage = function () {
|
||||
if (process.platform == "linux2") {
|
||||
var data = require("file").read("/proc/self/stat").wait();
|
||||
// from linux-2.6.29/Documentation/filesystems/proc.tx
|
||||
// 0 pid process id
|
||||
// 1 tcomm filename of the executable
|
||||
// 2 state state (R is running, S is sleeping, D is sleeping in an
|
||||
// uninterruptible wait, Z is zombie, T is traced or stopped)
|
||||
// 3 ppid process id of the parent process
|
||||
// 4 pgrp pgrp of the process
|
||||
// 5 sid session id
|
||||
// 6 tty_nr tty the process uses
|
||||
// 7 tty_pgrp pgrp of the tty
|
||||
// 8 flags task flags
|
||||
// 9 min_flt number of minor faults
|
||||
// 10 cmin_flt number of minor faults with child's
|
||||
// 11 maj_flt number of major faults
|
||||
// 12 cmaj_flt number of major faults with child's
|
||||
// 13 utime user mode jiffies
|
||||
// 14 stime kernel mode jiffies
|
||||
// 15 cutime user mode jiffies with child's
|
||||
// 16 cstime kernel mode jiffies with child's
|
||||
// 17 priority priority level
|
||||
// 18 nice nice level
|
||||
// 19 num_threads number of threads
|
||||
// 20 it_real_value (obsolete, always 0)
|
||||
// 21 start_time time the process started after system boot
|
||||
// 22 vsize virtual memory size
|
||||
// 23 rss resident set memory size
|
||||
// 24 rsslim current limit in bytes on the rss
|
||||
// 25 start_code address above which program text can run
|
||||
// 26 end_code address below which program text can run
|
||||
// 27 start_stack address of the start of the stack
|
||||
// 28 esp current value of ESP
|
||||
// 29 eip current value of EIP
|
||||
// 30 pending bitmap of pending signals (obsolete)
|
||||
// 31 blocked bitmap of blocked signals (obsolete)
|
||||
// 32 sigign bitmap of ignored signals (obsolete)
|
||||
// 33 sigcatch bitmap of catched signals (obsolete)
|
||||
// 34 wchan address where process went to sleep
|
||||
// 35 0 (place holder)
|
||||
// 36 0 (place holder)
|
||||
// 37 exit_signal signal to send to parent thread on exit
|
||||
// 38 task_cpu which CPU the task is scheduled on
|
||||
// 39 rt_priority realtime priority
|
||||
// 40 policy scheduling policy (man sched_setscheduler)
|
||||
// 41 blkio_ticks time spent waiting for block IO
|
||||
var fields = data.split(" ");
|
||||
|
||||
// 22 vsize virtual memory size
|
||||
// 23 rss resident set memory size
|
||||
|
||||
return { vsize: parseInt(fields[22]), rss: 4096*parseInt(fields[23]) };
|
||||
|
||||
} else if (process.platform == "darwin") {
|
||||
return process.macGetMemory();
|
||||
} else {
|
||||
throw new Error("Unsupported on your platform! Complain to Ryan!");
|
||||
}
|
||||
};
|
||||
|
124
src/node.cc
124
src/node.cc
@ -254,17 +254,15 @@ v8::Handle<v8::Value> Exit(const v8::Arguments& args) {
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define HAVE_GETMEM 1
|
||||
/* Researched by Tim Becker and Michael Knight
|
||||
* http://blog.kuriositaet.de/?p=257
|
||||
* http://blog.kuriositaet.de/?p=257
|
||||
*/
|
||||
|
||||
#include <mach/task.h>
|
||||
#include <mach/mach_init.h>
|
||||
|
||||
v8::Handle<v8::Value> MacGetMemory(const v8::Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
int getmem(size_t *rss, size_t *vsize) {
|
||||
task_t task = MACH_PORT_NULL;
|
||||
struct task_basic_info t_info;
|
||||
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
|
||||
@ -274,21 +272,123 @@ v8::Handle<v8::Value> MacGetMemory(const v8::Arguments& args) {
|
||||
(task_info_t)&t_info,
|
||||
&t_info_count);
|
||||
|
||||
if (KERN_SUCCESS != r) {
|
||||
if (r != KERN_SUCCESS) return -1;
|
||||
|
||||
*rss = t_info.resident_size;
|
||||
*vsize = t_info.virtual_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
#ifdef __linux__
|
||||
# define HAVE_GETMEM 1
|
||||
# include <sys/param.h> /* for MAXPATHLEN */
|
||||
# include <sys/user.h> /* for PAGE_SIZE */
|
||||
|
||||
int getmem(size_t *rss, size_t *vsize) {
|
||||
FILE *f = fopen("/proc/self/stat", "r");
|
||||
if (!f) return -1;
|
||||
|
||||
int itmp;
|
||||
char ctmp;
|
||||
char buffer[MAXPATHLEN];
|
||||
|
||||
/* PID */
|
||||
if (fscanf(f, "%d ", &itmp) == 0) goto error;
|
||||
/* Exec file */
|
||||
if (fscanf (f, "%s ", &buffer[0]) == 0) goto error;
|
||||
/* State */
|
||||
if (fscanf (f, "%c ", &ctmp) == 0) goto error;
|
||||
/* Parent process */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* Process group */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* Session id */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* TTY */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* TTY owner process group */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* Flags */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* Minor faults (no memory page) */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* Minor faults, children */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* Major faults (memory page faults) */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* Major faults, children */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* utime */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* stime */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* utime, children */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* stime, children */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* jiffies remaining in current time slice */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* 'nice' value */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
/* jiffies until next timeout */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* jiffies until next SIGALRM */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* start time (jiffies since system boot) */
|
||||
if (fscanf (f, "%d ", &itmp) == 0) goto error;
|
||||
|
||||
/* Virtual memory size */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
*vsize = (size_t) itmp;
|
||||
|
||||
/* Resident set size */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
*rss = (size_t) itmp * PAGE_SIZE;
|
||||
|
||||
/* rlim */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* Start of text */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* End of text */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
/* Start of stack */
|
||||
if (fscanf (f, "%u ", &itmp) == 0) goto error;
|
||||
|
||||
fclose (f);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
fclose (f);
|
||||
return -1;
|
||||
}
|
||||
#endif // __linux__
|
||||
|
||||
v8::Handle<v8::Value> MemoryUsage(const v8::Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
#ifndef HAVE_GETMEM
|
||||
return ThrowException(Exception::Error(String::New("Not support on your platform. (Talk to Ryan.)")));
|
||||
#else
|
||||
size_t rss, vsize;
|
||||
|
||||
int r = getmem(&rss, &vsize);
|
||||
|
||||
if (r != 0) {
|
||||
return ThrowException(Exception::Error(String::New(strerror(errno))));
|
||||
}
|
||||
|
||||
size_t rss = t_info.resident_size;
|
||||
size_t vs = t_info.virtual_size;
|
||||
|
||||
Local<Object> info = Object::New();
|
||||
|
||||
info->Set(String::NewSymbol("rss"), Integer::NewFromUnsigned(rss));
|
||||
info->Set(String::NewSymbol("vsize"), Integer::NewFromUnsigned(vs));
|
||||
info->Set(String::NewSymbol("vsize"), Integer::NewFromUnsigned(vsize));
|
||||
|
||||
return scope.Close(info);
|
||||
#endif
|
||||
}
|
||||
#endif // __APPLE__
|
||||
|
||||
|
||||
v8::Handle<v8::Value> Kill(const v8::Arguments& args) {
|
||||
HandleScope scope;
|
||||
@ -510,9 +610,7 @@ static Local<Object> Load(int argc, char *argv[]) {
|
||||
NODE_SET_METHOD(process, "cwd", Cwd);
|
||||
NODE_SET_METHOD(process, "dlopen", DLOpen);
|
||||
NODE_SET_METHOD(process, "kill", Kill);
|
||||
#ifdef __APPLE__
|
||||
NODE_SET_METHOD(process, "macGetMemory", MacGetMemory);
|
||||
#endif
|
||||
NODE_SET_METHOD(process, "memoryUsage", MemoryUsage);
|
||||
|
||||
// Assign the EventEmitter. It was created in main().
|
||||
process->Set(String::NewSymbol("EventEmitter"),
|
||||
|
@ -1,6 +1,6 @@
|
||||
process.mixin(require("./common"));
|
||||
|
||||
var r = memoryUsage();
|
||||
var r = process.memoryUsage();
|
||||
puts(inspect(r));
|
||||
assertTrue(r["rss"] > 0);
|
||||
assertTrue(r["vsize"] > 0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user