在从磁盘读取数据(数据仅表示字符串字符串的数据)的函数中,我应该选择哪一个?哪个更好?
A) DiskStream.Read(Pointer(s)^, Count)
or
B) DiskStream.Read(s[1], Count)
注意:
我知道两者的结果相同。
我知道在调用Read之前必须先设置S的SetLength。
更新
S是AnsiString。
这是全部功能:
{从文件中读取一堆字符。为什么是“ReadChars”而不是“ReadString”?此函数读取C++字符串(字符串的长度也未写入磁盘)。因此,我必须给出要读取的字符数作为参数。 }
function TMyStream.ReadChars(out s: AnsiString; CONST Count: Longint): Boolean;
begin
SetLength(s, Count);
Result:= Read(s[1], Count)= Count;
end;
速度测试
在我的速度测试中,第一种方法比第二种方法快一点。我使用了一个400MB的文件,从中读取了大约200000次字符串。该过程设置为“高优先级”。
有史以来最好的阅读时间是:
变体B为1.35,变体A为1.37。
平均:
平均而言,B的得分也比A高20毫秒。
每个变体重复测试15次。
差别确实很小。可能会落入测量误差范围内。
如果我更频繁地从更大的文件中读取字符串,可能会很有意义。
但是目前,我们假设两行代码都执行相同的操作。
答案
变体A-可能快一点
变体B-(显然)更容易阅读,而且更像Delphi。我的首选。
注意:
我已经看到Embarcadero在TStreamReadBuffer示例中使用了变体A,但是使用的是TBytes而不是String。
最佳答案
请注意,在运行时
1. DiskStream.Read(Pointer(s)^, Count)
2. DiskStream.Read(s[1], Count)
1.版本会更快。
但是,您必须确保
s
变量明确地是本地,或者您在循环之前已将自己称为UniqueString(s)
。由于
pointer(s)^
不会调用UniqueString?()
低级隐藏RTL调用,因此它比s[1]
和更快,但是如果s
字符串变量在当前上下文和其他上下文之间共享(例如,如果最后一个内容),则可以覆盖一些现有数据从属性值的函数中检索s
的,或将s
作为参数发送到另一个方法)。实际上,编码这种从内容读取
AnsiString
的最快正确方法是: s := '';
SetLength(s,Count);
DiskStream.Read(pointer(s)^,Count);
要么
SetString(s,nil,Count);
DiskStream.Read(pointer(s)^,Count);
第二版等于第一版,但少了一行。
将
s
设置为''将调用FreeMem()+AllocMem()
而不是ReallocMem()
中的SetLength()
,因此将避免调用move()
,因此会更快一些。实际上,由
UniqueString?()
生成的s[1]
RTL调用将非常快,因为在调用SetLength()
之前已经对其进行了调用:因此,s
已经是唯一的,并且UniqueString?()
RTL调用几乎立即返回。分析后,两个版本之间的速度差异不大:几乎所有时间都花在字符串分配和从磁盘上移动内容上。也许s[1]
被发现更“无聊”。关于delphi - 指针^与s [1],我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6411246/