You are not logged in.
Pages: 1
I suggest adding the ability to create threadPool for TSQLHttpServer with custom ThreadClass.
Here is an example of pseudocode:
Type
TAPIServer = class(TSQLRestServerFullMemory)
...
published procedure ServerMethod(Ctxt: TSQLRestServerURIContext);
...
procedure TAPIServer.ServerMethod(Ctxt: TSQLRestServerURIContext);
var
Obj1 : TSomeObject;
Obj2 : TOtherObject;
...
begin
Obj1 := TSomeObject.Create;
Obj2 := TOtherObject.Create;
try
// Heavy creation
...
// Some calculations
...
// Network functions
Ctxt.Returns(AnyValue);
finally
Obj1.free;
Obj2.free;
end;
end;
In this example, for each call ServerMethod some amount of objects is created and destroyed.
Objects initialization can be costly both in time and in CPU, eg compiling a large number of regular expressions,
creating hash tables and so on. And all this is destroyed after the method is executed.
You can of course create a separate class, and call its methods through CriticalSection, but
with long calculations it will greatly slow down the server.
How to improve:
type TThreadClass = class of TSynThread;
..
TSQLHttpServer.Create(const aPort: AnsiString; aServer: TSQLRestServer;
const aDomainName: AnsiString='+';
aHttpServerKind: TSQLHttpServerOptions=HTTP_DEFAULT_MODE; aRestAccessRights: PSQLAccessRights=nil;
ServerThreadPoolCount: Integer=32; aHttpServerSecurity: TSQLHttpServerSecurity=secNone;
const aAdditionalURL: AnsiString=''; const aQueueName: SynUnicode=''; ThreadClass: TThreadClass);
The TSQLHttpServer constructor is called with a class reference ThreadClass.
When TSQLHttpServer is cloned, it creates threads with our class.
type
TMyThreadClass = class(TSynThread)
..
end;
consturctor TMyThreadClass.Create()
var
Obj1 : TSomeObject;
Obj2 : TOtherObject;
...
begin
Obj1 := TSomeObject.Create;
Obj2 := TOtherObject.Create;
// Heavy creation
end;
..
HttpServer := TSQLHttpServer.Create(Port, [APIServer], '+', useHttpApi, 32, false, TMyThreadClass);
In the ServerMethod we get the pointer on Thread, which currently serves THttpServerRequest
and call the thread method:
procedure TAPIServer.ServerMethod(Ctxt: TSQLRestServerURIContext);
var
MyTh : TMyThreadClass;
begin
MyTh := Ctxt.Thread as TMyThreadClass;
MyTh.calculation(Ctxt.inputUtf8['value1']);
Ctxt.Returns(MyTh.CalculatedValue);
end;
In this case, we noticeably speed up the processing of requests and reduce the load on the memory and CPU.
What do you think?
Offline
I don't understand your point.
Each method is already executed in its own thread, from the http server thread pool, so I don't see why creating a new thread may help here.
You are not even using your thread execution context - just its properties!
So if you want to re-use some existing resource, create a pool of resources.
Note that you have already some thread execution options for method-based services, with TSQLRest.AcquireExecutionMode[execSOAByMethod] property.
See https://synopse.info/files/html/Synopse … #TITLE_288
Offline
Each method is already executed in its own thread, from the http server thread pool, so I don't see why creating a new thread may help here
There is no need to create a new thread. If you pass a reference to a class, then create a thread inherited from TSynThread instead of plain TSynThread, by default create TSynThread as it is.
So if you want to re-use some existing resource, create a pool of resources.
Now it is implemented in this way. Only in this case the another thread pool is used.
Offline
How the thread is created depends on how the HTTP server is implemented.
It may be a from a thread pool, or not. It may inherit from TSynThread, but not directly.
Let the logic depend from this implementation detail is a wrong idea.
There are other cleaner options available, focusing on resources, not threads.
Your design is clearly breaking the Single Responsibility OOP Principle.
The cleanest way to handle such case may be to use a sicClientDriven interface-based service...
Offline
How the thread is created depends on how the HTTP server is implemented.
It may be a from a thread pool, or not. It may inherit from TSynThread, but not directly.Let the logic depend from this implementation detail is a wrong idea.
There are other cleaner options available, focusing on resources, not threads.Your design is clearly breaking the Single Responsibility OOP Principle.
The cleanest way to handle such case may be to use a sicClientDriven interface-based service...
I'm with Arnaud here. What you need sounds like some kind of ressource pool, not threadpool. If using interface base services in sicClientDriven mode is no option, then there's no other way then using custom ressource pools i guess.
Cheers.
Offline
Pages: 1