[plt-scheme] PLT Web Server Memory Use

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Fri Dec 26 10:15:19 EST 2008

On Thu, Dec 25, 2008 at 10:41 PM, Henk Boom <lunarc.lists at gmail.com> wrote:
> Two things I'd like to note:
>
> For one, it looks like a significant part of the memory issues I was
> having before are due to non-trivial dispatching. If I use the virtual
> hosts dispatcher with this host->dispatcher function:
>
> (define (host->dispatcher host)
>  (let ((host-str (symbol->string host)))
>    (let-values (((clear-cache url->servlet)
>                  (servlets:make-cached-url->servlet
>                    (make-servlet-url->path host-str)
>                    (make-default-path->servlet))))
>      (sequencer:make
>        (files:make
>          #:url->path (make-file-url->path host-str)
>          #:path->mime-type path->mime-type)
>        (servlets:make url->servlet)))))
>
> mzscheme runs away gobbling up memory if I hold the refresh button in
> firefox for ~10 seconds (Its memory use rises continuously until I
> manually ^C it to death). Improving it with the following eliminates
> the problem.
>
> (define cached-host->dispatcher
>  (let ((cache (make-hasheq)))
>    (lambda (host)
>      (unless (hash-ref cache host #f)
>        (hash-set! cache host (host->dispatcher host)))
>      (hash-ref cache host))))
>
> I knew my host->dispatcher was not optimal (actually it is pretty
> wasteful) but I had no idea the consequences would be so drastic!

Yes, every time you were getting a request, you were creating a whole
bunch of closures and hash tables underneath those library calls. One
curious thing is that the servlet cache created in the first example
was never used, because a different servlet-dispatcher would be used
each time.

> The second thing, wouldn't it be useful to have something like the
> following included in the standard web server set of dispatchers?
>
> (define (make-limit-dispatcher num inner)
>  (let ((sem (make-semaphore num)))
>    (lambda (conn req)
>      (call-with-semaphore sem
>        (lambda () (inner conn req))))))
>
> This is a simple way of limiting the number of concurrent servlet
> instances running at once, and also helps to keep the memory use down.

I could add it. It _is_ 5 lines and really only one line matters. I
think I will add it to the FAQ.

Jay

-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://jay.teammccarthy.org

"The glory of God is Intelligence" - D&C 93


Posted on the users mailing list.