BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Re: 2Q: Danger of using FillMem() on a string? Speed of Abs(

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> comp.lang.pascal.delphi.misc
View previous topic :: View next topic  
Author Message
J French
Guest





PostPosted: Fri Dec 12, 2003 3:35 pm    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote



On Fri, 12 Dec 2003 15:25:54 +0100, Quivis <quivis (AT) ask (DOT) me.first>
wrote:

<snip>
Quote:

My second question is best illustrated as follows:

//Quivis, 2003-12: Reverse string (S)
function ReverseStr(const S: string): string;
var
I, iLen: integer;
sTmp: string;
begin
iLen := Length(S);
SetLength(sTmp, iLen);
for I := 1 to iLen do
sTmp[I] := S[Abs(I - (iLen + 1))];
Result := sTmp;
end;

Abs() is not slow
- but this code is daft
..... bizarre is more likely

Draw a string on a bit of paper, as a load of boxes
- draw arrows
- try a string of length two
- then one of length three

Think hard about what 'Div' does

Who Knows (Quivis) what you will realize ?

Back to top
Rob Kennedy
Guest





PostPosted: Fri Dec 12, 2003 4:21 pm    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote



Quivis wrote:
Quote:
Anyway, what I'm concerned about is, are there any dangers in using this
function? Like: "it's a bad idea because [...]," and similar.

The code is fine. However, it will *never* return False. If SetLength or
FillMemory fail, you will get an exception and you will have no return
value at all.

Your error checking seems to assume that FillMemory will start filling
at the beginning of the buffer and finish at the end, but it's allowed
to fill the buffer backward if it wants to, in which case checking the
last character won't be a good indication of success anyway.

You should check for the case when iNumChars is zero or negative. A zero
value will be fine for SetLength and FillMemory, but it will fail when
you check S[iNumChars]. A negative value is invalid input; use Assert to
check for it:

Assert(iNumChars >= 0);

I would declare S as an out parameter instead of var; it's more
expressive of how the parameter is used.

FillMemory is just a thin wrapper around the built-in FillChar
procedure. Save yourself a CALL/RET and use FillChar directly.

Quote:
I've seen similar approaches used in many code-snippets on how to
reverse a string, but so far I have not seen anyone using Abs() to do
the "dirty work" of reversing the string. So my question is: Is there a
reason for this? Is Abs() very slow, or what?

It's not slow, but it's not needed, either. Within your loop, iLen+1 is
always greater than I, so the result of subtraction will always be
negative. If the result is always negative, then you can save the call
to Abs and just reverse the operands:

sTmp[I] := S[iLen + 1 - I];

ILen+1 is also an expression with a constant result, so you should
perform the operation outside the loop.

I'd remove the use of sTmp and work on Result directly.

Abs is actually not a function at all. It's compiler magic, so there is
no CALL/RET involved; it's about as fast as it could possibly be.

--
Rob

Back to top
AlanGLLoyd
Guest





PostPosted: Fri Dec 12, 2003 7:04 pm    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote



In article <MPG.1a43ee611d5f529a989845 (AT) 207 (DOT) 14.113.17>, Quivis
<quivis (AT) ask (DOT) me.first> writes:

Quote:
In some of my apps I do this:

//Quivis, 2002-03, edited 2003-12: Fill a string (S) with a
//character (cCharacter) up to desired length (iNumChars),
//returns boolean
function FillString(var S: string; iNumChars: integer;
cCharacter: Char): boolean;
begin
Result := False; //assume failure
SetLength(S, iNumChars);
FillMemory(pointer(S), iNumChars, Ord(cCharacter));
if S[iNumChars] = cCharacter then
Result := True;
end;

...and it seems to be working. To those who may wonder: I don't have a
clue as to how fast this is, I've never tested it since it's mainly used
on fairly short strings. I just thought it was a waste not to use
already built-in stuff, and, to tell you the truth, I didn't really
expect it to run... :-)

But if anyone has a clue as to how fast this function might be, I'd
appreciate to hear about it, although this is not why I'm posting.

Anyway, what I'm concerned about is, are there any dangers in using this
function? Like: "it's a bad idea because [...]," and similar.


What's the problem with using Delphi's StringOfChar() ?

Alan Lloyd
[email]alanglloyd (AT) aol (DOT) com[/email]

Back to top
J French
Guest





PostPosted: Sat Dec 13, 2003 11:58 am    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote

On Sat, 13 Dec 2003 11:28:19 +0100, Quivis <quivis (AT) ask (DOT) me.first>
wrote:

Quote:
In article <3fd9dd86.10662948 (AT) news (DOT) btclick.com>, [email]erewhon (AT) nowhere (DOT) com[/email]
says...

8>< /snip
Abs() is not slow
- but this code is daft
.... bizarre is more likely

See my response to Rob where it came from.

8>< /snip
Think hard about what 'Div' does

I came up with this:

iLen := Length(S) + 1;
Result := S;
for I := 1 to iLen div 2 do
begin
//is there a faster way to swap two characters?
C := Result[I];
Result[I] := Result[iLen - I];
Result[iLen - I] := C;
end;


Yes, that is more like it, but the code is slightly obfuscated
Just because something looks terser, does not mean that it is faster
- I also missed a trick
- I thought you were reversing a string

L := Length( S );
For L9 := 1 To L Div 2 Do
Begin
C := S[L9];
S[ L9 ] := Result[ L ];
S[ L ] := C;
L := L - 1;
End;

However you are actually making a COPY of the String

L := Length( S );
SetLength( Result, L );
For L9 := 1 To L Do
Begin
Result[ L9 ] := S[ L ];
L := L - 1 ;
End;

Notice that I am using a simple counter rather than doing the maths
time and time again
- this makes the code far easier to understand
- and probably faster
if the compiler can 'remember' the results of simple math
- then it can certainly 'remember' to substitute a Register for a
variable

BTW, the reason why I would recomend using SetLength() if you are
returning a Result, is because Delphi definitely creates a new unique
Result, whereas assigning a copy of the string in S to Result _might_
result in reference counting
- probably not, as the compiler is pretty smart
- but in principle it is better to tell the compiler to do exactly
what you want, rather than 'misleading' it
- it also makes the code clearer to read

As far as swapping characters goes, it is probably not worth worrying
about
- there is the ASM XCHG
- but it is unlikely to be one of the 'optimized' Op codes that have
had a RISC element since the .486

Quote:

Who Knows (Quivis) what you will realize ?

Well, it seems you have realized what my "name" means... Wink

I wasn't sure for some time ...

BTW apologies for being rather sharp yesterday
- it is just that I've spent much of my coding life trying to unravel
'clever' code by other people
- and avoid writing it myself

Back to top
Rob Kennedy
Guest





PostPosted: Sat Dec 13, 2003 5:50 pm    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote

Quivis wrote:
Quote:
In article <vtjqohcq2p3a2 (AT) corp (DOT) supernews.com>, Rob Kennedy <.> says...
FillMemory is just a thin wrapper around the built-in FillChar
procedure. Save yourself a CALL/RET and use FillChar directly.

Are you sure? FillMemory() is, if I'm not mistaken, a system API.

I am certain. Go check it yourself in the source code. Another
indication is in the documentation. Unlike for most other API functions,
MSDN doesn't tell you which C library to link to your code since the
function doesn't appear in any library. Its implementation is left to
the compiler vendor. The same goes for CopyMemory, MoveMemory, and
ZeroMemory. They're implemented using Delphi's Move and FillChar.

Quote:
From Win32 help:
[...]
VOID FillMemory (
PVOID Destination, // pointer to block to fill
DWORD Length, // size, in bytes, of block to fill
BYTE Fill // the byte value with which to fill
);
[...]

The I in API stands for interface, not implementation.

--
Rob

Back to top
Dr John Stockton
Guest





PostPosted: Sat Dec 13, 2003 9:26 pm    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote

JRS: In article <MPG.1a45082b98f29eb9989849 (AT) 207 (DOT) 14.113.17>, seen in
news:comp.lang.pascal.delphi.misc, Quivis <quivis (AT) ask (DOT) me.first> posted
at Sat, 13 Dec 2003 11:28:19 :-

Quote:
iLen := Length(S) + 1;
Result := S;
for I := 1 to iLen div 2 do
begin
//is there a faster way to swap two characters?
C := Result[I];
Result[I] := Result[iLen - I];
Result[iLen - I] := C;
end;

The entire string is copied and then reversed; it bight be better to
copy it backwards. Consider something like

K := 1 ; L := Length(S) ;
SetLength(Result, L) ;
for J := L downto 1 do begin Result[K] := S[J] ; Inc(K) end ;
or
K := 1 ; L := Length(S) ;
SetLength(Result, L) ;
repeat Result[K] := S[L] ; Inc(K) ; Dec(L) until L=0 ;
or
L := Length(S) ; SetLength(Result, L) ; PS = @S[L] ; PR = @R[1] ;
repeat PR^ := PS^ ; Inc(PR) ; Dec(PS) until ??? ;

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Delphi 3 Turnpike 4 ©
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.bancoems.com/CompLangPascalDelphiMisc-MiniFAQ.htm> clpdmFAQ;
<URL:http://www.borland.com/newsgroups/guide.html> news:borland.* Guidelines

Back to top
Maarten Wiltink
Guest





PostPosted: Sat Dec 13, 2003 11:09 pm    Post subject: Re: Some tests on variations of the theme (a bit long) [ Re: Reply with quote

"Quivis" <quivis (AT) ask (DOT) me.first> wrote

Quote:
In article <3fdaf94d.83320989 (AT) news (DOT) btclick.com>, [email]erewhon (AT) nowhere (DOT) com[/email]
says...

However you are actually making a COPY of the String

Yes, but it seems Delphi refuses to work in this way directly on
TMemo.Text, ...

That is correct. You are not allowed to pass a property as a var parameter,
because it _may_ be backed by accessor methods. Even if it's backed by a
field in the current class, and constructing a reference would be possible,
a descendant class may change that. So the only safe thing to do is to
forbid it altogether.

Groetjes,
Maarten Wiltink



Back to top
J French
Guest





PostPosted: Sun Dec 14, 2003 1:33 pm    Post subject: Re: Some tests on variations of the theme (a bit long) [ Re: Reply with quote

On Sat, 13 Dec 2003 18:10:51 +0100, Quivis <quivis (AT) ask (DOT) me.first>
wrote:

Quote:
In article <3fdaf94d.83320989 (AT) news (DOT) btclick.com>, [email]erewhon (AT) nowhere (DOT) com[/email]
says...

8>< /snip
However you are actually making a COPY of the String

Yes, but it seems Delphi refuses to work in this way directly on
TMemo.Text, so I had to. Either inside the function or before I called
it. I opted for doing it inside the function. They way I use it, it will
only be called once for each string.

TMemo.Text is a Property
- in general you are probably right in making StrReverse a function
- my version works on the string itself (a procedure)
- this is historical, since the original was in ASM from about 1987

Quote:

8>< /snip
BTW, the reason why I would recomend using SetLength() if you are
returning a Result, is because Delphi definitely creates a new unique
Result, whereas assigning a copy of the string in S to Result _might_
result in reference counting

That's something to keep in mind.

IMO/IME it is better to be totally 'honest' when writing routines
- it makes them cleaner and clearer

Quote:

Some tests I've done, using the following setup:

snip


Quote:


Conclusion: There are more ways than one to skin a cat, especially when
the cats are so similar in size as these. Smile

True, but let's face it, the second version of the routine that I
posted was 'blindingly obvious' code

Quote:

Well, it seems you have realized what my "name" means... ;-)

I wasn't sure for some time ...

Well, it actually means whoever, at least in my Latin dictionary, e.g.
as in "whoever did that shall be keelhauled" Wink

Did the Romans keelhaul ?
- I doubt that there boats were sufficiently barnacled

Quote:

BTW apologies for being rather sharp yesterday

No problems.



Back to top
Dr John Stockton
Guest





PostPosted: Sun Dec 14, 2003 8:12 pm    Post subject: Re: 2Q: Danger of using FillMem() on a string? Speed of Abs( Reply with quote

JRS: In article <MPG.1a465d13cde147b3989850 (AT) 207 (DOT) 14.113.17>, seen in
news:comp.lang.pascal.delphi.misc, Quivis <quivis (AT) ask (DOT) me.first> posted
at Sun, 14 Dec 2003 11:42:51 :-
Quote:
In article <uBvns5AMQ42$Ewwb (AT) merlyn (DOT) demon.co.uk>,
[email]spam (AT) merlyn (DOT) demon.co.uk[/email] says...

The entire string is copied and then reversed; it bight be better to
^^^
Have you caught a cold? Wink

The cause is that I am not a good typist; however, your supposition is
unfortunately correct. The latter situation, unlike the former, will
probably improve.

--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Delphi 3 Turnpike 4 ©
<URL:http://www.merlyn.demon.co.uk/> TP/BP/Delphi/&c., FAQqy topics & links;
<URL:http://www.bancoems.com/CompLangPascalDelphiMisc-MiniFAQ.htm> clpdmFAQ;
<URL:http://www.borland.com/newsgroups/guide.html> news:borland.* Guidelines

Back to top
Michael Brown
Guest





PostPosted: Tue Dec 16, 2003 2:31 am    Post subject: Re: Some tests on variations of the theme (a bit long) [ Re: Reply with quote

Quivis wrote:
Quote:
In article <3fdaf94d.83320989 (AT) news (DOT) btclick.com>, [email]erewhon (AT) nowhere (DOT) com[/email]
says...
[...]
Some tests I've done, using the following setup:

XP-Pro, 1.3 GHz CPU (Celeron Mobile), 256 MB RAM
Iterations: 100,000 for each code snippet on separate runs.
String to reverse: Many websites assume that every visitor will have a
browser capable of Javascript.
[...]
//Tick count: 761, stabilized around this value, first run: 781
[...]


What? There's no heavily-unrolled, hand-optimised MMX version in there? Aww
Smile
(estimated tick count: 20-50)

[...]

--
Michael Brown
www.emboss.co.nz : OOS/RSI software and more Smile
Add michael@ to emboss.co.nz - My inbox is always open



Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> comp.lang.pascal.delphi.misc All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.