就任何其他不同环境下这个简单的本地化性能测试得出的结果的有效性寻求第二意见
我的设置:
- 操作系统:Windows 7 SP1(32 位)
- RAM:4 Go
- 处理器:Intel Pentium D 3.00 GHz
- Delphi XE
我的简单测试:
我执行了运行以下命令的测试程序:
program TestAssign;
{$APPTYPE CONSOLE}
uses
SysUtils,
Diagnostics;
type
TTestClazz = class
private
FIntProp: Integer;
FStringProp: string;
protected
procedure SetIntProp(const Value: Integer);
procedure SetStringProp(const Value: string);
public
property IntProp: Integer read FIntProp write SetIntProp;
property StringProp: string read FStringProp write SetStringProp;
end;
{ TTestClazz }
procedure TTestClazz.SetIntProp(const Value: Integer);
begin
if FIntProp <> Value then
FIntProp := Value;
end;
procedure TTestClazz.SetStringProp(const Value: string);
begin
if FStringProp <> Value then
FStringProp := Value;
end;
var
i, j: Integer;
stopw1, stopw2 : TStopwatch;
TestObj: TTestClazz;
begin
ReportMemoryLeaksOnShutdown := True;
//
try
TestObj := TTestClazz.Create;
//
try
j := 10000;
while j <= 100000 do
begin
///
/// assignement
///
stopw1 := TStopwatch.StartNew;
for i := 0 to j do
begin
TestObj.FIntProp := 666;
TestObj.FStringProp := 'Hello';
end;
stopw1.Stop;
///
/// property assignement using Setter
///
stopw2 := TStopwatch.StartNew;
for i := 0 to j do
begin
TestObj.IntProp := 666;
TestObj.StringProp := 'Hello';
end;
stopw2.Stop;
///
/// Log results
///
Writeln(Format('Ellapsed time for %6.d loops: %5.d %5.d', [j, stopw1.ElapsedMilliseconds, stopw2.ElapsedMilliseconds]));
//
Inc(j, 5000);
end;
//
Writeln('');
Write('Press Return to Quit...');
Readln;
finally
TestObj.Free
end
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
我的(临时)结论:
看来:
- 在某些条件下使用具有属性的 Setter 是值得的
- 调用方法和执行条件测试的开销比赋值花费的时间更少。
我的问题:
这些发现在任何其他不同环境下有效还是仅在本地环境下有效(例外)?
My setting:
- OS: Windows 7 SP1 (32 bits)
- Ram: 4 Go
- Processor: Intel Pentium D 3.00 GHz
- Delphi XE
My simple test:
I performed a test running the following program:
program TestAssign;
{$APPTYPE CONSOLE}
uses
SysUtils,
Diagnostics;
type
TTestClazz = class
private
FIntProp: Integer;
FStringProp: string;
protected
procedure SetIntProp(const Value: Integer);
procedure SetStringProp(const Value: string);
public
property IntProp: Integer read FIntProp write SetIntProp;
property StringProp: string read FStringProp write SetStringProp;
end;
{ TTestClazz }
procedure TTestClazz.SetIntProp(const Value: Integer);
begin
if FIntProp <> Value then
FIntProp := Value;
end;
procedure TTestClazz.SetStringProp(const Value: string);
begin
if FStringProp <> Value then
FStringProp := Value;
end;
var
i, j: Integer;
stopw1, stopw2 : TStopwatch;
TestObj: TTestClazz;
begin
ReportMemoryLeaksOnShutdown := True;
//
try
TestObj := TTestClazz.Create;
//
try
j := 10000;
while j <= 100000 do
begin
///
/// assignement
///
stopw1 := TStopwatch.StartNew;
for i := 0 to j do
begin
TestObj.FIntProp := 666;
TestObj.FStringProp := 'Hello';
end;
stopw1.Stop;
///
/// property assignement using Setter
///
stopw2 := TStopwatch.StartNew;
for i := 0 to j do
begin
TestObj.IntProp := 666;
TestObj.StringProp := 'Hello';
end;
stopw2.Stop;
///
/// Log results
///
Writeln(Format('Ellapsed time for %6.d loops: %5.d %5.d', [j, stopw1.ElapsedMilliseconds, stopw2.ElapsedMilliseconds]));
//
Inc(j, 5000);
end;
//
Writeln('');
Write('Press Return to Quit...');
Readln;
finally
TestObj.Free
end
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
My (provisionnal) conclusion:
It seems that:
- It's worth using Setter with property under some condition
- The overhead of calling a method and performing a conditional test take less time than an assignement.
My question:
Are those findings valid under any other diffrent setting or just localized ones (exception)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我会提出以下意见:
if
语句每次都计算为False
。设置属性的现实世界代码可能会在设置器运行的合理时间内修改属性。True
,那么显然,如果没有它,代码会更快。if
测试的优化,如果可能的话,可以避免字符串赋值代码,从而带来一些真正的性能优势。我相信任何现实世界的代码永远无法检测到任何这些性能差异。实际上,瓶颈将是获取传递给设置器的值,而不是在设置器中花费的时间。
这种
if
保护有价值的主要情况是属性修改成本高昂。例如,可能涉及发送 Windows 消息或访问数据库。对于由字段支持的财产,您可能可以接受或离开它。在评论中的讨论中,过早优化想知道为什么比较
if FStringProp <> Value
比赋值FStringProp := Value
更快。我进一步调查了一下,发现情况并不像我最初想象的那样。事实证明
if FStringProp <> Value
由对System._UStrEqual
的调用控制。传递的两个字符串实际上不是相同的引用,因此必须比较每个字符。然而,这段代码经过了高度优化,最重要的是只有 5 个字符可供比较。对
FStringProp := Value
的调用会转到System._UStrAsg
,并且由于Value
是一个具有负引用计数的文字,因此必须使用一个全新的字符串被制作。 Pascal 版本的代码如下所示:其中的关键部分是对
_NewUnicodeString
的调用,它当然会调用GetMem
。对于堆分配比 5 个字符的比较慢得多,我一点也不感到惊讶。I would make the following observations:
if
statements evaluate toFalse
every time. Real world code that sets properties would be likely to modify the properties a reasonable proportion of the time that the setter runs.True
every time then clearly the code would be quicker without it.if
test which avoids string assignment code if possible.My belief is that any real world code would never be able to detect any of these performance differences. In reality the bottleneck will be obtaining the values passed to the setters rather than time spent in the setters.
The main situation where such
if
protection is valuable is where the property modification is expensive. For example, perhaps it involves sending a Windows message, or hitting a database. For a property backed by a field you can probably take it or leave it.In the chatter in the comments Premature Optimization wonders why the comparison
if FStringProp <> Value
is quicker than the assignmentFStringProp := Value
. I investigated a little further and it wasn't quite as I had originally thought.It turns out that
if FStringProp <> Value
is dominated by a call toSystem._UStrEqual
. The two strings passed are not in fact the same reference and so each character has to be compared. However, this code is highly optimised and crucially there are only 5 characters to compare.The call to
FStringProp := Value
goes toSystem._UStrAsg
and sinceValue
is a literal with negative reference count, a brand new string has to be made. The Pascal version of the code looks like this:The key part of this is the call to
_NewUnicodeString
which of course callsGetMem
. I am not at all surprised that heap allocation is significantly slower than comparison of 5 characters.将 'Hello' const 放入变量中并使用它进行设置,然后再次进行测试
Put 'Hello' const into a variable and use it for setting then do a test again