提高FastReplace速度 (fStrRep.pas)[4]

[入库:2005年8月18日] [更新:2007年3月24日]

本文简介:选择自 luckyjan 的 blog

//ion are dword aligned, so moving bytes avoids the cycle penalty of reading/w
//riting dwords across physical boundaries.
procedure mymove(
  const source; var dest; count : integer);
asm
// note: when this function is called,
// delphi passes the parameters as follows:
// ecx = count
// eax = const source
// edx = var dest
  // if there are no bytes to copy, just quit
  // altogether; there's no point pushing registers.
  cmp   ecx,0
  je    @justquit
  // preserve the critical delphi registers.
  push  esi
  push  edi
  // move source into esi (generally the
  // source register).
  // move dest into edi (generally the dest
  // register for string commands).
  // this might not actually be necessary,
  // as i'm not using movsb etc.
  // i might be able to just use eax and edx;
  // there could be a penalty for not using
  // esi, edi, but i doubt it.
  // this is another thing worth trying!
  mov   esi, eax
  mov   edi, edx
  // the following loop is the same as repnz
  // movsb, but oddly quicker!
    @loop:
  // get the source byte.
  mov   al, [esi]
  // point to next byte.
  inc   esi
  // put it into the dest.
  mov   [edi], al
  // point dest to next position.
  inc   edi
  // dec ecx to note how many we have left to copy.
  dec   ecx
  // if ecx <> 0, then loop.
  jnz   @loop
  // another optimization note.
  // many people like to do this.
  // mov al, [esi]
  // mov [edi], al
  // inc esi
  // inc esi
//there’s a hidden problem here. i won’t go into too much detail, but the pe
//ntium can continue processing instructions while it’s still working out the
// result of inc esi or inc edi. if, however, you use them while they’re stil
//l being calculated, the processor will stop until they’re calculated (a pen
//alty). therefore, i alter esi and edi as far in advance as possible of using
// them.
  // pop the critical delphi registers
  // that we've altered.
  pop   edi
  pop   esi
    @justquit:
end;

//point 1: i pass var asourcestring rather than just asourcestring. this is be
//cause i’ll just be passed a pointer to the data rather than a 10m copy of t
//he data itself, which is much quicker!
function fastreplace(
  var asourcestring : string;
  const afindstring, areplacestring : string;
  casesensitive : boolean = false) : string;
var
  // size already passed to setlength,
  // the real size of result.
  actualresultlen,
  // position of afindstring is asourcestring.
  currentpos,
  // last position the afindstring was found at.
  lastpos,
  // bytes to copy (that is, lastpos to this pos).
  bytestocopy,
  // the "running" result length, not the actual one.
  resultlen,
  // length of afindstring, to save
  // calling length repetitively.
  findlen,
  // length of areplacestring, for the same reason.
  replacelen,
  sourcelen         : integer;
  // this is where i explain the
  // type tfastposproc from earlier!
  fastposproc       : tfastposproc;
begin
//as this function has the option of being case-insensitive, i’d need to call
// either fastpos or fastposnocase. the problem is that you’d have to do this
// within a loop. this is a bad idea, since the result never changes throughou
//t the whole operation–in which case we can determine it in advance, like so
//:
  if casesensitive then
    fastposproc := fastpos
  else
    fastposproc := fastposnocase;
  // i don't think i actually need
  // this, but i don't really mind!
  result := '';
  // get the lengths of the strings.
  findlen := length(afindstring);
  replacelen := length(areplacestring);
  sourcelen := length(asourcestring);
  // if we already have room for the replacements,
  // then set the length of the result to
  // the length of the sourcestring.
  if replacelen <= findlen then
    actualresultlen := sourcelen
  else
    // if not, we need to calculate the
    // worst-case scenario.

本文关键:提高FastReplace速度 (fStrRep.pas)
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top