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

silvioprog silvioprog at gmail.com
Tue Feb 17 17:49:07 CET 2015

On Tue, Feb 17, 2015 at 7:03 AM, Michael Van Canneyt <michael at freepascal.org
> wrote:
> 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.

Good! =)

After that I'll start the changes directly in custfcgi.

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.

You are right.

> 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.

Really, you are right! I made a confusion, because in other languages, most
of the time, HashSet() is more fast than ArrayList(). In Pascal it seems a
bit different (I need to do more tests after).

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.

Yes. I'll do it.

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

I don't want to use it anymore. Because you showed that an ordinary TFPList
is more fast than a THashSet.

> 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.

In this case, we could use a RTL ThreadList. Now I understand the internal
code (it is very simple), so I can use it correctly.

I'll wait you check my last changes in
"FastCGI_Proxy_nginx_Apache24_III.zip", so, after that, I'll go back to the
implementations directly in custfcgi, now using ThreadList. =)

Silvio Cl├ęcio
My public projects - github.com/silvioprog
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20150217/4d341e91/attachment.html>

More information about the fpc-pascal mailing list