Re: Asyncronous IO

2008-10-08 Thread Alexander Burger
Hi Konrad,

 sufficently abstract the URL space from the physical disk. Most other
 mature frameworks allow your to creat a completly virtual url space
 which has no relation to physical files on disk. The way the forms.l
 maps a full path to its javascript file and puts it in the output

Hmm, which path do you think of? There is only one .js file referenced
in form.l, and it appears as

   src=http://localhost/8080/lib/form.js;

 makes me particularly uncomfortable as it is exposing data on where I
 have installed picolisp.

so the only path that is exposed is lib/. Where do you see the
installation path? In general, the GUI only uses relative paths anyway.
(note: the /8080/ is not part of the path, but the port encoded for
httpGate).

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Henrik Sarvell
Sounds clever, but very complicated maybe to maintain the scheduling?
You mentioned multiplayer online games as a possibility, are the big
ones with thousands of simultaneous users already operating under
these principles? It would be great if you could point me to a
resource on the basics behind this way of doing things.

/Henrik
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread rand

Henrik, take a look at
http://docs.python.org/library/asyncore.html
There is even a few samples.  I have used this extensively, 
reimplemented it directly in C a time or two.


I think it would be relatively simple to implement using 'task' and 
'*Run'. 


Rand

Henrik Sarvell wrote:

Sounds clever, but very complicated maybe to maintain the scheduling?
You mentioned multiplayer online games as a possibility, are the big
ones with thousands of simultaneous users already operating under
these principles? It would be great if you could point me to a
resource on the basics behind this way of doing things.

/Henrik
  

--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Alexander Burger
On Wed, Oct 08, 2008 at 09:55:16PM +1100, konrad Zielinski wrote:
 I belive the issue is that I have actually installed picoLisp under
 usr/local but don't use it exclusivly from that directory. As such I

Ah, yes, in that case the path gets expanded. I didn't think about that,
because I always use it locally, with relative paths.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Henrik Sarvell
Konrad,

Thanks for the links and clarifications, here is another one:
http://en.wikipedia.org/wiki/Twisted_(software)

However, for really understanding what this is about this link that
you posted is very good: http://www.nightmare.com/medusa/medusa.html

From the above Medusa link: Most Internet servers are built on a
'forking' model.. It never states that this is in fact the case with
Apache but I get the feeling that this is in fact how Apache works, at
least the 1.x version which didn't do threading.

If this is the case then why is Apache the de facto standard? From the
Medusa page one gets the impression that forking is horribly
inefficient compared to the asynchronous way, but if this really was
the case an alternative to Apache based on this model would surely
have strong support. There is something missing here and I can't get
that missing piece. Please enlighten me.

Could this maybe be an explanation: A high-load server thus needs to
have a lot of memory. Many popular Internet servers are running with
hundreds of megabytes of memory.. Hundreds of megabytes was maybe a
lot at time of writing but is nothing now. Maybe technological
advancements simply solved the whole problem on the http side?

If I can be convinced that I'm not solving a non-existent problem then
I would be happy to help you with this if you want help.

/Henrik
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread rand

For even more discussions, look at http://www.acme.com/software/ and then
mini_httpd, micro_httpd, thttpd.  These are really lightweight http 
servers.  He did

a lot of work comparing threading, forking, and async IO.  Async IO wins big
for http serving.  Apache just happened to be at the right place at the 
right time,
it is by far NOT the most efficient http server. Apache 1 was only 
forking. With
modern UNIX memory management, forking is (was) not that expensive, and 
Apache
performed well. Today, apache has a zillion mod_* stuff, but even that 
is just

to speed up inefficiencies.  I really prefer NOT to put up apache, unless my
customer forces me to do so.  Most other servers perform better than apache,
but apache is just out there.

I started my work with python and medusa, one day switched to asyncore, and
then found picolisp.  I WILL NOT be going back.  It would be very 
interesting

to have a non-threading, non-forking model in picolisp based on 'task'.  The
more I think about it, it really is simple.  One just needs to get your 
head around
the concepts first and then around 'task'.  Picolisp also forks, but for 
other reasons,

the main one, it is completely integrated with it's database.  A lightweight
async 'task' model would indeed be an interesting alternative.


If this is the case then why is Apache the de facto standard? From the
Medusa page one gets the impression that forking is horribly
inefficient compared to the asynchronous way, but if this really was
the case an alternative to Apache based on this model would surely
have strong support. There is something missing here and I can't get
that missing piece. Please enlighten me.
  

Apache JUST HAPPENED to be there when http serving took
off.  At that moment in history, it was the best available solution.
Apache is where it is today for the same reason that Microsoft is
where it is.  A happenstance of history.

Just like Linux won out over BSD.  BSD was entangled in a lawsuit
with ATT at a critical junction of time, and Linux took off.  Had it
not been for the ATT / Berkeley lawsuit, I do not believe we would
have ever heard the word Linux.  Well some of us would have - I was
doing kernel work in 1991 when Linus released the first code.  Of
course we looked at it - and quickly said, no, let's use BSD - then in 1992
ATT screwed themselves with the lawsuit.  Do you hear much about
Bell Labs these days?  They do still exist.

Rand
--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread konrad Zielinski
Ahh,

I belive the issue is that I have actually installed picoLisp under
usr/local but don't use it exclusivly from that directory. As such I
get the following:

script src=http://localhost:8080//usr/local/picoLisp/lib/form.js;
type=text/javascript/script

which includes an absolure path to forms.js

regards

Konrad


On 08/10/2008, Alexander Burger [EMAIL PROTECTED] wrote:
 Hi Konrad,

 sufficently abstract the URL space from the physical disk. Most other
 mature frameworks allow your to creat a completly virtual url space
 which has no relation to physical files on disk. The way the forms.l
 maps a full path to its javascript file and puts it in the output

 Hmm, which path do you think of? There is only one .js file referenced
 in form.l, and it appears as

src=http://localhost/8080/lib/form.js;

 makes me particularly uncomfortable as it is exposing data on where I
 have installed picolisp.

 so the only path that is exposed is lib/. Where do you see the
 installation path? In general, the GUI only uses relative paths anyway.
 (note: the /8080/ is not part of the path, but the port encoded for
 httpGate).

 Cheers,
 - Alex
 --
 UNSUBSCRIBE: mailto:[EMAIL PROTECTED]

-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread konrad Zielinski
Henrik,

all of the references I'm aware of are based on Python.

the standard Python library includes modules called asyncore and asynchat
(sections 17.5 and 17.6 of the Python documentation.

The original Asyncronous webserver (as far as I'm aware) is medusa
http://www.nightmare.com/medusa/
http://www.amk.ca/python/code/medusa

Twisted is a more mature (read complex) implementation of the same
thing. At this stage i belive they have reimplemented everything and
don't even use the standard asyncore module anymore.

I use teisted at work and from the application developers point of
view the system allows complex applications to be built in very neat
small peices.  The approach has the advantage of not having the same
kind of concurrency issues as threaded code has.

By definition asyncronous code is only doing one thing at a time, so
there is no danger of two functions accessing the same data objects at
the same time, without the need for stemapors or locks. I believe that
the Erlang language uses a similer approach to implement its light
weight processes, and it allows them to scale to thousands of
processes.

regards

Konrad

On 08/10/2008, Henrik Sarvell [EMAIL PROTECTED] wrote:
 Sounds clever, but very complicated maybe to maintain the scheduling?
 You mentioned multiplayer online games as a possibility, are the big
 ones with thousands of simultaneous users already operating under
 these principles? It would be great if you could point me to a
 resource on the basics behind this way of doing things.

 /Henrik
 --
 UNSUBSCRIBE: mailto:[EMAIL PROTECTED]

-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread rand

Henrik Sarvell wrote:

Thanks Randall for that! So where do we start, where do I start, am I needed?
  

I just don't have time now to really look into it. :-(

Is the best way to simply review the Twisted source and reimplementing
in Pico, keeping the OODB in mind all the time maybe?
  

I would look at the simplest example, Medusa, first.
--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Tomas Hlavaty
Hi Konrad and Henrik,

 Is the best way to simply review the Twisted source and
 reimplementing in Pico, keeping the OODB in mind all the time maybe?

reading from http://en.wikipedia.org/wiki/Twisted_(software)

   Twisted supports an abstraction over raw threads=E2=80=94using a thread =
as
   a deferred source.

How threads fit in the Twisted framework?  I thought that Konrad's
idea was not to use threads or processes at all?

In case of forking, it is as efficient to use processes as using
threads, at least on Linux, as Rand already mentioned.  The advantage
of picoLisp is that the processes are small, say 3MB so you can have
many sessions and fork many times before you run out of memory.  This
is very hard to achieve with Common Lisp implementations (or Java) for
example, so people there need threads with their monster process.

I do not think Konrad could achieve single process/thread http server
without a bit of coding in C.  PicoLisp I/O operations block I think
and that is not good for this problem.  It would be at least hard to
make sure no operation blocks the process.

Maybe the best or most pragmatic way is splitting your web app into a
static files part that can be served by a specialized web server,
e.g. thttpd or nginx and a dynamic part served by picolisp.

It would be nice to see Konrad's aim come true though;-)

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Alexander Burger
Hi Tomas,

 I do not think Konrad could achieve single process/thread http server
 without a bit of coding in C.  PicoLisp I/O operations block I think

Not necessarily. If we use the select() mechanism provided by '*Run' and
'task', you can make input operations like 'listen', 'accept', 'read',
'rd' etc. non-blocking. In addition, I sometimes use the 'alarm'
function (in combination with 'catch', 'throw' and 'finally') to ensure
that no operation takes too long.


 Maybe the best or most pragmatic way is splitting your web app into a
 static files part that can be served by a specialized web server,

You do not need a specialized web server for that. A .html file will
be directly sent to the client, without any forking. And also .l files
do not automatically cause the fork, but only if (app) is called during
their execution.

For the (now obsolete) 7fach web portal the whole initial processig
consisted of non-forking pages (static html-files and dynamically
generated contents), and only when the user went to the login page it
happened that (app) was called.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


picoWiki

2008-10-08 Thread Tomas Hlavaty
Hi all,

I am implementing a wiki in picoLisp, see http://logand.com/picoWiki

Do you think it would be useful for the picoLisp comunity (can we call
it that way yet?) to have a wiki with publicly editable info about
picoLisp and related stuff?  If yes, any ideas and/or content
contributions welcome;-)

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Tomas Hlavaty
Hi Alex,

 In addition, I sometimes use the 'alarm' function (in combination
 with 'catch', 'throw' and 'finally') to ensure that no operation
 takes too long.

I don't think alarm is good enough though.  It is good for timeouts
but not for schedulling.

BTW: I found a typo in http://www.software-lab.de/refD.html#alarm
which should be http://www.software-lab.de/refA.html#alarm

 Not necessarily. If we use the select() mechanism provided by '*Run'
 and 'task', you can make input operations like 'listen', 'accept',
 'read', 'rd' etc. non-blocking.

How would this work, could you provide a simple example?

How would I know that 'read' does not have data available, or only
part of the data is available?  If I just use alarm (or maybe
something with smaller granularity) I would be wasting precious time
on timeouts.

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Alexander Burger
Hi Tomas,

 I don't think alarm is good enough though.  It is good for timeouts
 but not for schedulling.

True. I would not use if for scheduling, though, but to terminate
operations which might possibly take too long (e.g. 'connect' to another
server).


 BTW: I found a typo in http://www.software-lab.de/refD.html#alarm
 which should be http://www.software-lab.de/refA.html#alarm

Thanks! I fixed it in the testing release.


  Not necessarily. If we use the select() mechanism provided by '*Run'
  and 'task', you can make input operations like 'listen', 'accept',
  'read', 'rd' etc. non-blocking.
 
 How would this work, could you provide a simple example?

I posted some examples in my initial response to Konrad yesterday
(Message-ID: [EMAIL PROTECTED]).

For a single port, this could be

   (task (port ) # Listen on port 
  (when (accept @)   # A connect arrived
 (task @ # Install another task on this socket
Sock @   # Keep the socket in the task's env
(in Sock   # Data arrived on that socket
   (if (rd)   # read them
  (out Sock (eval @)) # Do something with the data
  (task Sock) # else we got EOF
  (close Sock) ) ) ) ) )  # and close the connection

This mechanism allows an arbitrary number of connections on port .

I have this mechanism very often for communication between different
systems. For communication with a browser you would better use (line)
instead of (rd), and send HTML-data instead of (eval @).


 How would I know that 'read' does not have data available, or only
 part of the data is available?

For the above communication between my own machines, I can guarantee
that no message received with the (rd) is longer than the system pipe
buffer size (at least 4096 bytes, larger on most systems). In that case
the (rd) will never block if select() said that data are available.

If you receive data from a browser, they may be larger. But I think this
will never make problems if you always read reasonable chunks (e.g.
chunked transfers, or character by character to be absolutely sure) in a
single step in the 'task' body. select() will either return immediately
when more data are available, or will not call the 'task' body, so
nothing will actually block.


 If I just use alarm (or maybe
 something with smaller granularity) I would be wasting precious time
 on timeouts.

Yes. So alarm is always just an additional security measure.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: picoWiki

2008-10-08 Thread Alexander Burger
Hi Tomas,

 I am implementing a wiki in picoLisp, see http://logand.com/picoWiki

Good idea! However, I did not succeed to connect (yet?).


 Do you think it would be useful for the picoLisp comunity (can we call
 it that way yet?)

Hehe, perhaps better call it a com-mini-ty ;-)

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: picoWiki

2008-10-08 Thread Alexander Burger
 http://logand.com/picoWiki

Ah, now it works! Seems I just had a temporary network problem.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: picoWiki

2008-10-08 Thread Tomas Hlavaty
Hi Alex,

 Good idea! However, I did not succeed to connect (yet?).

I just tried with w3m, looks like w3m messes up the relative links,
e.g. if I am at http://logand.com/picoWiki and have a relative link a
class=i href=?ChangesChanges/a, w3m will interpret it as
http://logand.com/?Changes. It works in Firefox though, i.e. it opens
http://logand.com/picoWiki?Changes page as intended.

I'll think how to do the links better.

Thanks,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Alexander Burger
Hi all,

oops, sorry! Forget what I wrote:

 A .html file will
 be directly sent to the client, without any forking. And also .l files
 do not automatically cause the fork, but only if (app) is called during
 their execution.

This was wrong. The 'server' function in lib/http.l will always fork
when a connection request arrives. It is just that the child process
immediately terminates after serving the connection (unless (app) was
called).


BTW, as a matter of an example, the 'server' function in lib/http.l
*does* implement a non-forking server, but only in the child process
once the initial connect from a client has created a session:

   ...
   (loop # Main loop in the parent process
  (setq *Sock (listen P))# Wait for a request
  (NIL (fork) (close P)) # The child closes 'P' and exits the loop
  (close *Sock) )# The parent closes the new connection and 
continues
   (task *Sock (http @)) # The child installs a task on that socket
   (http *Sock)  # and serves the first page
   (or *SesId (bye)) # If (app) was not called, terminate
   (task *Sock   # Else install a task for the new session 
socket
  (when (accept *Sock)  # Accept requests on that socket
 (task @ (http @))  # without forking
 (http @) ) ) )


Note: This uses in two places a construct of the form

   (task socket (http socket))
   (http socket)

The reason for that is that for HTTP/1.1 more than one transaction may
be done before the connection is closed.

Hope this helps.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread konrad Zielinski
Hi All,

In the matter of how to begin. Twisted is I think the wrong place. It
is a very large and complicated beast which has grown in its own
unquie direction. So much so that it is incompatable with a lot of
standard python tools and libraries, uses its own logging system etc.

In copying python the place to start are Asyncore and Asynchat. The
Medusa pages had some basic examples of building an asyncronous client
and then an asyncronous proxy.

I intend to try to build these things and satisfy myself that I'm
really getting asyncronous behaviour.

After that I'm thinking that a good proof of concept application would
be a basic instant messanger which allows multiple users to connect
and send messages to each other. this is a nice application which has
shared state without needing a particularly fancy interface.

As this is a personal project, I'm happy to share code, questions and
comments through this list if there is interest.

A similer Tic Tac Toe server which allows multiple simultainous games
and routes moves to the correct clients would also be nice.

Then its on to the main event. where more care is needed in working
out what functions are needed and how additional functionality should
be hooked into the system. Here I would be aiming to build a generic
UDP and TCP server that is as adaptable as Medusa and Twisted.

At this point, if there is enough interest. putting code on
Sourceforge or Google code might be worth while. Heck it might even
give pico Lisp some extra publicity. (I note this list has been
getting a little more lively lately, which is a good sign).

And can be used as a base for any protocol anyone chooses to throw at it.

One reason why the Async approach is well suited to python is due to
limitations in the Python interpreter. Python has something called a
Global interpreter lock, which restricts it to using a single CPU,
even if threading primitives are used. Ergo threading primities become
an overhead which increases code complexity without giving increased
scalability.

I believe that picoLisp has similer single CPU limitation, I'm pretty
sure that there are no threading primitives. So the only possible
choices are Asyncronous or Forking. The latter makes shared state
somewhat difficult to manage, and exists allready (so there is nothing
new to build).

2008/10/9 Alexander Burger [EMAIL PROTECTED]:
 Hi all,

 oops, sorry! Forget what I wrote:

 A .html file will
 be directly sent to the client, without any forking. And also .l files
 do not automatically cause the fork, but only if (app) is called during
 their execution.

 This was wrong. The 'server' function in lib/http.l will always fork
 when a connection request arrives. It is just that the child process
 immediately terminates after serving the connection (unless (app) was
 called).


 BTW, as a matter of an example, the 'server' function in lib/http.l
 *does* implement a non-forking server, but only in the child process
 once the initial connect from a client has created a session:

   ...
   (loop # Main loop in the parent process
  (setq *Sock (listen P))# Wait for a request
  (NIL (fork) (close P)) # The child closes 'P' and exits the loop
  (close *Sock) )# The parent closes the new connection and 
 continues
   (task *Sock (http @)) # The child installs a task on that socket
   (http *Sock)  # and serves the first page
   (or *SesId (bye)) # If (app) was not called, terminate
   (task *Sock   # Else install a task for the new session 
 socket
  (when (accept *Sock)  # Accept requests on that socket
 (task @ (http @))  # without forking
 (http @) ) ) )


 Note: This uses in two places a construct of the form

   (task socket (http socket))
   (http socket)

 The reason for that is that for HTTP/1.1 more than one transaction may
 be done before the connection is closed.

 Hope this helps.

 Cheers,
 - Alex
 --
 UNSUBSCRIBE: mailto:[EMAIL PROTECTED]

-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Tomas Hlavaty
Hi Alex,

  Not necessarily. If we use the select() mechanism provided by '*Run'
  and 'task', you can make input operations like 'listen', 'accept',
  'read', 'rd' etc. non-blocking.

select() does not make thinks non-blocking as far as I am aware.  It
just wakes up the process when something is going on.

I think that to be non-blocking, all I/O operations must be able to
say how much data to read/write without blocking.

 I posted some examples in my initial response to Konrad yesterday
(if (rd)   # read them
   (out Sock (eval @)) # Do something with the data

I think these two lines are the problematic ones.

 I have this mechanism very often for communication between different
 systems. For communication with a browser you would better use (line)
 instead of (rd), and send HTML-data instead of (eval @).

Does not (line) try to read until eol or eof?  That could block if the
client is naughty or something happens (like delay while receiving
the line and being in the middle of it).  Also,
http://www.software-lab.de/refL.html#line says

   Note that a single carriage return may not work on network
   connections, because the character look-ahead to distinguish from
   return+linefeed can block the connection.

 How would I know that 'read' does not have data available, or only
 part of the data is available?

 For the above communication between my own machines, I can guarantee
 that no message received with the (rd) is longer than the system pipe
 buffer size (at least 4096 bytes, larger on most systems). In that case
 the (rd) will never block if select() said that data are available.

How can you guarantee that? Simply by sending little data or some
special protocol?

Also, that is a very special case.  I don't think you can make such
assumptions with HTTP server where you don't have the clients under
control.

 If you receive data from a browser, they may be larger. But I think this
 will never make problems if you always read reasonable chunks (e.g.
 chunked transfers, or character by character to be absolutely sure) in a
 single step in the 'task' body. select() will either return immediately
 when more data are available, or will not call the 'task' body, so
 nothing will actually block.

How big is a reasonable chunk?  What if something happens (a delay)
with the client in the middle of sending the chunk?

Would not reading by character loose the magic of striving for
supercalifragilisticexpialidoucious server?;-)


Also, not blocking is only a part of the story, what about
schedulling?  If two people share a computer say with MS-DOS, one must
go for a coffee and wait until the other one finished.  If they use
UNIX, they can work simultaneously because the system splits the time
between them in tiny chunks which they don't notice.  The non-forking
server in picolisp is of the first kind.  Once the server is serving a
request, everything else (all the other requests) have to wait until
it is finished with the current task.

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread Tomas Hlavaty
Hi Alex,

thanks for the explanation!

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Asyncronous IO

2008-10-08 Thread konrad Zielinski
Hi Alex,

 your response to Tomas's questions dosn't seem to have made it to the list.

Most of the documentation I have seen seems to suggest that Sockets
need to be put into non blocking mode explicitly, ie using select() is
not sufficent. At a low level attempting to read from a nonblocking
socket will return a Would Block error condition.

Is the picoLisp socket and task code allready setting sockets into non
blocking mode?

regards

Konrad.

2008/10/9 Tomas Hlavaty [EMAIL PROTECTED]:
 Hi Alex,

 thanks for the explanation!

 Tomas
 --
 UNSUBSCRIBE: mailto:[EMAIL PROTECTED]

-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]