我的程序调用数万次,使用这样的通用结构:
procedure PrintIndiEntry(JumpID: string);
type
TPeopleIncluded = record
IndiPtr: pointer;
Relationship: string;
end;
var
PeopleIncluded: TList<TPeopleIncluded>;
PI: TPeopleIncluded;
begin { PrintIndiEntry }
PeopleIncluded := TList<TPeopleIncluded>.Create;
{ A loop here that determines a small number (up to 100) people to process }
while ... do begin
PI.IndiPtr := ...;
PI.Relationship := ...;
PeopleIncluded.Add(PI);
end;
DoSomeProcess(PeopleIncluded);
PeopleIncluded.Clear;
PeopleIncluded.Free;
end { PrintIndiEntry }
或者,我可以在全局而不是本地声明PeopleIncluded,如下所示:
unit process;
interface
type
TPeopleIncluded = record
IndiPtr: pointer;
Relationship: string;
end;
var
PeopleIncluded: TList<TPeopleIncluded>;
PI: TPeopleIncluded;
procedure PrintIndiEntry(JumpID: string);
begin { PrintIndiEntry }
{ A loop here that determines a small number (up to 100) people to process }
while ... do begin
PI.IndiPtr := ...;
PI.Relationship := ...;
PeopleIncluded.Add(PI);
end;
DoSomeProcess(PeopleIncluded);
PeopleIncluded.Clear;
end { PrintIndiEntry }
procedure InitializeProcessing;
begin
PeopleIncluded := TList<TPeopleIncluded>.Create;
end;
procedure FinalizeProcessing;
begin
PeopleIncluded.Free;
end;
我的问题是,在这种情况下,最好是全局声明PeopleIncluded而不是本地声明。我知道理论是尽可能在本地定义,但我想知道是否有任何问题需要担心成千上万的“创造”和“免费”?使它们成为全球只会创造一个创造,一个免费。
在这种情况下使用的推荐方法是什么?
如果推荐的方法仍然在本地定义,那么我想知道在本地定义仍然是一个选项时是否有更好的全局定义。
答案 0 :(得分:5)
关于流程的可见性,我要做的是创建一个 class
保存所有数据,一个用于初始化的方法和一个析构函数,然后一个方法来调用该流程。然后使用分析器优化速度。 从不使用全局,但将您的进程封装在小型可重用和多线程就绪的类中。
关于流程速度,简而言之:“过早优化是所有邪恶的根源” - 唐纳德克努特,引用C. A. R. Hoare。我确信TList Create/Free
中的瓶颈不是,而是在主流程循环中。
因此,在猜测可能发生的变化之前,请先使用分析器查看瓶颈所在。见Profiler and Memory Analysis Tools for Delphi
您可以预先分配变量和/或缓存可重用数据,使用静态数组而不是TList
(或分配它并使用外部count
变量重用它),并避免分配{ {1}}个实例(并且没有string
参数传递它们)。但也许不是一个神奇的解决方案。
为了加快处理速度,更改算法几乎总是比你尝试的一些低级实现技巧更好。使用预先计算的查找表,内存预分配,避免创建临时const
(例如使用string
代替PosEx
子链;或混合copy
/ AnsiString
),避免磁盘,API或DB调用,更改内存结构,排序数据然后使用二进制搜索,使用散列或非管道循环,让你处理多线程等等......这是不可能的猜测如果没有流程的完整源代码就应该更改,并在真实数据上运行探查器!
答案 1 :(得分:2)
你的第一个代码更好。从外部隐藏任何数据结构是很好的。第一个代码显示PeopleIncluded不在您的程序之外使用,因此最好将其保留在其中。将其暴露在外面(在界面部分中)将使其可以从使用该单元的所有其他单元中看到。通过这样做,您可能会被其他单位访问和修改。这可能是您或其他人使用您的代码有意或无意地发生的,并可能导致不良后果。
如果你不能或仍然想让它不是你的程序的本地,最好在实现部分中声明类型和var,而不是接口部分。
您不必担心性能问题。内存中的操作很快,我的建议只是在性能瓶颈真正发生时才会担心。当它发生时,您可以分析您的应用程序以找到瓶颈,并仅优化导致瓶颈的代码。这样做可以避免不必要的努力来优化对您的应用程序性能没有贡献(或最小化)的代码。
答案 2 :(得分:1)
案例#3
unit process;
interface
type
TPeopleIncluded = record
IndiPtr: pointer;
Relationship: string;
end;
procedure PrintIndiEntry(JumpID: string);
var
PeopleIncluded: TList<TPeopleIncluded>;
PI: TPeopleIncluded;
begin { PrintIndiEntry }
{ A loop here that determines a small number (up to 100) people to process }
while ... do begin
PI.IndiPtr := ...;
PI.Relationship := ...;
PeopleIncluded.Add(PI);
end;
DoSomeProcess(PeopleIncluded);
PeopleIncluded.Clear;
end { PrintIndiEntry }
procedure InitializeProcessing;
Dosomeprocess((PeopleIncluded)也必须知道记录。在多个地方声明相同的记录有点不好。这就是为什么你想让它可用于Dosomeprocess。但是这些变量在本地更好地声明。
创建一个小班可能是最好的。