Re: Calling a C function using malloc() in a XS
by BrowserUk (Patriarch) on Aug 08, 2010 at 11:36 UTC
|
malloc() gets redefined by macro to one of the official memory allocation functions: Newx(), Newxc(), or Newxz(), but free() doesn't get redefined to Safefree().
The solution is to use the official apis, not the crt functions.
Or, if your memory allocations are never passed back to your perl code, #undef malloc at the top of your IC code.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] [select] |
Re: Calling a C function using malloc() in a XS
by ikegami (Patriarch) on Aug 08, 2010 at 18:02 UTC
|
void do_simulation() {
struct s* m;
m = (struct s*)malloc(10000000 * sizeof(struct s));
free(m);
m = (struct s*)malloc(10000000 * sizeof(struct s));
free(m);
}
use more memory than
void do_simulation() {
struct s* m = (struct s*)malloc(10000000 * sizeof(struct s));
free(m);
}
It could be that the memory is being pout back into Perl's free memory pool and you just don't realize it.
| [reply] [d/l] [select] |
Re: Calling a C function using malloc() in a XS
by Anonymous Monk on Aug 08, 2010 at 11:38 UTC
|
See perlclib, replacements for standard C library functions | [reply] |
Re: Calling a C function using malloc() in a XS
by Anonymous Monk on Aug 08, 2010 at 11:53 UTC
|
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "stdlib.h"
struct s {
int field1;
int field2;
int field3;
};
void do_simulation() {
int i;
struct s* m;
New(1, (struct s*)m, 10000000, struct s);
// do some computation with data
// but for simplifying things I'll do a simple initialization
for ( i=0; i<10000000; i++ ) {
m[i].field1 = 0;
m[i].field2 = 1;
m[i].field3 = 2;
}
Safefree(m);
}
MODULE = MyModule PACKAGE = MyModule
void
sim()
CODE:
do_simulation();
Tested in a mod_perl environment and the memory continues to add up for each request (the final destination of this module will be the mod_perl environment) | [reply] [d/l] |
|
|
The same problem with New() and Safefree()
I can't reproduce the problem using either malloc/free or New/safefree:
use warnings;
use Inline C => Config =>
BUILD_NOISY => 1;
use Inline C => <<'EOC';
struct s {
int field1;
int field2;
int field3;
};
void do_simulation() {
int i;
struct s * m = (struct s*)malloc(10000000 * sizeof(struct s));
for (i=0; i<10000000; i++) {
m[i].field1 = 0;
m[i].field2 = 1;
m[i].field3 = 2;
}
printf("Sleeping for 5\n");
sleep(5);
free(m);
printf("Memory freed ... sleep for another 5\n");
sleep(5);
printf("Done\n");
}
void do_simulation2() {
int i;
struct s* m;
New(1, (struct s*)m, 10000000, struct s);
for ( i=0; i<10000000; i++ ) {
m[i].field1 = 0;
m[i].field2 = 1;
m[i].field3 = 2;
}
printf("Sleeping for 5\n");
sleep(5);
Safefree(m);
printf("Memory freed ... sleep for another 5\n");
sleep(5);
printf("Done\n");
}
EOC
do_simulation();
do_simulation2();
For me (perl-5.12.0, Win32) the memory is freed as soon as free/Safefree is called.
Perhaps you're up against a feature of mod_perl ?
Cheers, Rob | [reply] [d/l] |
|
|
Thank you, Rob, for your participation and reproducing the code on your Win32/perl-5-12 environment. I described my problem bearing in mind perl 5.6 (I know, it's an old version ... maybe even an archaic one), but your perl version triggered my intention to try a more recent perl.
Firstly I wanted to try on a fresh environment. After reinstalling Win/MSVS6/Perl everything worked the same way ... Then I tried Perl 5.8 with the SAME (only #include "ppport.h" was added by h2xs) code and it worked correctly.
Maybe it's premature to state that it's a Perl 5.6 (more precisely ActiveState Perl 5.6.1 Build 638) bug, but Perl 5.8 doesn't have this memory leak problem.
Now I need to upgrade Perl/mod_perl. A last question would be what do you recommend for a 'not-enterprise production environment': 5.8, 5.10, or 5.12? Is there a stable mod_perl module built from 5.12 sources for Apache 2.2 (all Win32)? Or is it better to use mod_perl with Apache 2.0?
| [reply] |
|
|
|
|
|
|
|
|
|
You have #include "stdlib.h" after perl includes, get rid of it
| [reply] [d/l] |
|
|
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
struct s {
int field1;
int field2;
int field3;
};
void do_simulation() {
int i;
struct s * m = (struct s*)malloc(10000000 * sizeof(struct s));
for (i=0; i<10000000; i++) {
m[i].field1 = 0;
m[i].field2 = 1;
m[i].field3 = 2;
}
/* sleep for 5 seconds to be able to analyze memory usage
sleep(5);
free(m);
/* sleep for 5 seconds to be able to see if memory is freed
sleep(5);
}
int main(void) {
do_simulation();
return 1;
}
... and everithing works as it should: first 5 seconds the process uses 200+ MB (VM included), the last 5 seconds memory usage drops down to ~600 KB | [reply] [d/l] |
Re: Calling a C function using malloc() in a XS
by BrowserUk (Patriarch) on Aug 09, 2010 at 14:52 UTC
|
If you really need to do this, then go to the OS direct for the memory and you can guarantee to be able to give it back when you're done with it:
#! perl -slw
use 5.010;
use strict;
use Inline C => Config => BUILD_NOISY => 1;
use Inline C => <<'END_C', NAME => 'FreeMem', CLEAN_AFTER_BUILD => 0;
struct s {
int field1;
int field2;
int field3;
};
#define SIZE ((int)10e6 * sizeof( struct s ))
int test( SV *dummy ) {
char buf[256];
struct s *m;
printf( "CheckMem then enter"); gets( buf );
m= VirtualAlloc( NULL, SIZE, MEM_COMMIT, PAGE_READWRITE );
if( !m ) croak( "Couldn't allocate virtual memory: %d\n", GetLastE
+rror() );
printf( "CheckMem then enter"); gets( buf );
VirtualFree( m, SIZE, MEM_DECOMMIT );
printf( "CheckMem then enter"); gets( buf );
return 1;
}
END_C
test( 1 );
__END__
C:\test>freeMem-IC.pl
CheckMem then enter 7.5MB
CheckMem then enter 122.1MB
CheckMem then enter 7.7MB
-
-
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [d/l] |