Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[ace-users] ACE_Task needs a lot of memory

30 views
Skip to first unread message

Spang, Oliver

unread,
Sep 22, 2006, 8:47:31 AM9/22/06
to ace-...@cs.wustl.edu
ACE VERSION: 5.5.2

HOST MACHINE and OPERATING SYSTEM:
Fedora Core 5

COMPILER NAME AND VERSION (AND PATCHLEVEL):
gcc 4.1.0 20060304 (Red Hat 4.1.0-3)

THE $ACE_ROOT/ace/config.h FILE [if you use a link to a platform-
specific file, simply state which one]:
config-linux.h

THE $ACE_ROOT/include/makeinclude/platform_macros.GNU FILE [if you
use a link to a platform-specific file, simply state which one
(unless this isn't used in this case, e.g., with Microsoft Visual
C++)]:
platform-linux.GNU

DOES THE PROBLEM AFFECT:
COMPILATION?
LINKING?
On Unix systems, did you run make realclean first?
EXECUTION?
OTHER (please specify)?
[Please indicate whether ACE, your application, or both are affected.]

SYNOPSIS:
[Brief description of the problem]
Each activated ACE_Task increases the used memory by ~10 MBytes

DESCRIPTION:
[Detailed description of problem. Don't just say "<blah>
doesn't work, here's a fix," explain what your program does
to get to the <blah> state. ]
In our application we use a lot of ACE_Tasks. As we ran out of memory,
we checked where this came from.
Using top we saw, that each call to activate () on an ACE_Task increased
the memory (column VIRT in top) by ~10MBytes.
Does ACE_Task really consume 10MBytes for each running instance?
Can we somehow decrease this?

REPEAT BY:
Here is a short example. I know that we should join and delete the
tasks, but that is not the problem. The problem is the memory
consumption while it is running.

#include "ace/Task.h"

class C_Task:public ACE_Task<ACE_MT_SYNCH>
{
public:
C_Task (void);
virtual int svc (void);
int close (u_long i);
~C_Task (void);
private:
};

C_Task::C_Task (void)
{
}

C_Task::~C_Task (void)
{
}

int C_Task::close (u_long)
{
delete this;
return 0;
}

int C_Task::svc (void)
{
int i=0;
printf ("C_MethodCaller start\n");

while (1)
{
printf ("loop %d\n", i++);
ACE_OS::sleep (1);
}

printf ("C_MethodCaller end\n");

return 0;
}

int main (int argc, char *argv[])
{
ACE_UNUSED_ARG (argc);
ACE_UNUSED_ARG (argv);

C_Task* pc_Task;

for (int i=0;i<100;i++)
{
pc_Task=new C_Task ();
if (pc_Task->activate (THR_NEW_LWP|THR_JOINABLE)==-1)
{
printf ("error in spawning thread (err_msg: %m)\n");
return -1;
}
}

while (1)
{
}

return EXIT_SUCCESS;
}


SAMPLE FIX/WORKAROUND:
[If available ]

Douglas C. Schmidt

unread,
Sep 22, 2006, 8:51:07 AM9/22/06
to Spang, Oliver, ace-...@cs.wustl.edu

Hi Oliver,

Thanks for using the PRF.

It depends on what the default size of a thread stack is on Linux.

> Can we somehow decrease this?

Sure, you can make the size of the stack as large/small as you want when
you activate() a task. Please see Chapter 6 of C++NPv2
<www.cs.wustl.edu/~schmidt/ACE/book2/> for more detalis.

Thanks,

Doug

> _______________________________________________
> ace-users mailing list
> ace-...@mail.cse.wustl.edu
> http://mail.cse.wustl.edu/mailman/listinfo/ace-users

Matthew Gillen

unread,
Sep 22, 2006, 9:21:30 AM9/22/06
to Spang, Oliver, ace-...@cs.wustl.edu
Spang, Oliver wrote:
> In our application we use a lot of ACE_Tasks. As we ran out of memory,
> we checked where this came from.
> Using top we saw, that each call to activate () on an ACE_Task increased
> the memory (column VIRT in top) by ~10MBytes.
> Does ACE_Task really consume 10MBytes for each running instance?

No. You're misinterpreting the 'top' output. Memory profiling on linux is
not always easy since it uses copy-on-write memory management for fork() and
pthread_create() calls. So even though it claims that it could be using up to
10MB/thread (if copy-on-write and other memory optimizations weren't used),
the actual use is much, much lower. You should be looking at the RES column,
that tells how much memory you're actually using.

Doing a quick test of your program on my box, heres what I get for 100 threads:
VIRT: 1005m RES: 3416
and for 10 threads:
VIRT: 104m RES: 1908

So, going by the RES field, each thread seems to add 150 *Bytes* of actual
memory usage. See this page for more info:
http://gentoo-wiki.com/FAQ_Linux_Memory_Management

> for (int i=0;i<100;i++)
> {
> pc_Task=new C_Task ();
> if (pc_Task->activate (THR_NEW_LWP|THR_JOINABLE)==-1)
> {
> printf ("error in spawning thread (err_msg: %m)\n");
> return -1;
> }
> }

By the way, activate() takes a parameter that tells it how many threads to
spawn, so you could replace the entire for loop above with this:
pc_Task=new C_Task();
int numberOfThreads = 100;
if (pc_Task->activate (THR_NEW_LWP|THR_JOINABLE, numberOfThreads) == -1)
{ ... }

Matt

Spang, Oliver

unread,
Sep 22, 2006, 9:49:12 AM9/22/06
to Matthew Gillen, ace-...@cs.wustl.edu
> No. You're misinterpreting the 'top' output. Memory
> profiling on linux is
> not always easy since it uses copy-on-write memory management
> for fork() and
> pthread_create() calls. So even though it claims that it
> could be using up to
> 10MB/thread (if copy-on-write and other memory optimizations
> weren't used),
> the actual use is much, much lower. You should be looking at
> the RES column,
> that tells how much memory you're actually using.
>
> Doing a quick test of your program on my box, heres what I
> get for 100 threads:
> VIRT: 1005m RES: 3416
> and for 10 threads:
> VIRT: 104m RES: 1908
In our real program we get VIRT: 3020m, after that we can't get any more
memory. I think this is because it's a 32Bit machine, so you can only
address 4GByte (theoretical, minus PCI address space --> ~3GByte)

I tried Dougs hint of explicitly setting the stack size, and it seems to
work.

Oliver

Spang, Oliver

unread,
Sep 22, 2006, 9:36:18 AM9/22/06
to Douglas C. Schmidt, ace-...@cs.wustl.edu
Hi Doug,

that was exactly the hint I was searching for.
Thank you.

regards,
Oliver

> -----Ursprüngliche Nachricht-----
> Von: sch...@tango.dre.vanderbilt.edu
> [mailto:sch...@tango.dre.vanderbilt.edu] Im Auftrag von
> Douglas C. Schmidt
> Gesendet: Freitag, 22. September 2006 14:51
> An: Spang, Oliver
> Cc: ace-...@cs.wustl.edu
> Betreff: Re: [ace-users] ACE_Task needs a lot of memory

> > In our application we use a lot of ACE_Tasks. As we ran out
> of memory,
> > we checked where this came from.
> > Using top we saw, that each call to activate () on an
> ACE_Task increased
> > the memory (column VIRT in top) by ~10MBytes.
> > Does ACE_Task really consume 10MBytes for each running instance?
>

> > for (int i=0;i<100;i++)
> > {
> > pc_Task=new C_Task ();
> > if (pc_Task->activate (THR_NEW_LWP|THR_JOINABLE)==-1)
> > {
> > printf ("error in spawning thread (err_msg: %m)\n");
> > return -1;
> > }
> > }
> >

0 new messages