我如何正确使用 PChars 来改进这种优化?

发布于 2024-11-02 12:05:16 字数 1374 浏览 1 评论 0原文

我的应用程序中有一个被大量调用的函数。它基本上是一个 csv 解析器,它“弹出”第一个值并将输入字符串更改为剩余的字符串。

function StripString(mask: string; var modifiedstring: string): string;
var
  index,len: integer;
  s: string;
begin
    Index := pos(Mask, ModifiedString);
    len := Length(ModifiedString);
    if index <> 0 then
    begin
        if Index <> 1 then
        begin
            s := LeftStr(ModifiedString, index - 1);
            ModifiedString := RightStr(ModifiedString, len-index);
        end else begin
            if Length(ModifiedString)>1 then
              ModifiedString := Copy(ModifiedString,2,len)
            else
              ModifiedString := '';
            s := '';
        end;
    end else begin
        s := ModifiedString;
        ModifiedString := '';
    end;
    result := s
end;

我想尝试使用 PChars 来优化这个例程。所以我想出了这个方法,但不幸的是我在结果输出中得到了奇怪的字符。我猜是因为指针不正确。

//faster method - uses PChars
function StripStringEx(mask: char; var modifiedstring: string): string;
var
  pSt,pCur,pEnd : Pchar;
begin
    pEnd := @modifiedString[Length(modifiedString)];
    pSt := @modifiedString[1];
    pCur := pSt;
    while pCur <= pEnd do
    begin
         if pCur^ = mask then break;
         inc(pCur);
    end;
    SetString(Result,pSt,pCur-pSt);
    SetString(ModifiedString,pCur+1,pEnd-pCur);
end;

有人“指出”:)我的方向正确吗?

I have a function that is called heavily in my app. It is basically a csv parser, which 'pops' the first value off and changes the input string to the remaining string.

function StripString(mask: string; var modifiedstring: string): string;
var
  index,len: integer;
  s: string;
begin
    Index := pos(Mask, ModifiedString);
    len := Length(ModifiedString);
    if index <> 0 then
    begin
        if Index <> 1 then
        begin
            s := LeftStr(ModifiedString, index - 1);
            ModifiedString := RightStr(ModifiedString, len-index);
        end else begin
            if Length(ModifiedString)>1 then
              ModifiedString := Copy(ModifiedString,2,len)
            else
              ModifiedString := '';
            s := '';
        end;
    end else begin
        s := ModifiedString;
        ModifiedString := '';
    end;
    result := s
end;

I want to try and optimize this routine, using PChars. So i came up with this method, but unfortunately i get weird characters in the resultant output. Im guessing its because of incorrect pointers.

//faster method - uses PChars
function StripStringEx(mask: char; var modifiedstring: string): string;
var
  pSt,pCur,pEnd : Pchar;
begin
    pEnd := @modifiedString[Length(modifiedString)];
    pSt := @modifiedString[1];
    pCur := pSt;
    while pCur <= pEnd do
    begin
         if pCur^ = mask then break;
         inc(pCur);
    end;
    SetString(Result,pSt,pCur-pSt);
    SetString(ModifiedString,pCur+1,pEnd-pCur);
end;

Anyone "point":) me in the right direction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

送君千里 2024-11-09 12:05:16

即使您让指针版本正常工作,我也不明白为什么它会更快。

调用 Pos 比循环更快,因为 Pos 经过了合理优化。两个版本的分配模式是相同的,两个堆分配和一个堆释放。我会坚持使用有效的版本。

您可以摆脱局部变量 s 并直接分配给 Result 以跳过一些引用计数。

Even if you get your pointer version to work I don't see why it would be faster.

Calling Pos is faster than your loop since Pos is reasonably optimized. The allocation patterns are the same with both versions, two heap allocations and a heap deallocation. I'd stick with the version that works.

You can get rid of the local variable s and assign direct to Result to skip a bit of reference counting.

迷路的信 2024-11-09 12:05:16

我认为由于 ModifiedString 上的 SetString,您会得到奇怪的结果。
SetString首先设置字符串的长度,然后将缓冲区中的内容复制到新创建的字符串中。但在您的情况下,缓冲区是目的地,并且缓冲区的长度刚刚进行了调整。

只需遵循 David 的建议,不要使用 PChars。

如果你愿意,你可以让它变得更短:

function StripString(const Mask: string; var ModifiedString: string): string;
var
  Index: Integer;
begin
  Index := Pos(Mask, ModifiedString);
  if Index <> 0 then
  begin
    Result := LeftStr(ModifiedString, Index - 1);
    Delete(ModifiedString, Index);
  end
  else
  begin
    Result := ModifiedString;
    ModifiedString := '';  
  end;
end;

I think you get strange results because of the SetString on ModifiedString.
SetString first sets the length of the string, and then copies the content from the buffer to the newly created string. But in your case the buffer is the destination, and the length of the buffer just got adjusted.

Just follow David's advise and do not use PChars.

If you want, you can make it somewhat shorter:

function StripString(const Mask: string; var ModifiedString: string): string;
var
  Index: Integer;
begin
  Index := Pos(Mask, ModifiedString);
  if Index <> 0 then
  begin
    Result := LeftStr(ModifiedString, Index - 1);
    Delete(ModifiedString, Index);
  end
  else
  begin
    Result := ModifiedString;
    ModifiedString := '';  
  end;
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文