Multithreading 线程化以提高性能
我从未使用过线程——从未想过我的代码会受益。但是,我认为线程可能会提高以下伪代码的性能:Multithreading 线程化以提高性能,multithreading,delphi,Multithreading,Delphi,我从未使用过线程——从未想过我的代码会受益。但是,我认为线程可能会提高以下伪代码的性能: Loop through table of records containing security symbol field and a quote field Load a web page (containing a security quote for a symbol) into a string variable Parse the string for the quote
Loop through table of records containing security symbol field and a quote field
Load a web page (containing a security quote for a symbol) into a string variable
Parse the string for the quote
Save the quote in the table
Get next record
end loop
加载每个网页花费的时间最多。对报价的解析相当快。我想我可以把一半的记录放在一个线程中,另一半放在第二个线程中。如果记录的数量相对较少,比如说50个或更少,你可以为每个记录启动一个单独的线程,让它们并行运行,例如:
begin thread
Load a web page for symbol into a string variable
Parse the string for the quote
Save the quote in the table
end thread
如果要处理的记录数较多,请考虑使用一组线程,这样就可以处理较小批次的记录,例如:
Create X threads
Put threads in a list
Loop through table of records
Wait until a thread in pool is idle
Get idle thread from pool
Assign current security symbol to thread
Signal thread
Get next record
end loop
Wait for all threads to be idle
Terminate threads
有许多不同的方法可以实现上述功能,这就是我将其保留在伪代码中的原因。查看VCL的TThread
、TList
和TEvent
类,或Win32 APIQueueUserWorkerItem()
函数,或者任何数量的第三方线程库。在中,使用多级管道解决此问题非常简单-第一阶段在多个任务上运行并下载网页,第二阶段在一个实例中运行并将数据存储到数据库中。不久前,我写了一篇文档记录了这个解决方案
这个解决方案可以用以下代码总结(您必须填写HttpGet和Inserter方法中的一些地方)
使用线程框架,您可以在大量StackOverflow问题(进行搜索)中找到该框架的参考。检查:我会使用omnithreadlibrary,它非常高效,顺便说一句。看看omnixml,这些库也非常有用!在这种情况下,使用管道显然是有意义的。你需要更多的线程来下载,而不是通过声音来解析。谢谢你的评论。在跟进您的评论之后,我会喜欢做一些实验。我认为基于管道的解决方案在这里更合适,因为任务的组成部分在本质上是完全不同的。下载是IO绑定的,解析文件是CPU绑定的。@David:我需要做一些关于“管道”的研究,因为我从来没有听说过它。良好的网址链接将不胜感激。
Create X threads
Put threads in a list
Loop through table of records
Wait until a thread in pool is idle
Get idle thread from pool
Assign current security symbol to thread
Signal thread
Get next record
end loop
Wait for all threads to be idle
Terminate threads
begin thread
Loop until terminated
Mark idle
Wait for signal
If not Terminated
Load a web page for current symbol into a string variable
Parse the string for the quote
Save the quote in the table
end if
end loop
end thread
uses
OtlCommon,
OtlCollections,
OtlParallel;
function HttpGet(url: string; var page: string): boolean;
begin
// retrieve page contents from the url; return False if page is not accessible
end;
procedure Retriever(const input: TOmniValue; var output: TOmniValue);
var
pageContents: string;
begin
if HttpGet(input.AsString, pageContents) then
output := TPage.Create(input.AsString, pageContents);
end;
procedure Inserter(const input, output: IOmniBlockingCollection);
var
page : TOmniValue;
pageObj: TPage;
begin
// connect to database
for page in input do begin
pageObj := TPage(page.AsObject);
// insert pageObj into database
FreeAndNil(pageObj);
end;
// close database connection
end;
procedure ParallelWebRetriever;
var
pipeline: IOmniPipeline;
s : string;
urlList : TStringList;
begin
// set up pipeline
pipeline := Parallel.Pipeline
.Stage(Retriever).NumTasks(Environment.Process.Affinity.Count * 2)
.Stage(Inserter)
.Run;
// insert URLs to be retrieved
for s in urlList do
pipeline.Input.Add(s);
pipeline.Input.CompleteAdding;
// wait for pipeline to complete
pipeline.WaitFor(INFINITE);
end;