[fpc-pascal] How to use FCGI in threaded mode?

Michael Van Canneyt michael at freepascal.org
Tue Feb 17 11:03:58 CET 2015



On Mon, 16 Feb 2015, silvioprog wrote:

> On Mon, Feb 16, 2015 at 7:23 AM, Michael Van Canneyt <michael at freepascal.org> wrote:
> Good.
> 
> But I don't know it we need two arrays, I think that a hash list will suit well, I'll explain it below ...
>  
>       - New Request comes in. - No thread to handle request is available in pool.
>       - Request is accepted and put in incoming requestsarray.
>       - Check outgoing response array, send back any responses.
>       - When Thread finishes a request, puts it in outgoing responses array.
>
>       Details will depend heavily on the way the pool is handled.
> 
> 
> ... I don't know if you tested the code that I sent you, but I've already done it, and in an unique array. =) The implemented structure works this way:
> 
> - the main acceptconn waits the first request;
> - after receiving the first request, the execution comes from the main acceptconn, creating a new thread, that has an own acceptconn;
> - the first open thread keep waiting for new requests in its own acceptconn, keeping the main acceptconn in 'stand-by'.
> 
> If an user make two or more later requests, it will call the acceptconn from the thread, and the main acceptconn will go on in stand-by. If a thread get in a long
> process (e.g: that 10 seconds loop), the main acceptconn it will call, that leaving from the stand-by status, creating a new thread, putting this new processing on
> it.

I will check your code.

> 
> In short, if a request is short, only one thread is created and one acceptconn is used; if a new request takes some time to be processed, the application opens a
> new thread to process the other requests.
> 
> Another thing: IMHO, it is interesting to use hash lists instead of commom arrays. A hash list has a internal generic array.

First of all, your sample code is simply wrong.

The threadlist is faster than the hashlist.

Change your code so that you 
a) Set the capacity of the list.
b) add the items to the LIST, not the CommomList:

CommomList := TThreadList.Create;
   try
     List := CommomList.LockList; //
     List.Capacity:=Count+1;
     for I := 1 to Count do
     begin
       Item := TFCGIThread.Create;
       Item.Name := 'thread_' + IntToStr(I);
       List.Add(Item); // adding to LIST not COMMOMLIST
     end;
    CommomList.UnlockList; // unlock

If you do that, you'll see that the list is about 30% faster.

home: >./mytest
Hash: 00:00:00.752 vs Common: 00:00:00.526

So an ordinary (common) list is faster.

Then: when you do such tests, you must do 2 test runs, with the order of the tests reversed.
The first of your 2 tests must always ask memory from the OS, because none is allocated yet. 
The second can re-use the memory and thus will be faster, this creates a skew in the result.

But then: where do you want to use a hash list  ?

I don't believe that iterating over a hashlist is very useful, for that you can use a list.

A hashlist is only useful if you need to do lookups based on a key. So what do you want to look up  ?
Threads ? I don't think that creating 150000 threads is a very realistic example. I'm not sure the OS can pull this :)
So, if you have 100 threads, this will be more than enough, and to use a hash list for 100 items seems a bit overkill.
Maybe I am missing something ?

But if you still, after all this, want to use a hashlist: use one from contnrs.pp, not the generics one.

Michael.


More information about the fpc-pascal mailing list