Check out this further pool test,


Using apache 2.0.48


I defined tenbyte_string as the
constant string "0123456789"
which is 10 bytes long.

Here is a test where I used
apr_pstrcat( ... ) to
in a loop 10,000 iterations
so the resulting string
should only take up
10 * 10,000 = 100,000 bytes.

It took about 2.5 MB more than
the example child by itself in redhat 7.2
this is much better than apache 1.3.29

I ran this equivalent code on apache 1.3.29
redhat version 7.2 and it used nearly
400 Mega Bytes of RAM, with physical
RAM of only 128 MB

Does anybody know why this little loop uses so much
RAM?  Is there a problem with the way the code is
written?  Is it possible that apache has a pool problem?


The apache 2.0.48 source code follows:


-----------------------------------------------------------------------------------

#define tenbyte_string "0123456789"

void fun(void) {
        fprintf(stderr, "cannot create pool\n");
}

static int x_handler(request_rec *r)
{
        int i;
        apr_pool_t *subp1, *subp2, *p = r->pool;
        char *s = "";


if (strcmp(r->handler, "example-handler")) { return DECLINED; }

ap_set_content_type(r, "text/html");

    if (r->header_only) {
        return OK;
    }

ap_rputs(DOCTYPE_HTML_3_2, r);
ap_rputs("<HTML>\n", r);
ap_rputs(" <HEAD>\n", r);
ap_rputs(" <TITLE>mod_example Module Content-Handler Output\n", r);
ap_rputs(" </TITLE>\n", r);
ap_rputs(" </HEAD>\n", r);
ap_rputs(" <BODY>\n", r);
ap_rputs(" <H1><SAMP>mod_example</SAMP> Module Content-Handler Output\n", r);
ap_rputs(" </H1>\n", r);
ap_rputs(" <P>\n", r);
ap_rprintf(r, " Apache HTTP Server version: \"%s\"\n",
ap_get_server_version());
ap_rputs(" <BR>\n", r);
ap_rprintf(r, " Server built: \"%s\"\n", ap_get_server_built());
ap_rputs("<h1>hello world</h1><br>\n", r);
ap_rputs(" </BODY>\n", r);
ap_rputs("</HTML>\n", r);


        apr_pool_create_ex(&subp1, p, fun, NULL);
        apr_pool_create_ex(&subp2, p, fun, NULL);
        for (i = 0; i < 10000; i++) {
        apr_pool_clear(subp1);
            s = apr_pstrcat(subp1, s, tenbyte_string, NULL);
        apr_pool_clear(subp2);
        s = apr_pstrdup(subp2, s);
        }
        apr_pool_destroy(subp1);
        apr_pool_destroy(subp2);

    return OK;
}



-----------------------------------------------------------------------------------


Still in apache 2.0.48


Now set the loop iterations to 20,000
the child took 11 MB total and 75 seconds
Child never released the RAM till apache restarted.

Now set the loop iterations to 25,000
the child took 17 MB total and 120 seconds
Child never released the RAM till apache restarted.

Now set the loop iterations to 30,000
the child took 23 MB total and 180 seconds
Child never released the RAM till apache restarted.

Now set the loop iterations to 35,000
the child took 31 MB total and 250 seconds
Child never released the RAM till apache restarted.

Now set the loop iterations to 100,000
the child took over 100 MB total and over 1000 seconds
i killed the process before completion
Child never released the RAM till apache was stopped.

Just for fun I wrote some equivalent
code using calloc, strlen, strcpy,
free and pstrdup.  At 30,000 iterations
the child took 2.2 MB and 265 seconds.
Base child for mod_example was about 2 MB
when child was done child RAM usage
dropped back down to about 2 MB.


At 30,000 iterations: So malloc, calloc, free took about 1.5 times longer than apache. 265/180 = 1.472 but it only used a fraction of the RAM size of apache.




Conclusion: Apache 2.0.X pools are much more efficient in RAM allocation than apache 1.3.X pools and run in 2/3 the time as malloc, calloc and free.

If you are not using many iterations then you should use
apache pools because they are faster.  If you use
very many iterations in Apache 1.3.X you will run
out of RAM and bring down the server.

Also an apache child never released the RAM once it had allocated it.





--- Mark R. Rowe, MSEE




Reply via email to