Process pool thread pool

The concept of pool

Because the hardware resources of the server are "abundant", a direct way to improve the performance of the server is to exchange space for time, that is, to "waste" the hardware resources of the server in exchange for its operational efficiency. This is the concept of pool. A pool is a collection of resources that are created and initialized completely at the beginning of server startup, which is called static resource allocation. When the server enters the formal operation stage, that is, when it begins to process customer requests, if it needs related resources, it can be obtained directly from the pool without dynamic allocation. Obviously, getting resources directly from the pool is much faster than dynamically allocating resources, because system calls that allocate system resources are time-consuming. When a client connection is processed by the server, the related resources can be put back into the pool without performing system calls to release the resources. In the end, the pool is equivalent to the application facility of the server management system resources, which avoids the frequent access of the server to the kernel.

Pools can be divided into many kinds, including memory pool, process pool, thread pool and connection pool.

Memory pool

Memory pool is a memory allocation method. Usually we are accustomed to using system calls such as new and malloc to apply for allocation of memory directly. The disadvantage of this method is that because the size of the applied memory block is variable, it will cause a large number of memory fragments and reduce performance when used frequently.

Memory pool is to apply for allocation of a certain number of memory blocks of equal size (in general) to be reserved before the real use of memory. When there is a new memory requirement, a part of the memory block is separated from the memory pool, and if the memory block is insufficient, the application for new memory will not continue. A significant advantage of this approach is that it improves the efficiency of memory allocation.

Process pool and thread pool

The process pool is similar to the thread pool, so here we take the process pool as an example. If there is no special declaration, the following description of process pools is also applicable to thread pools.

The process pool is a set of pre-created sub-processes by the server, with the number of these sub-processes ranging from 3 to 10 (this is a typical case, of course). The number of threads in the thread pool should be about the same as the number of CPU s.

All the subprocesses in the process pool run the same code and have the same attributes, such as priority, PGID, etc.

When a new task arrives, the main process will somehow select a subprocess in the process pool to serve it. The cost of choosing an existing subprocess is much less than creating a subprocess dynamically. As for which sub-process the main process chooses to serve the new task, there are two ways:

1) The main process uses some algorithm To actively select subprocesses. The simplest and most commonly used algorithms are random algorithm and Round Robin (rotation algorithm).

2) The main process and all the sub-processes are synchronized through a shared work queue on which the sub-processes sleep. When new tasks arrive, the main process adds tasks to the work queue. This will wake up the child process waiting for the task, but only one child process will get the "take-over" of the new task, which can take the task out of the work queue and execute it, while the other child processes will continue to sleep on the work queue.

After selecting the sub-process, the main process also needs to use some notification mechanism to tell the target sub-process that new tasks need to be processed and to pass the necessary data. The simplest way is to pre-establish a pipeline between parent and child processes, and then use the pipeline to achieve all inter-process communication. Transferring data between parent and child threads is much simpler, because we can define these data as global, so they are shared by all threads themselves.

Thread pool is mainly used for:

1) A large number of threads are needed to complete the task, and the time to complete the task is relatively short. For example, WEB server completes the task of web page request, using thread pool technology is very suitable. Because a single task is small, and the number of tasks is huge. But for long-term tasks, such as a Telnet connection request, the advantages of thread pooling are not obvious. Because Telnet session time is much longer than thread creation time.

2) Applications with high performance requirements, such as requiring servers to respond quickly to customer requests.

3) Accept a large number of sudden requests, but not so that the server will produce a large number of threads of application.

Process City implementation source code:

How to Linux Implementation of process pool technology, original post:
http://topic.csdn.net/u/20090206/16/b424e1c1-90dc-4589-a63f-1d90ed6560ae.html.

  1. //Master Receiving Network Message Processes  
  2. int main()  
  3. {  
  4.     int iReLen;  
  5.     char szBuffer[64];  
  6.     ...  
  7.     //Initialization process pool  
  8.     InitProcessPoll();  
  9.     ....  
  10.     while(1)  
  11.     {  
  12.         iRelen = recv(iSock, szBuffer, sizeof(szbuffer), 0);  
  13.         if (iRelen > 0)  
  14.         {  
  15.             SubmitWork(szBuffer, iRelen);   //Submit work to resource process  
  16.         }     
  17.     }  
  18.     ...  
  19. }  
  20.   
  21. //  
  22. int SubmitWork(void *pBuffer, int iMsgLen)  
  23. {  
  24.     int iMsgQueID;  
  25.       
  26.     iMsgQueID = GetMsgQue(key, 0); //Get more handle to the message team that communicates with the management process;  
  27.       
  28.     msgsnd(iMsgQueID, pBuffer, iMsgLen, 0);  
  29. }  
  30.   
  31. int InitProcessPoll(const int iProcessNum)  
  32. {  
  33.     int iPid;  
  34.       
  35.     //Create a management process  
  36.     iPid = fork();  
  37.     if (iPid == 0)  
  38.     {  
  39.         InitMngProcess(iProcessNum);  
  40.     }     
  41.     return 0;  
  42. }  
  43.   
  44. typedef struct  
  45. {  
  46.     int pid;  
  47.     int iFlag;  
  48. } T_ProcessStatus;  
  49.   
  50. //Pointing to Resource Process Management Architecture  
  51. T_ProcessStatus *pProcessMng = NULL;  
  52.   
  53. //Record how many resource processes are there in total  
  54. INT32 iMaxProcessNum = 0;  
  55.   
  56. //Initially manages the process management structure and creates resource subprocesses, and finally receives external work requests and distributes them to resources for processing.  
  57. InitMngProcess(const int iProcessNum)  
  58. {  
  59.     int i;  
  60.     int iPid;  
  61.     int iRtn;  
  62.     int iMsgLen;  
  63.     int iMsgQue1, iMsgQue2;  
  64.     char szBuffer[64];  
  65.       
  66.     //Create a management process structure  
  67.     pProcessMng = calloc(iProcessNum, sizeof(T_ProcessStatus))  
  68.   
  69.     for (i = 0; i < iProcessNum; i++)  
  70.     {  
  71.         iPid = fork();  
  72.         if (iPid == 0);  
  73.         {  
  74.             //Resource process;  
  75.             ResourceProcess();  
  76.         }  
  77.         pProcessMng[i].pid = iPid; //Process number for recording resource processes  
  78.         pProcessMng[i].iFlag = 0;   //Leave resource processes idle  
  79.     }  
  80.       
  81.     iMaxProcessNum = iProcessNum;  
  82.   
  83.     //Create a message queue that communicates externally with the management process;  
  84.     iMsgQue1 = CreateMsgQue();  
  85.   
  86.     //Create a message queue for the management process to communicate with the resource process;  
  87.     iMsgQue2 = CreateMsgQue();  
  88.   
  89.     //Install the Resource Process Recycling Signal Processing Function  
  90.     signal(SIGUSR1, ReleaseAProcess);     
  91.   
  92.     //Start receiving external incoming tasks  
  93.     while(1)  
  94.     {  
  95.         //Receiving external work requests  
  96.         iMsgLen = msgrcv(iMsgQue1, szBuffer, sizeof(szBuffer), 0);  
  97.           
  98.         //Forwarding Work Request to Resource Process Processing Message Queue  
  99.         iRtn = msgsnd(iMsgQue2, szBuffer, iMsgLen, 0);  
  100.       
  101.         //Notify one of the idle resource processes for processing  
  102.         NoticeAIdleProcess();  
  103.     }  
  104. }  
  105.   
  106. //Notify an idle resource process for processing  
  107. int NoticeAIdleProcess()  
  108. {  
  109.     int i;  
  110.       
  111.     for (i = 0; i < iMaxProcessNum; i++)  
  112.     {  
  113.         if (pProcessMng[i].iFlag == 0)  
  114.         {  
  115.             pProessMng[i].Flag = 1;  
  116.             kill(processMng[i].pid, SIGUSR1);  
  117.             return 0;  
  118.         }  
  119.     }  
  120.       
  121.     return -1;    
  122. }  
  123.   
  124. //Recycling a resource process that has been processed  
  125. void ReleaseAProcess(int iPid)  
  126. {  
  127.     int i;  
  128.       
  129.     for (i = 0; i < iMaxProcessNum; i++)  
  130.     {  
  131.         if (pProessMng[i].pid == iPid)  
  132.         {  
  133.             pProcessMng[i].iFlag = 0;  
  134.             return;  
  135.         }  
  136.     }  
  137.   
  138.     return;  
  139. }  
  140.   
  141. //Processing of resource processes  
  142. void ResourceProcess()  
  143. {  
  144.     //Signal Processing with Work Notification Installed  
  145.     signal(SIGUSR1, SIG_IGN);  
  146.   
  147.     //Settings are only interested in SIGUSR1 signals  
  148.     sigprocmask()  
  149.     while(1)  
  150.     {  
  151.         //Suspend without message processing  
  152.         pause();  
  153.           
  154.         //Processing  
  155.         void StartWork()  
  156.   
  157.         //Notify the management process that the work is completed  
  158.         NoticeMngProcessFinishedWork();   
  159.     }  
  160. }  
  161.   
  162. //Processing messages  
  163. void StartWork()  
  164. {  
  165.     char szBuffer[64];  
  166.     int iMsgID;  
  167.     int iRtn;  
  168.       
  169.     iMsgID = msgget();  
  170.     iRtn = msgrcv(iMsgID, szBuffer, sizeof(szBuffer), 0);  
  171.       
  172.     //Now that you have a message that needs to be processed in the child process, you can start processing the message until the message processing is complete.  
  173.   
  174.     return;   
  175. }  
  176.   
  177. //Notify the management process of the resource recovery process  
  178. void NoticeMngProcessFinishedWork();  
  179. {  
  180.     kill(MngProcessPid, SIGUSR1);  
  181.       
  182.     return;  
  183. }  

  1. //Master Receiving Network Message Processes  
  2. int main()  
  3. {  
  4.     int iReLen;  
  5.     char szBuffer[64];  
  6.     ...  
  7.     //Initialization process pool  
  8.     InitProcessPoll();  
  9.     ....  
  10.     while(1)  
  11.     {  
  12.         iRelen = recv(iSock, szBuffer, sizeof(szbuffer), 0);  
  13.         if (iRelen > 0)  
  14.         {  
  15.             SubmitWork(szBuffer, iRelen);   //Submit work to resource process  
  16.         }     
  17.     }  
  18.     ...  
  19. }  
  20.   
  21. //  
  22. int SubmitWork(void *pBuffer, int iMsgLen)  
  23. {  
  24.     int iMsgQueID;  
  25.       
  26.     iMsgQueID = GetMsgQue(key, 0); //Get more handle to the message team that communicates with the management process;  
  27.       
  28.     msgsnd(iMsgQueID, pBuffer, iMsgLen, 0);  
  29. }  
  30.   
  31. int InitProcessPoll(const int iProcessNum)  
  32. {  
  33.     int iPid;  
  34.       
  35.     //Create a management process  
  36.     iPid = fork();  
  37.     if (iPid == 0)  
  38.     {  
  39.         InitMngProcess(iProcessNum);  
  40.     }     
  41.     return 0;  
  42. }  
  43.   
  44. typedef struct  
  45. {  
  46.     int pid;  
  47.     int iFlag;  
  48. } T_ProcessStatus;  
  49.   
  50. //Pointing to Resource Process Management Architecture  
  51. T_ProcessStatus *pProcessMng = NULL;  
  52.   
  53. //Record how many resource processes are there in total  
  54. INT32 iMaxProcessNum = 0;  
  55.   
  56. //Initially manages the process management structure and creates resource subprocesses, and finally receives external work requests and distributes them to resources for processing.  
  57. InitMngProcess(const int iProcessNum)  
  58. {  
  59.     int i;  
  60.     int iPid;  
  61.     int iRtn;  
  62.     int iMsgLen;  
  63.     int iMsgQue1, iMsgQue2;  
  64.     char szBuffer[64];  
  65.       
  66.     //Create a management process structure  
  67.     pProcessMng = calloc(iProcessNum, sizeof(T_ProcessStatus))  
  68.   
  69.     for (i = 0; i < iProcessNum; i++)  
  70.     {  
  71.         iPid = fork();  
  72.         if (iPid == 0);  
  73.         {  
  74.             //Resource process;  
  75.             ResourceProcess();  
  76.         }  
  77.         pProcessMng[i].pid = iPid; //Process number for recording resource processes  
  78.         pProcessMng[i].iFlag = 0;   //Leave resource processes idle  
  79.     }  
  80.       
  81.     iMaxProcessNum = iProcessNum;  
  82.   
  83.     //Create a message queue that communicates externally with the management process;  
  84.     iMsgQue1 = CreateMsgQue();  
  85.   
  86.     //Create a message queue for the management process to communicate with the resource process;  
  87.     iMsgQue2 = CreateMsgQue();  
  88.   
  89.     //Install the Resource Process Recycling Signal Processing Function  
  90.     signal(SIGUSR1, ReleaseAProcess);     
  91.   
  92.     //Start receiving external incoming tasks  
  93.     while(1)  
  94.     {  
  95.         //Receiving external work requests  
  96.         iMsgLen = msgrcv(iMsgQue1, szBuffer, sizeof(szBuffer), 0);  
  97.           
  98.         //Forwarding Work Request to Resource Process Processing Message Queue  
  99.         iRtn = msgsnd(iMsgQue2, szBuffer, iMsgLen, 0);  
  100.       
  101.         //Notify one of the idle resource processes for processing  
  102.         NoticeAIdleProcess();  
  103.     }  
  104. }  
  105.   
  106. //Notify an idle resource process for processing  
  107. int NoticeAIdleProcess()  
  108. {  
  109.     int i;  
  110.       
  111.     for (i = 0; i < iMaxProcessNum; i++)  
  112.     {  
  113.         if (pProcessMng[i].iFlag == 0)  
  114.         {  
  115.             pProessMng[i].Flag = 1;  
  116.             kill(processMng[i].pid, SIGUSR1);  
  117.             return 0;  
  118.         }  
  119.     }  
  120.       
  121.     return -1;    
  122. }  
  123.   
  124. //Recycling a resource process that has been processed  
  125. void ReleaseAProcess(int iPid)  
  126. {  
  127.     int i;  
  128.       
  129.     for (i = 0; i < iMaxProcessNum; i++)  
  130.     {  
  131.         if (pProessMng[i].pid == iPid)  
  132.         {  
  133.             pProcessMng[i].iFlag = 0;  
  134.             return;  
  135.         }  
  136.     }  
  137.   
  138.     return;  
  139. }  
  140.   
  141. //Processing of resource processes  
  142. void ResourceProcess()  
  143. {  
  144.     //Signal Processing with Work Notification Installed  
  145.     signal(SIGUSR1, SIG_IGN);  
  146.   
  147.     //Settings are only interested in SIGUSR1 signals  
  148.     sigprocmask()  
  149.     while(1)  
  150.     {  
  151.         //Suspend without message processing  
  152.         pause();  
  153.           
  154.         //Processing  
  155.         void StartWork()  
  156.   
  157.         //Notify the management process that the work is completed  
  158.         NoticeMngProcessFinishedWork();   
  159.     }  
  160. }  
  161.   
  162. //Processing messages  
  163. void StartWork()  
  164. {  
  165.     char szBuffer[64];  
  166.     int iMsgID;  
  167.     int iRtn;  
  168.       
  169.     iMsgID = msgget();  
  170.     iRtn = msgrcv(iMsgID, szBuffer, sizeof(szBuffer), 0);  
  171.       
  172.     //Now that you have a message that needs to be processed in the child process, you can start processing the message until the message processing is complete.  
  173.   
  174.     return;   
  175. }  
  176.   
  177. //Notify the management process of the resource recovery process  
  178. void NoticeMngProcessFinishedWork();  
  179. {  
  180.     kill(MngProcessPid, SIGUSR1);  
  181.       
  182.     return;  
  183. }  



Keywords: network less Web Server Session

Added by aprieto on Wed, 26 Jun 2019 01:38:00 +0300