memory allocation

81 views
Skip to first unread message

pete

unread,
Jul 10, 2009, 1:14:32 AM7/10/09
to nodejs
Realizing node is still a nascent project, Ryan's away from the list
for awhile, and node vs. thin is an apple vs. oranges sort of thing,
just sharing recent observations here on the chance others might find
informative...

I ran ab -c100 -n3000000 against the node and thin (ruby) web servers
to watch them each from linux's top display. While thin kept its
memory allocation relatively conservative and constant (~6.5MB) over
the duration of the run (as viewed in top's DATA column over the time
it serviced requests), node's started out at 33MB and gradually
climbed up to 353MB by the time all three million requests had been
processed. I haven't done so yet but believe if I increase the number
of requests sent to node and wait long enough, it will eventually fall
over where v8's heap.cc and assembler-ia32.h define the limit, 512MB.
I'd be interested to learn what others see on their own systems. This
was Ubuntu 8.10 Desktop running inside VirtualBox on Mac OS Leopard.

Thanks. -pete

(node and thin code snippets)

node.http.createServer(function (request, response) {
response.sendHeader(200, [["Content-Type", "text/plain"]]);
response.sendBody("Hello World!");
response.finish();
request.connection.close(); // Thanks, Connor
}).listen(8000);
puts("Server running at http://127.0.0.1:8000/");

---

app = proc do |env|
[
200,
{
'Content-Type' => 'text/html',
'Content-Length' => '12',
},
['Hello World!']
]
end
run app

Brian Hammond

unread,
Jul 22, 2009, 1:22:32 AM7/22/09
to nodejs
Has there been any update on this? I'm getting bit by this as well.

On Jul 10, 1:14 am, pete <p...@pollenware.com> wrote:
> Realizing node is still a nascent project, Ryan's away from the list
> for awhile, and node vs. thin is an apple vs. oranges sort of thing,
> just sharing recent observations here on the chance others might find
> informative...
>
> I ran ab -c100 -n3000000 against the node and thin (ruby) web servers
> to watch them each from linux's top display.  While thin kept its
> memory allocation relatively conservative and constant (~6.5MB) over
> the duration of the run (as viewed in top's DATA column over the time
> it serviced requests), node's started out at 33MB and gradually
> climbed up to 353MB by the time all three million requests had been
> processed.  I haven't done so yet but believe if I increase the number
> of requests sent to node and wait long enough, it will eventually fall
> over where v8's heap.cc and assembler-ia32.h define the limit, 512MB.
> I'd be interested to learn what others see on their own systems.  This
> was Ubuntu 8.10 Desktop running inside VirtualBox on Mac OS Leopard.
>
> Thanks.  -pete
>
> (node and thin code snippets)
>
>   node.http.createServer(function (request, response) {
>     response.sendHeader(200, [["Content-Type", "text/plain"]]);
>     response.sendBody("Hello World!");
>     response.finish();
>     request.connection.close(); // Thanks, Connor
>   }).listen(8000);
>   puts("Server running athttp://127.0.0.1:8000/");

ryan dahl

unread,
Jul 22, 2009, 4:21:45 AM7/22/09
to nod...@googlegroups.com
On Wed, Jul 22, 2009 at 5:22 AM, Brian
Hammond<or.else.it.g...@gmail.com> wrote:
>
> Has there been any update on this?  I'm getting bit by this as well.
>

I haven't been able to figure out the leak yet.

Brian Hammond

unread,
Jul 22, 2009, 11:50:54 AM7/22/09
to nodejs
I tried this with the latest v8 from svn

svn checkout http://v8.googlecode.com/svn/trunk/ v8

and saw the same results, and a "broken pipe" after a while (~ 1.5
million requests made).

I am going to try with the bleeding edge v8 from svn

svn checkout http://v8.googlecode.com/svn/branches/bleeding_edge/
v8

and saw exactly the same results.

I'm not sure I was expecting anything different but you can rule out
v8 I suppose.



On Jul 22, 4:21 am, ryan dahl <coldredle...@gmail.com> wrote:
> On Wed, Jul 22, 2009 at 5:22 AM, Brian
>

Brian Hammond

unread,
Jul 22, 2009, 11:51:24 AM7/22/09
to nodejs
> I am going to try with the bleeding edge v8 from svn

s/going to/did/

On Jul 22, 11:50 am, Brian Hammond
<or.else.it.gets.the.h...@gmail.com> wrote:
> I tried this with the latest v8 from svn
>
>     svn checkouthttp://v8.googlecode.com/svn/trunk/v8
>
> and saw the same results, and a "broken pipe" after a while (~ 1.5
> million requests made).
>
> I am going to try with the bleeding edge v8 from svn
>
>     svn checkouthttp://v8.googlecode.com/svn/branches/bleeding_edge/

Brian Hammond

unread,
Jul 22, 2009, 3:59:37 PM7/22/09
to nodejs
another data point....

$ ab -n 2500000 -c 50 -k http://127.0.0.1:8000/

That is, keep-alives were used. This finished the run and ** memory
went back down **.

So,
- loading node test_server.js ... 12MB resident
- during run of 'ab' ... 286MB resident (ouch)
- after 'ab' finishes all 2.5M requests ... 116MB resident (why not
12MB again?)

Maybe that's a clue? Not sure.



On Jul 22, 11:51 am, Brian Hammond

ryan dahl

unread,
Jul 24, 2009, 9:20:29 AM7/24/09
to nod...@googlegroups.com
I fixed one problem which was related to a missing HandleScope in the
event processing code. Fixed in
50c0d16208aab392d815e420f3423d23283a31de.

It's very hard to spot these errors and I wonder if there is some V8
technique that I'm missing to catch these errors. There seems to still
be a smaller leak somewhere else.

Brian

unread,
Jul 24, 2009, 12:07:43 PM7/24/09
to nodejs
$ ab -n 3000000 -c 100 http://127.0.0.1:8000/

Requests per second: 3515.67 [#/sec] (mean)
Failed requests: 0
Transfer rate: 391.39 [Kbytes/sec] received

Watching 'top' showed node using 34-35m resident memory. It does not
grow. Good stuff.


Regarding the missing HandleScope. I'm not intimately familiar with
the V8 API. However, I whipped up this little Perl script to
**maybe** find other cases like this in the Node V8 code. YMMV.

It found one thing that may or may not be a problem:

http.cc:153 - no HandleScope found in function
Function started at line 136
Concern is from line content: return Local<String>();

static inline Local<String>
GetMethod (int method)
{
switch (method) {
case HTTP_COPY: return String::NewSymbol("COPY");
case HTTP_DELETE: return String::NewSymbol("DELETE");
case HTTP_GET: return String::NewSymbol("GET");
case HTTP_HEAD: return String::NewSymbol("HEAD");
case HTTP_LOCK: return String::NewSymbol("LOCK");
case HTTP_MKCOL: return String::NewSymbol("MKCOL");
case HTTP_MOVE: return String::NewSymbol("MOVE");
case HTTP_OPTIONS: return String::NewSymbol("OPTIONS");
case HTTP_POST: return String::NewSymbol("POST");
case HTTP_PROPFIND: return String::NewSymbol("PROPFIND");
case HTTP_PROPPATCH: return String::NewSymbol("PROPPATCH");
case HTTP_PUT: return String::NewSymbol("PUT");
case HTTP_TRACE: return String::NewSymbol("TRACE");
case HTTP_UNLOCK: return String::NewSymbol("UNLOCK");
}
return Local<String>();
}

Again, I'm not really sure if you need a HandleScope here. I suppose
it's unclear to me if the HandleScope in the caller of GetMethod is
"good enough" to grab the returned Local. Not sure.


Here's the script. Run it from the node/src dir like: $ perl
find_handle_scope_issues.pl

#!/usr/bin/perl
use strict;

foreach my $filename (<*.cc>) {
local $/;
open(FH, $filename) or die "$filename: $!";
my @lines = split /\n/, <FH>;
close(FH);

my $most_recent_func_start_line = 0;
my $most_recent_handle_scope_line = 0;
my $line_no = 0;

foreach my $line (@lines) {
++$line_no;

if ( $line =~ /^{/ ) {
$most_recent_func_start_line = $line_no;
next;
}

if ( $line =~ /^}/ ) {
$most_recent_func_start_line = 0;
next;
}

if ( $line =~ /HandleScope/ ) {
$most_recent_handle_scope_line = $line_no;
next;
}

if ( $line =~ /\b(?:Local|Handle)\b/ ) {
if ( $most_recent_handle_scope_line <
$most_recent_func_start_line and
$most_recent_func_start_line > 0 ) {
warn "$filename:$line_no - no HandleScope found in function
\n".
"\tFunction started at line $most_recent_func_start_line
\n".
"\tConcern is from line content: $line\n";

Felix Geisendörfer

unread,
Jul 24, 2009, 12:49:55 PM7/24/09
to nodejs
Fantastic work guys! I was monitoring this thread with great interest
and I am very happy to see you guys nailing down those evil memory
leaks : ).

-- Felix Geisendörfer aka the_undefined

On Jul 24, 6:07 pm, Brian <or.else.it.gets.the.h...@gmail.com> wrote:
> $ ab -n 3000000 -c 100http://127.0.0.1:8000/
Reply all
Reply to author
Forward
0 new messages