Ben Langhinrichs

Photograph of Ben Langhinrichs

E-mail address - Ben Langhinrichs







Recent posts

Mon 21 Jun 2021

Custom Domino Extensions presentation



Thu 10 Jun 2021

Notes 12 without all the blue



Wed 5 May 2021

Pull public data into Notes on the fly


October, 2021
SMTWTFS
     01 02
03 04 05 06 07 08 09
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

Search the weblog





























Genii Weblog

How slow is an ampersand?

Tue 8 Feb 2005, 11:45 AM



by Ben Langhinrichs
Thomas Gumz brings up a point in a post on the Notes 6 Gold forum about the inefficiency of using an ampersand ("&") to concatenate strings:
...by all means don't concatenate all your strings via "&" (because this is slow and inefficient).

Use "+" instead.

BAD :strBody = strBody & "Fax " & conFaxNumber
GOOD: strBody = strBody + "Fax " + conFaxNumber

If conFaxNumber isn't a string, then use this:
strBody = strBody + "Fax " + Cstr(conFaxNumber)

Thomas - IBM
Now, I am a bit of an efficiency nut, but while I have heard this before, I continue to use ampersand a lot.  How much slower do you think it really is?  Anybody have experience with this?  Should I go rewrite the places that use ampersands to use plus signs instead?  Or is this too small to matter on today's modern systems, and should I just remember it going forward?

Copyright 2005 Genii Software Ltd.

What has been said:


286.1. Christopher Byrne
(02/08/2005 09:02 AM)

My understanding is that the ampersand (&) was most useful to concatenate strings from different value types.

So to me, the answer is "Depends on the situation". If I know I am only doing a concatenation of string elements, sure it might be more inefficient if the & forces an evaluation everytime.

If not, what is less efficient?

strValue + ": " + Cstr(iMeters)

or

strValue + ": " & iMeters


286.2. Damien Katz
(02/08/2005 09:18 AM)

While I can't be sure, I think Thomas is wrong here. I'll bet you'll see no noticable difference if you test the execution times.


286.3. Jess Stratton
(02/08/2005 10:58 AM)

I may be being REALLY naive on this one, so please don't make fun, but I would think it would be the opposite. According to the Lotus Help on concatenation operators:

"

Use the ampersand (&) operator to ensure a concatenation operation. The plus (+) operator also concatenates two character strings, but LotusScript determines whether to interpret the plus as a concatenation operator or an addition operator on the basis of the operands in the expression in which it appears.

"

Wouldn't it take longer using a "+" because LotusScript has to first analyze that it's not supposed to be adding it, but rather concatenating it?


286.4. Colin Pretorius
(02/08/2005 11:00 AM)

I recall a circa R5 performance/best practices document saying that & was recommended because it didn't require explicit type checks, while + did. I used to religiously + everything, read that article, then switched to &.

The best is to test, and I just did :) Not very scientific, but plussing two strings was no faster than ampersanding two strings, (12 seconds over 2 million iterations) but as soon as I threw an integer into the mix (str1 + str2 + cstr(10) versus str1 & str2 & 10), the ampersanding was faster, 15 seconds to 17.

I re-ran it a few times with consistent results, but this is on my dodgy (and busy) old Linux box using Wine, so ymmv.


286.5. Ben Langhinrichs
(02/08/2005 11:05 AM)

While not definitive, that certainly seems like enough feedback that I won't change my habits (until I hear something different, at least). Thanks all!


286.6. Jess Stratton
(02/08/2005 01:15 PM)

Colin,

How do you do a test like that? One that counts it? I've always wondered how a performance test like that is done...

Thanks!

Jess :-)


286.7. Julian Robichaux
(02/08/2005 03:14 PM)

I think it just depends on what your interpretation of "slow" is. Or really, what you consider "fast enough".

Without doing any tests, let's say that & is indeed slower than +, because it has to explicitly cast everything to a string before it concatenates. And let's say that because of that, it takes 0.00002 seconds to concatenate with & instead of 0.00001 seconds with + (wild ass guess, but concatenation is virtually instantaneous if you try to clock it, and even if I'm off by a factor of 10 it'll still make my point). So if you're doing something crazy in your script and you concatenate 100 times with &, you've just wasted 0.001 seconds of your user's time.

Now let's say that you decide to use + instead, and your concatenation is:

newString = oldString + doc.SomeField(0)

Everything compiles, but at some point a number gets in the doc.SomeField field, and causes a runtime error, which causes the agent not to run properly and makes you have to troubleshoot.

Which is slower: losing 0.001 seconds per agent run, or noticing, tracking down, and fixing a runtime error?

I'll take the less efficient & concatenation in that case.

And sure, you could code it as:

newString = oldString + CStr(doc.SomeField(0))

but how long did it take you to type that extra CStr() for every concatenation? 3 seconds each time? It'll take a lot of agent runs to make up that kind of lost time.

Yeah, the ampersand works for me, slower or not.

- Julian


286.8. Colin Pretorius
(02/08/2005 03:27 PM)

Jess, there are a couple of ways. The quick-and-dirtiest is to call the timer() function in LotusScript - that gives you the seconds since midnight, and you can just take readings before and after and compare them. The midnight thing means you need a bit more logic if you're planning to leave something running overnight :)

Another longwinded way is to instantiate two NotesDateTime objects (a start and a finish), call setNow() on the first before you start a section and call setNow() on the other when you're done, and then call finish.timeDifference(start) to get the difference in seconds.


286.9. Nathan T. Freeman
(02/09/2005 03:08 AM)

LOL.

startTime = Now

[process]

(Now - startTime)*86400


286.10. Colin Pretorius
(02/09/2005 04:48 AM)

I prefer using timer() in favour of calculating the difference between double-valued date variants and having to stop and remember/calculate the 86400 bit to convert to seconds.

I guess I should have mentioned it as well though. Sorry Nathan, was there anything else I left out?


286.11. Jess Stratton
(02/09/2005 10:31 AM)

Thanks everyone! I don't know why I assumed it would be more complicated than that...


286.12. Thomas Gumz
(02/09/2005 12:20 PM)

Both Colin's and Nathan's methods work, but the results are in seconds, which, for lots of benchmarks, simply isn't good enough.

Fortunately, Notes/Domino lets you use a high resolution timer (not measured in sconds, but CPU 'ticks').

Here's some sample code on how to use them:

%include "lsprcval.lss"

Dim lStart as Long

DIm lStop Long

lStart = Getthreadinfo(LSI_THREAD_TICKS)

'do some work...

lStop = Getthreadinfo(LSI_THREAD_TICKS)

msgbox "Ticks: " & lStop - lStart

[a [href]http://thomasgumz.net/[/href]Thomas[/a]


286.13. Colin Pretorius
(02/09/2005 12:58 PM)

Now _that_ rocks. Thanks!


286.14. Colin Pretorius
(02/09/2005 01:19 PM)

...and I see GetThreadInfo in the help db. Naughty me ;)


286.15. Alain H Romedenne
(02/18/2005 05:58 AM)

While timing script routines, note lsi_info(98), lsi_info(99) provide getThreadInfo(n) equivalence with older releases.

You'll get a precision scaling down to microseconds on Wintel platforms while using Stopwatches class from org.OpenNTF.OpenDOM project.


286.16. harkpabst_meliantrop
(26.01.2006 08:39)

Thomas, I not only like the hi-res timer code, but also the fact that it uses an ampersand instead of + Cstr(long) .... ;-)