From: ·············@gmail.com
Subject: proxy server in lisp
Date: 
Message-ID: <1176283008.664987.227920@o5g2000hsb.googlegroups.com>
I had a great fun in my school project with lisp, i even make it a web
app
through hunchentoot, now i want to start a project  for myself,
something that will help me gain some experience and be useful.
I decided to make a proxy server so the hucnhentoot will stay behind
it.
So i have a few question:
Is writing proxy server very hard ? I'm very new to lisp < 1 month.
Does somebody has written proxy in common lisp
(a small one especially so i will have something to start with)?
Or some recommendation for some small proxy in c/c++.
Does  somebody see any benefit  of having a lisp proxy ?
I primary work on windows but i prefer a portable solution.

jt

From: Edi Weitz
Subject: Re: proxy server in lisp
Date: 
Message-ID: <u4pnnl0dc.fsf@agharta.de>
On 11 Apr 2007 02:16:48 -0700, ·············@gmail.com wrote:

> Is writing proxy server very hard ?

Depends on your experience with the HTTP protocol.

> Does somebody has written proxy in common lisp (a small one
> especially so i will have something to start with)?

AllegroServe contains proxy code.  You can look at it here:

  http://allegroserve.sourceforge.net/

> Does somebody see any benefit of having a lisp proxy ?

It definitely wouldn't hurt to have one.  Proxy servers can be nice if
you want to debug or programmatically modify HTTP traffic you
otherwise can't control.  (I once wrote a proxy server in Lisp, based
on TBNL, which filtered the traffic between a Java SyncML server and
cell phones connecting to it.  That was very helpful - and much more
fun than hacking the Java server itself.)

As you already played with Hunchentoot, you might consider to
implement your proxy server as some kind of add-on to Hunchentoot,
relying on its infrastructure.

HTH,
Edi.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: ·············@gmail.com
Subject: Re: proxy server in lisp
Date: 
Message-ID: <1176285741.317020.290430@n59g2000hsh.googlegroups.com>
On Apr 11, 11:35 am, Edi Weitz <········@agharta.de> wrote:
> On 11 Apr 2007 02:16:48 -0700, ·············@gmail.com wrote:
>
> > Is writing proxy server very hard ?
>
> Depends on your experience with the HTTP protocol.
>
nil,but i learn very fast(at least i think so).
> > Does somebody has written proxy in common lisp (a small one
> > especially so i will have something to start with)?
>
> AllegroServe contains proxy code.  You can look at it here:
>
>  http://allegroserve.sourceforge.net/
>
I'm currently learning  KPAX & s-http-server,  redit movies are very
interesthing,
but i'll look at allegroserve code too.

> > Does somebody see any benefit of having a lisp proxy ?
>
> It definitely wouldn't hurt to have one.  Proxy servers can be nice if
> you want to debug or programmatically modify HTTP traffic you
> otherwise can't control.  (I once wrote a proxy server in Lisp, based
> on TBNL, which filtered the traffic between a Java SyncML server and
> cell phones connecting to it.  That was very helpful - and much more
> fun than hacking the Java server itself.)
>
> As you already played with Hunchentoot, you might consider to
> implement your proxy server as some kind of add-on to Hunchentoot,
> relying on its infrastructure.

I guess i could do that at first, but later i wanna make independent
so lispfolks would be able to use it from other lisp servers .

BTW hunch' really rocks, it's very fast and easy to learn.
Do you have any idea how many  connections could support?

jt
From: Edi Weitz
Subject: Re: proxy server in lisp
Date: 
Message-ID: <uzm5fjk6g.fsf@agharta.de>
On 11 Apr 2007 03:02:21 -0700, ·············@gmail.com wrote:

> BTW hunch' really rocks, it's very fast and easy to learn.  Do you
> have any idea how many connections could support?

That'll depend on the Lisp you use and whether or not you're using
mod_lisp I'd say.  You'll have to experiment - maybe with ApacheBench.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: fireblade
Subject: Re: proxy server in lisp
Date: 
Message-ID: <1176363658.947399.26160@n76g2000hsh.googlegroups.com>
On Apr 11, 11:16 am, ·············@gmail.com wrote:
> I had a great fun in my school project with lisp, i even make it a web
> app
> through hunchentoot, now i want to start a project  for myself,
> something that will help me gain some experience and be useful.
> I decided to make a proxy server so the hucnhentoot will stay behind
> it.
> So i have a few question:
> Is writing proxy server very hard ? I'm very new to lisp < 1 month.
> Does somebody has written proxy in common lisp
> (a small one especially so i will have something to start with)?
> Or some recommendation for some small proxy in c/c++.
> Does  somebody see any benefit  of having a lisp proxy ?

Reverse proxy might be interesthing for speed up of static pages
but in my current demo i concentrated solely on dynamic pages
with user interaction.
Anyway you might consider something simpler first, like blog framework
or gallery.

cheers
bobi
From: Alex Mizrahi
Subject: Re: proxy server in lisp
Date: 
Message-ID: <4620d48d$0$90273$14726298@news.sunsite.dk>
(message (Hello ··············@gmail.com)
(you :wrote  :on '(11 Apr 2007 02:16:48 -0700))
(

 J> I had a great fun in my school project with lisp, i even make it a web
 J> app
 J> through hunchentoot, now i want to start a project  for myself,
 J> something that will help me gain some experience and be useful.
 J> I decided to make a proxy server so the hucnhentoot will stay behind
 J> it.
 J> So i have a few question:
 J> Is writing proxy server very hard ?

no.

 J> Does  somebody see any benefit  of having a lisp proxy ?

no.
you might need a reverse proxy to increase performance -- proxy in low-level 
language might be more efficient handling simple/static web requests. for 
example, it doesn't need GC. GC is a major threat for web servers -- while 
typically pages can be served in few milliseconds, when full GC will happen, 
that can stop everything for several seconds -- that is 1000 times slowdown 
for some requests. but if you have proxy, full GCs will be less frequent, 
and it will be able to server static content while doing GC, so there will 
be less impact. but if you'll do proxy with a language with GC model too, 
there will be less performance benefits (well, there could be some 
benefits..).
additionally, typically web servers in Lisp (and Java) have 
thread-per-connection, and that thread is quite heavy-weight, so you can 
have problems if you have many connections (slow clients, for example) -- it 
will eat lotsa RAM. (and all this threads are paralyzed during GC time). 
proxy can serve multiple connections with something like select() or 
multiple _lightweight_ theads.
actually, if you're using a proxy you can have only one server thread --  
handle requests one at a time, anyway handling multiple requests 
simultaneously typically isn't a good thing on single-core machine. thus, 
having proxy can simplify server code.

that's why it's better to use proxy that is not written in Lisp.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"I am everything you want and I am everything you need") 
From: Edi Weitz
Subject: Re: proxy server in lisp
Date: 
Message-ID: <ubqhr2hhu.fsf@agharta.de>
On Sat, 14 Apr 2007 16:18:34 +0300, "Alex Mizrahi" <········@users.sourceforge.net> wrote:

> that's why it's better to use proxy that is not written in Lisp.

Yes, it's always a good strategy to convince yourself that Lisp isn't
fast enough for what you're trying to do before you even start coding.
Saves a lot of trouble.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Alex Mizrahi
Subject: Re: proxy server in lisp
Date: 
Message-ID: <4622598b$0$90268$14726298@news.sunsite.dk>
(message (Hello 'Edi)
(you :wrote  :on '(Sat, 14 Apr 2007 15:49:33 +0200))
(

 ??>> that's why it's better to use proxy that is not written in Lisp.

 EW> Yes, it's always a good strategy to convince yourself that Lisp isn't
 EW> fast enough for what you're trying to do before you even start coding.
 EW> Saves a lot of trouble.

i just wanted to point that there is very little practical use of HTTP proxy 
written in Common Lisp.
or you do know some reason why one should write a proxy in Common Lisp 
instead of using existing one?

except educational purposes, certainly -- writting HTTP proxy is an excelent 
way to understand HTTP protocol.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"I am everything you want and I am everything you need") 
From: Edi Weitz
Subject: Re: proxy server in lisp
Date: 
Message-ID: <utzvhblhc.fsf@agharta.de>
On Sun, 15 Apr 2007 19:58:16 +0300, "Alex Mizrahi" <········@users.sourceforge.net> wrote:

> or you do know some reason why one should write a proxy in Common
> Lisp instead of using existing one?

Yes.  I gave one further up the thread.

-- 

Lisp is not dead, it just smells funny.

Real email: (replace (subseq ·········@agharta.de" 5) "edi")
From: Rainer Joswig
Subject: Re: proxy server in lisp
Date: 
Message-ID: <joswig-CFC87F.18163514042007@news-europe.giganews.com>
In article <·························@news.sunsite.dk>,
 "Alex Mizrahi" <········@users.sourceforge.net> wrote:

> (message (Hello ··············@gmail.com)
> (you :wrote  :on '(11 Apr 2007 02:16:48 -0700))
> (
> 
>  J> I had a great fun in my school project with lisp, i even make it a web
>  J> app
>  J> through hunchentoot, now i want to start a project  for myself,
>  J> something that will help me gain some experience and be useful.
>  J> I decided to make a proxy server so the hucnhentoot will stay behind
>  J> it.
>  J> So i have a few question:
>  J> Is writing proxy server very hard ?
> 
> no.
> 
>  J> Does  somebody see any benefit  of having a lisp proxy ?
> 
> no.
> you might need a reverse proxy to increase performance -- proxy in low-level 
> language might be more efficient handling simple/static web requests. for 
> example, it doesn't need GC. GC is a major threat for web servers -- while 
> typically pages can be served in few milliseconds, when full GC will happen,

That's where you start thinking about using a better GC
and about avoiding unnecessary consing. I'd say these are
standard practices - though sometimes when I'm reading about the response
to the ILC talks, the concept of controlling/reducing the consing
rate seems to be something alien, confusing and/or new.

Those who haven't figured it out yet, might look at the
Lisp Machine Manual from the early 80s:

Resources <http://common-lisp.net/project/bknr/static/lmman/resour.xml>
Areas <http://common-lisp.net/project/bknr/static/lmman/areas.xml>

GC related, check out the concept of an Ephemeral GC:
http://openmcl.clozure.com/Doc/index.html#The-Ephemeral-GC
 
> that can stop everything for several seconds -- that is 1000 times slowdown 
> for some requests. but if you have proxy, full GCs will be less frequent, 
> and it will be able to server static content while doing GC, so there will 
> be less impact. but if you'll do proxy with a language with GC model too, 
> there will be less performance benefits (well, there could be some 
> benefits..).
> additionally, typically web servers in Lisp (and Java) have 
> thread-per-connection, and that thread is quite heavy-weight, so you can 
> have problems if you have many connections (slow clients, for example) -- it 
> will eat lotsa RAM.

Thousand parallel connections will eat how much RAM do you think?
100 KB? Ten MB? 1 GB?

Though I agree that for certain performance demands one
needs a better strategy. One would need something like
the HTTP infrastructure of Scieneer Common Lisp.
<http://www.scieneer.com/scl/http.html>.
CL-HTTP runs on top of Scieneer CL, but does not currently
use that infrastructure - though one might ask Scieneer CL
support if one would be interested to fund such a thing.

> (and all this threads are paralyzed during GC time). 
> proxy can serve multiple connections with something like select() or 
> multiple _lightweight_ theads.
> actually, if you're using a proxy you can have only one server thread --  
> handle requests one at a time, anyway handling multiple requests 
> simultaneously typically isn't a good thing on single-core machine. thus, 
> having proxy can simplify server code.
> 
> that's why it's better to use proxy that is not written in Lisp.

You can always lose nicely with naively written Lisp software.
But why be so stupid?

> 
> )
> (With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
> "I am everything you want and I am everything you need")

-- 
http://lispm.dyndns.org
From: Alex Mizrahi
Subject: Re: proxy server in lisp
Date: 
Message-ID: <462255a4$0$90264$14726298@news.sunsite.dk>
(message (Hello 'Rainer)
(you :wrote  :on '(Sat, 14 Apr 2007 18:16:35 +0200))
(

 RJ> That's where you start thinking about using a better GC

almost all garbage collectors do full GC from time to time, having 
potentially large delay.

as far as i know, there is no incremental GC (that has deterministic pauses) 
implemented for Common Lisp.
moreover, i haven't seen concurrent GC implementation too..

 RJ> and about avoiding unnecessary consing.

if we speak about HTTP proxy, the best way to avoid consing (and also save 
some time) is to use one of ready proxies written in C.

 ??>> servers in Lisp (and Java) have thread-per-connection, and that thread
 ??>> is quite heavy-weight, so you can have problems if you have many
 ??>> connections (slow clients, for example) -- it will eat lotsa RAM.

 RJ> Thousand parallel connections will eat how much RAM do you think?
 RJ> 100 KB? Ten MB? 1 GB?

standard Windows applications have overhead of 1 MB per thread for a stack. 
so, 1000 connections will eat 1 GB of RAM.
it's possible to tune this stuff to eat less, but it's easier to just use 
proper tools..

 ??>> actually, if you're using a proxy you can have only one server thread
 ??>> --  handle requests one at a time, anyway handling multiple requests
 ??>> simultaneously typically isn't a good thing on single-core machine.
 ??>> thus, having proxy can simplify server code.
 ??>>
 ??>> that's why it's better to use proxy that is not written in Lisp.

 RJ> You can always lose nicely with naively written Lisp software.
 RJ> But why be so stupid?

external non-lisp proxy can be configured in some 10 minutes, and it can 
provide significant benefits for high traffic sites, saving time to be spent 
on optimizations of static content serving etc. so more time can be spent on 
more interesting tasks.
are there reasons not to use it, except mental masturbation?

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"I am everything you want and I am everything you need") 
From: Rainer Joswig
Subject: Re: proxy server in lisp
Date: 
Message-ID: <joswig-8EE2AE.22202915042007@news-europe.giganews.com>
In article <·························@news.sunsite.dk>,
 "Alex Mizrahi" <········@users.sourceforge.net> wrote:

> (message (Hello 'Rainer)
> (you :wrote  :on '(Sat, 14 Apr 2007 18:16:35 +0200))
> (
> 
>  RJ> That's where you start thinking about using a better GC
> 
> almost all garbage collectors do full GC from time to time, having 
> potentially large delay.

How long do you think a full GC of a GB real memory takes
on a current system? 

Why do you think an incremental generational GC should do
a full GC when there is no need to do so? I think you
haven't read the references I gave you on resources
and areas. What one does is to identify the larger
and longer living data structures (connections, threads,
buffers, headers, ...) and manage them as resource pools. There
is no garbage generated for them. With some care it is
possible to run with very little consing and what
you cons can be garbage collected with an ephemeral
collector.

> 
> as far as i know, there is no incremental GC (that has deterministic pauses) 
> implemented for Common Lisp.

What is a deterministic pause exactly and why do you need it for
a proxy? What is the reason you can't write a proxy for
Lisp? I mean there have been TCP stacks written in Lisp,
ATM switches, databases, real-time expert systems,
and other demanding applications. What makes a proxy special
that you can't write one in Lisp?

Check out the GCs from Franz and LispWorks. They have
a lot of knobs you can tweak.

Some years ago LispWorks ran on ATM switches from Lucent.
Guess what it had.

> moreover, i haven't seen concurrent GC implementation too..
> 
>  RJ> and about avoiding unnecessary consing.
> 
> if we speak about HTTP proxy, the best way to avoid consing (and also save 
> some time) is to use one of ready proxies written in C.

You'll never get a piece of Lisp code written with this attitude.
Plus you will never get Lisp systems advancing the state of the
art with this attitude.

> 
>  ??>> servers in Lisp (and Java) have thread-per-connection, and that thread
>  ??>> is quite heavy-weight, so you can have problems if you have many
>  ??>> connections (slow clients, for example) -- it will eat lotsa RAM.
> 
>  RJ> Thousand parallel connections will eat how much RAM do you think?
>  RJ> 100 KB? Ten MB? 1 GB?
> 
> standard Windows applications have overhead of 1 MB per thread for a stack. 
> so, 1000 connections will eat 1 GB of RAM.
> it's possible to tune this stuff to eat less, but it's easier to just use 
> proper tools..

Yeah, why use Windows. Use something better. Use a PC with
1 GB RAM, put Linux on top, some Lisp for it and you can
serve more than thousand connections with a Lisp proxy.



>  ??>> actually, if you're using a proxy you can have only one server thread
>  ??>> --  handle requests one at a time, anyway handling multiple requests
>  ??>> simultaneously typically isn't a good thing on single-core machine.
>  ??>> thus, having proxy can simplify server code.
>  ??>>
>  ??>> that's why it's better to use proxy that is not written in Lisp.
> 
>  RJ> You can always lose nicely with naively written Lisp software.
>  RJ> But why be so stupid?
> 
> external non-lisp proxy can be configured in some 10 minutes, and it can 
> provide significant benefits for high traffic sites, saving time to be spent 
> on optimizations of static content serving etc. so more time can be spent on 
> more interesting tasks.
> are there reasons not to use it, except mental masturbation?

It is about eating ones own dogfood and improving the tools. If one
always use something else, no wonder one is not able to
deploy any Lisp software. With some competent hackers one
can get surprisingly far. Much of the C software is not that
sophisticated (plus you get all the nice buffer overflows).
Writing a proxy is not that difficult. Writing a proxy
with some decent performance is an interesting exercise.

A Lisp written proxy also can be configured in a few minutes. So what.
Atleast I was able to set up one for me.

> (With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
> "I am everything you want and I am everything you need")

-- 
http://lispm.dyndns.org
From: Alex Mizrahi
Subject: Re: proxy server in lisp
Date: 
Message-ID: <46235945$0$90275$14726298@news.sunsite.dk>
(message (Hello 'Rainer)
(you :wrote  :on '(Sun, 15 Apr 2007 22:20:29 +0200))
(

 ??>> almost all garbage collectors do full GC from time to time, having
 ??>> potentially large delay.

 RJ> How long do you think a full GC of a GB real memory takes
 RJ> on a current system?

it depends on patterns of trees in memory and lots other values.

if we'd like to test web server workloads, let's do a benchmarking of UCW.

1. i've got latest ucw-dev. i'd be testing all default settings, examples 
head page. only modification i've made is shutting down loggers.
2. free say that i have used 20 MB of total memory 512 MB
3. i've loaded ucw, 82 MB are used now.

(time (gc :full t)) 0.35 seconds of real time

4. to stretch it

ab -n 30 -c 10 http://localhost:8080/
Percentage of the requests served within a certain time (ms)

  50%     89
  66%    220
  75%   1060
  80%   1082
  90%   1131
  95%   1151
  98%   1162
  99%   1162
 100%   1162 (longest request)

free says that 88 MB is used now.
5.
ab -n 5000 -c 10 http://localhost:8080/
  50%     20
  66%     25
  75%     29
  80%     33
  90%     48
  95%     78
  98%    267
  99%   3029
 100%  11754 (longest request)

as you can see, most requests take 20 mseconds, but longest takes 12 -- i 
bet connected with full GC. and there are some 50 requests that last for 3 
seconds.
cheking (time (gc :full t)) repors 2.1 seconds real time in repl.

memory allocated will grow as we test it, since UCW creates a dozen of 
continuations for each request it serves.
but currently we are only using 156 MB of 512.

6. next 5000 requests give us similar picture:

  50%     21
  66%     28
  75%     33
  80%     37
  90%     58
  95%     87
  98%    728
  99%   3017
 100%  10837 (longest request)

so it appears to be quite repeateable result.
we're using 255 MB RAM now -- starting approaching point when swapping will 
happen.

again, i'll do a full gc in repl, it takes 4.3 seconds now.

7. next 15000 requests killed the server -- SBCL said "Heap exhausted, game 
over".

unfortunately i don't have enough time to tune it and test more, but i think 
that GC time will scale aprox linearly, so for GB it can be as long as one 
minute. it gets especially problematic on an OS with VM -- it can swap out 
parts for memory that is not used -- for example, web server doesn't get 
much attention on weekend, but mailserver has some, so OS will swap web 
servers memory on disk. but on Monday people will come to see their web 
server, and once it will do full GC it will be totally disruptive -- it will 
need ALL it's 1 GB of RAM, and that would make lots of random accesses to 
disk, which are not fast.. so, people will see web server down for a few 
minutes..

 RJ> Why do you think an incremental

incremental never does full GC by it's definition.

 RJ>  generational GC should do a full GC when there is no need to do so? I
 RJ> think you
 RJ> haven't read the references I gave you on resources
 RJ> and areas. What one does is to identify the larger
 RJ> and longer living data structures (connections, threads,
 RJ> buffers, headers, ...) and manage them as resource pools. There
 RJ> is no garbage generated for them. With some care it is
 RJ> possible to run with very little consing and what
 RJ> you cons can be garbage collected with an ephemeral
 RJ> collector.

it's certainly possible to do so, but i think it's very hard for 
sufficiently complex application, and it will undermines whole idea of 
building web application in Common Lisp -- it will have too much 
restrictions, so it will be lots easier to build just some CGI-style 
application in PHP, that doesn't have such problems at all.

and how are you going to make framework like UCW consingless? as i've noted 
above, on each request UCW allocates a dozen of continuations and some 
object instances, that is quite a complex structure. this continuations will 
expire in some hours, so it's not possible to deallocate them with anything 
less than full GC.

 ??>> as far as i know, there is no incremental GC (that has deterministic
 ??>> pauses) implemented for Common Lisp.

 RJ> What is a deterministic pause exactly

you can find info about how deterministic GC is desired thing for some kinds 
of dynamic application is BEA JRockit white paper (it's for Java):

http://www.bea.com/content/news_events/white_papers/BEA_JRockit_Deterministic_GC_wp.pdf

they say they can limit garbage collection pause to 45 mseconds, while 
typical parallel GC typically takes more that 0.5 seconds, and even with 
Sun's incremental GC some requests can be paused for 0.5 seconds and more.

 RJ> and why do you need it for a proxy?

i don't want my clients wait for undefined period of time

 RJ>  What is the reason you can't write a proxy for Lisp?

it's possible, but there's really very little sense for it.

 ??>> if we speak about HTTP proxy, the best way to avoid consing (and also
 ??>> save some time) is to use one of ready proxies written in C.

 RJ> You'll never get a piece of Lisp code written with this attitude.
 RJ> Plus you will never get Lisp systems advancing the state of the
 RJ> art with this attitude.

i'm using Lisp for relatively complex and new tasks, which it is good for.
and if i can find a ready tool that does it task well -- like Apache serving 
static pages and doing proxying -- i'll be glad to use it.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"I am everything you want and I am everything you need") 
From: Espen Vestre
Subject: Re: proxy server in lisp
Date: 
Message-ID: <m1ps648rlt.fsf@gazonk.vestre.net>
"Alex Mizrahi" <········@users.sourceforge.net> writes:

> as you can see, most requests take 20 mseconds, but longest takes 12 -- i 
> bet connected with full GC. and there are some 50 requests that last for 3 
> seconds.
> cheking (time (gc :full t)) repors 2.1 seconds real time in repl.
>
> memory allocated will grow as we test it, since UCW creates a dozen of 
> continuations for each request it serves.
> but currently we are only using 156 MB of 512.

Hmm. Not very impressing GC duration.... What kind of hardware is this?

Here's what I get on one of our production PrimeTrader servers
(http-derived protocol) when doing a full gc:

("2007-04-16 11:00:16" "Global GC" :DO-GC :ROOM-BEFORE (:TOTAL-SIZE 520159 :TOTAL-ALLOCATED 249083 :TOTAL-FREE 270643)) 
("2007-04-16 11:00:16" "Global GC" :DO-GC :ROOM-AFTER (:TOTAL-SIZE 520159 :TOTAL-ALLOCATED 77836 :TOTAL-FREE 441891)) 
("2007-04-16 11:00:16" "Global GC" :DO-GC :STATS "freed 171247K in 428 ms cpu time") 

The data structures of this application is not kind to the GC, should
be worse than your average web application.  It had 130 active threads
at the time of the GC.  This is LispWorks 5.0 (4.x is not that good).

The HW is pretty cool, though: It's a 2 x Xeon 5160 ("Woodcrest"),
i.e. 4 cores running at 3Ghz, and with 8GB RAM. It runs 6 of these
server instances.

Here's another application that is a little more demanding, so I only
run global GCs at night. This is 64 bit LW on 64 bit linux, running
on a somewhat slower Woodcrest (2x 2x 2.33Ghz) with 12GB RAM:

("2007-04-16 03:00:35" "hourly-gc" :DO-GC :ROOM-BEFORE (:TOTAL-SIZE 5181468 :TOTAL-ALLOCATED 3983520 :TOTAL-FREE 780061)) 
("2007-04-16 03:00:35" "hourly-gc" :DO-GC :ROOM-AFTER (:TOTAL-SIZE 3847680 :TOTAL-ALLOCATED 2539243 :TOTAL-FREE 890920)) 
("2007-04-16 03:00:35" "hourly-gc" :DO-GC :STATS "freed 1444277K in 7904 ms cpu time") 

(8 seconds is too much, but the chance that the server needs attention
 from the applications that access it is very close to zero at 3
 o'clock in the morning. And after all, it does free 1.4GB ;))
-- 
  (espen)
From: Alex Mizrahi
Subject: Re: proxy server in lisp
Date: 
Message-ID: <46236a57$0$90270$14726298@news.sunsite.dk>
(message (Hello 'Espen)
(you :wrote  :on '(Mon, 16 Apr 2007 13:51:26 +0200))
(

 EV> Hmm. Not very impressing GC duration.... What kind of hardware is this?

Intel Core2 Duo E6400, 2MB L2, DDR2-667 memory. Linux is running in vmware, 
but i don't think it's a big issue, since other applications are running 
approx at same spead, including Java.

 EV> The data structures of this application is not kind to the GC, should
 EV> be worse than your average web application.

i think ucw is complex enough :)

 EV>   It had 130 active threads at the time of the GC.  This is LispWorks
 EV> 5.0 (4.x is not that good).

and i was benchmarking SBCL, i suspect LispWorks has a better GC.

 EV> Here's another application that is a little more demanding, so I only
 EV> run global GCs at night. This is 64 bit LW on 64 bit linux, running
 EV> on a somewhat slower Woodcrest (2x 2x 2.33Ghz) with 12GB RAM:

 EV> (8 seconds is too much, but the chance that the server needs attention
 EV>  from the applications that access it is very close to zero at 3
 EV>  o'clock in the morning. And after all, it does free 1.4GB ;))

that's quite a good result, but still you had to tune your system to avoid 
full GCs at day time..
i suspect that if Lisp had concurrent or incremental GC, it could handle 
such stuff automatically with less delays.

when i was playing with Java, i think it was able to avoid significant 
delays with concurrent GC when it was not flooded with requests -- it was 
able to do most GC job during pauses in requests. but i didn't do any 
serious benchmarking yet.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"I am everything you want and I am everything you need") 
From: Espen Vestre
Subject: Re: proxy server in lisp
Date: 
Message-ID: <m14png8pqj.fsf@gazonk.vestre.net>
"Alex Mizrahi" <········@users.sourceforge.net> writes:

> Intel Core2 Duo E6400, 2MB L2, DDR2-667 memory. Linux is running in vmware, 
> but i don't think it's a big issue, since other applications are running 
> approx at same spead, including Java.

No, that should be OK, I guess. And all the Core 2 processors are fine
for lisp (in stark contrast to all the P4-derived crap).

> and i was benchmarking SBCL, i suspect LispWorks has a better GC.

It's gotten quite decent in v. 5, it seems.

-- 
  (espen)
From: Rainer Joswig
Subject: Re: proxy server in lisp
Date: 
Message-ID: <joswig-3F9035.14432316042007@news-europe.giganews.com>
In article <·························@news.sunsite.dk>,
�"Alex Mizrahi" <········@users.sourceforge.net> wrote:

> (message (Hello 'Rainer)
> (you :wrote� :on '(Sun, 15 Apr 2007 22:20:29 +0200))
> (
>�
>� ??>> almost all garbage collectors do full GC from time to time, having
>� ??>> potentially large delay.
>�
>� RJ> How long do you think a full GC of a GB real memory takes
>� RJ> on a current system?
>�
> it depends on patterns of trees in memory and lots other values.
>�
> if we'd like to test web server workloads, let's do a benchmarking of UCW.

You never do a benchmark of UCW alone. It is always a combination
of application, host system, operating system, Lisp implementation,
32bit vs. 64bit mode, GC strategy.

>�
> 1. i've got latest ucw-dev. i'd be testing all default settings, examples�
> head page. only modification i've made is shutting down loggers.
> 2. free say that i have used 20 MB of total memory 512 MB
> 3. i've loaded ucw, 82 MB are used now.
>�
> (time (gc :full t)) 0.35 seconds of real time

Real time is what? The time of the user process, the time spend
in system plus what ever else happened on the machine. 

>�
> 4. to stretch it
>�
> ab -n 30 -c 10 http://localhost:8080/
> Percentage of the requests served within a certain time (ms)
>�
> � 50% � � 89
> � 66%� � 220
> � 75% � 1060
> � 80% � 1082
> � 90% � 1131
> � 95% � 1151
> � 98% � 1162
> � 99% � 1162
>� 100% � 116 (longest request)
>�
> free says that 88 MB is used now.
> 5.
> ab -n 5000 -c 10 http://localhost:8080/
> � 50% � � 20
> � 66% � � 25
> � 75% � � 29
> � 80% � � 33
> � 90% � � 48
> � 95% � � 78
> � 98%� � 267
> � 99% � 3029
>� 100%� 11754 (longest request)
>�
> as you can see, most requests take 20 mseconds, but longest takes 12 -- i�
> bet connected with full GC. and there are some 50 requests that last for 3�
> seconds.
> cheking (time (gc :full t)) repors 2.1 seconds real time in repl.
>�
> memory allocated will grow as we test it, since UCW creates a dozen of�
> continuations for each request it serves.
> but currently we are only using 156 MB of 512.
>�
> 6. next 5000 requests give us similar picture:
>�
> � 50% � � 21
> � 66% � � 28
> � 75% � � 33
> � 80% � � 37
> � 90% � � 58
> � 95% � � 87
> � 98%� � 728
> � 99% � 3017
>� 100%� 10837 (longest request)
>�
> so it appears to be quite repeateable result.
> we're using 255 MB RAM now -- starting approaching point when swapping will�
> happen.
>�
> again, i'll do a full gc in repl, it takes 4.3 seconds now.
>�
> 7. next 15000 requests killed the server -- SBCL said "Heap exhausted, game�
> over".

;-)

My MacBook Pro gives me with CL-HTTP and LispWorks 5 something like
this for 5000 requests of a static resource:

Percentage of the requests served within a certain time (ms)
  50%      7
  66%      7
  75%      8
  80%      8
  90%     10
  95%     11
  98%     12
  99%     13
 100%   2926 (last request)

It has a generational GC with 4 generations set up by default.
A full GC takes about 0.1 seconds.

>�
> unfortunately i don't have enough time to tune it and test more, but i think�
> that GC time will scale aprox linearly, so for GB it can be as long as one�
> minute. it gets especially problematic on an OS with VM -- it can swap out�
> parts for memory that is not used -- for example, web server doesn't get�
> much attention on weekend, but mailserver has some, so OS will swap web�
> servers memory on disk. but on Monday people will come to see their web�
> server, and once it will do full GC it will be totally disruptive -- it will�
> need ALL it's 1 GB of RAM, and that would make lots of random accesses to�
> disk, which are not fast.. so, people will see web server down for a few�
> minutes..

I'm not using SBCL and not UCW. My home web server runs without problems
for several months now. LispWorks has a much better GC than SBCL, I guess.

>�
>� RJ> Why do you think an incremental
>�
> incremental never does full GC by it's definition.

It does. If the incremental GC runs out of memory, then it will trigger
a full GC.

>�
>� RJ>� generational GC should do a full GC when there is no need to do so? I
>� RJ> think you
>� RJ> haven't read the references I gave you on resources
>� RJ> and areas. What one does is to identify the larger
>� RJ> and longer living data structures (connections, threads,
>� RJ> buffers, headers, ...) and manage them as resource pools. There
>� RJ> is no garbage generated for them. With some care it is
>� RJ> possible to run with very little consing and what
>� RJ> you cons can be garbage collected with an ephemeral
>� RJ> collector.
>�
> it's certainly possible to do so, but i think it's very hard for�
> sufficiently complex application,

Sufficiently complex applications are hard anyway.

> and it will undermines whole idea of�
> building web application in Common Lisp -- it will have too much�
> restrictions,

What kind of restrictions are you talking about?

> so it will be lots easier to build just some CGI-style�
> application in PHP, that doesn't have such problems at all.

>�
> and how are you going to make framework like UCW consingless? as i've noted�
> above, on each request UCW allocates a dozen of continuations and some�
> object instances, that is quite a complex structure. this continuations will�
> expire in some hours, so it's not possible to deallocate them with anything�
> less than full GC.

You, deallocate them when they are no longer needed.

Say, you have a session handling construct. When you start a session,
then you allocate the necessary data from a pool of resources.
When the session terminates, you give back the used resources to the pool.
Check out the reference to resources. There is a very simple API
to it.

>�
>� ??>> as far as i know, there is no incremental GC (that has deterministic
>� ??>> pauses) implemented for Common Lisp.
>�
>� RJ> What is a deterministic pause exactly
>�
> you can find info about how deterministic GC is desired thing for some kinds�
> of dynamic application is BEA JRockit white paper (it's for Java):
>�
> http://www.bea.com/content/news_events/white_papers/BEA_JRockit_Deterministic_GC_wp.pdf
>�
> they say they can limit garbage collection pause to 45 mseconds, while�
> typical parallel GC typically takes more that 0.5 seconds, and even with�
> Sun's incremental GC some requests can be paused for 0.5 seconds and more.

In main memory the time for the GC depends on the amount of
memory to look at. There is an upper bound for how long it takes
to GC a certain amount of memory. In a generational GC you
will scan a sufficiently small young generation, so that time
is small enough. Usually you can set up the number and sizes
of these generations with better GC implementations.
(same for Java, for several applications I was involved, the engineers
did a lot of GC profiling and were had tuning the GC).

>�
>� RJ> and why do you need it for a proxy?
>�
> i don't want my clients wait for undefined period of time
>�
>� RJ>� What is the reason you can't write a proxy for Lisp?
>�
> it's possible, but there's really very little sense for it.

There we obviously have different opinions.
�
>� ??>> if we speak about HTTP proxy, the best way to avoid consing (and also
>� ??>> save some time) is to use one of ready proxies written in C.
>�
>� RJ> You'll never get a piece of Lisp code written with this attitude.
>� RJ> Plus you will never get Lisp systems advancing the state of the
>� RJ> art with this attitude.
>�
> i'm using Lisp for relatively complex and new tasks, which it is good for.
> and if i can find a ready tool that does it task well -- like Apache serving�
> static pages and doing proxying -- i'll be glad to use it.
>�
> )
> (With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
> "I am everything you want and I am everything you need")�

-- 
http://lispm.dyndns.org
From: Alex Mizrahi
Subject: Re: proxy server in lisp
Date: 
Message-ID: <4623872b$0$90269$14726298@news.sunsite.dk>
(message (Hello 'Rainer)
(you :wrote  :on '(Mon, 16 Apr 2007 14:43:23 +0200))
(

 RJ> You never do a benchmark of UCW alone. It is always a combination
 RJ> of application, host system, operating system, Lisp implementation,
 RJ> 32bit vs. 64bit mode, GC strategy.

i'm not aiming for very accurate analysis, but i think it shows order of 
magnitude of numbers quite well.

 ??>> incremental never does full GC by it's definition.

 RJ> It does. If the incremental GC runs out of memory, then it will trigger
 RJ> a full GC.

hm, maybe there are different variants of incremental GC, but
i fail to see how Train Algorithm, described here: 
http://www.daimi.au.dk/~beta/Papers/Train/train.html
maybe some implementations can have problems, but BEA seem to guarantee that 
their collector doesn't take much time :)

 RJ> Sufficiently complex applications are hard anyway.

need for careful allocation can make it even much more harder, to the point 
it's impossible

 RJ> You, deallocate them when they are no longer needed.

 RJ> Say, you have a session handling construct. When you start a session,
 RJ> then you allocate the necessary data from a pool of resources.
 RJ> When the session terminates, you give back the used resources to the
 RJ> pool. Check out the reference to resources. There is a very simple API
 RJ> to it.

in my simple framework for each web form i generate i store a closure that 
captures current local variables, like

(let ((lotsa local variables))

 (let ((action-id (next-action-id)))
   (setf (aref actions action-id)
     (lambda () (do something with lotsa local variables)))
   (emit-hidden-input-with action-id)))

(when user will submit the form, control will be passed to that lambda)
UCW does similar thing, but 10+ times more complex. older version did CPS 
transform to create those lambdas automatically.

so, i capture different data into closures, and it can form quite complex 
trees in memory.

as i understand, it's not possible to create a pool of resources for 
closures.

so only solution -- not use closures. that's restrictions i'm speaking 
about.

)
(With-best-regards '(Alex Mizrahi) :aka 'killer_storm)
"I am everything you want and I am everything you need")