Which is faster...

Mark Waddingham mark at livecode.com
Fri Dec 15 10:00:06 EST 2023


On 2023-12-14 21:22, Paul Dupuis via use-livecode wrote:
> Which is faster or more efficient (from an engine performance 
> perspective)?
> 
> To retrieve an array from a property?
> As in:
> command someHandler -- in an objects script
>   get the cMyArray from me -- cMyArray is some multi-dimensional array
>   ...
> end someHandler
> 
> OR
> 
> To retrieve an array from a script local variable?
> As in:
> local sMyArray -- script local variable in some objects script
> 
> command someHandler -- in an objects script
>   get sMyArray
>   ...
> end someHandler
> 
> Anyone know?

Fetching a value directly from a variable will always be faster than any 
other method - as it essentially reduces to fetching or storing a value 
from a (integer indexed) table.

In contrast, fetching a custom property will require a message send 
unless lock messages is set, and then an array lookup (to actually get 
the property's value).

Custom property sets are stored using the same data structure internally 
as livecode arrays so getting `the cMyArray of me` eventually reduces to 
the same as objectsCurrentPropertySet["cMyArray"] - the latter lookup is 
more work than just fetching a value from an internal table.

UPSHOT:

Fetching a value directly from a variable is a constant time operation.

If lock messages is false, then the time it takes to fetch a custom 
property value will be somewhat proportional to the length of the 
message path from the point of view of the object you are accessing - 
i.e. how many frontscripts, backscripts, stacks in use, and parent 
objects/behaviors the object has.

If lock messages is true, then the time it takes to fetch a custom 
property value will be pretty much the same as doing an LC array key 
lookup.

Now whether or not this actually matters in any one case will largely 
depend on how often such access is being done - if its a few times in 
the context of UI-related code then it probably won't be appreciable; 
if, however, you are fetching a custom property 100000's of times in a 
tight loop and the rest of the loop is only doing small amounts of work, 
you'll definitely notice a difference.

SIMPLE BENCHMARK:

```

on mouseUp
local sMyArray

on mouseUp
    set the cMyArray of me to [ 1, 2, 3 ]
    put empty

    local tTime
    put the milliseconds into tTime
    repeat 1000000 times
       get the cMyArray of me
    end repeat
    put "CUSTOM PROP:" && the milliseconds - tTime & return after msg

    put the milliseconds into tTime
    lock messages
    repeat 1000000 times
       get the cMyArray of me
    end repeat
    unlock messages
    put "CUSTOM PROP (LOCKED OUTSIDE):" && the milliseconds - tTime & 
return after msg

    put the milliseconds into tTime
    repeat 1000000 times
       lock messages
       get the cMyArray of me
       unlock messages
    end repeat
    put "CUSTOM PROP (LOCKED INSIDE):" && the milliseconds - tTime & 
return after msg

    local tMyProps
    put [ 1, 2, 3 ] into tMyProps["cMyArray"]
    put the milliseconds into tTime
    repeat 1000000 times
       get sMyArray["cMyArray"]
    end repeat
    put "ARRAY ELEMENT:" && the milliseconds - tTime & return after msg

    put the milliseconds into tTime
    lock messages
    repeat 1000000 times
       get sMyArray
    end repeat
    unlock messages
    put "SCRIPT LOCAL:" && the milliseconds - tTime & return after msg
end mouseUp
end mouseUp
```

RESULTS (1 million iterations):

CUSTOM PROP: 2006
CUSTOM PROP (LOCKED OUTSIDE): 116
CUSTOM PROP (LOCKED INSIDE): 125
ARRAY ELEMENT: 80
SCRIPT LOCAL: 38

ANALYSIS:

The above results are run in the IDE which is important to mention 
because the message path in the IDE is typically longer than that in 
standalones (as the all extension libraries are loaded, and the IDE 
inserts its own front/back/stacks into the message path).

Accessing custom properties with messages locked is nearly 10x faster 
than without (again that multiplier will be vary with the length of the 
message path).

Using lock/unlock messages for every custom property access has a (quite 
negligible) 10% overhead - and the message path overhead (in the IDE) is 
about 40% of the total (the array element fetch will be the rest).

Accessing a script local is
   - about 50x faster than accessing a custom property when messages are 
sent
   - about 3x faster than accessing a custom property when messages are 
not sent
   - about 2x faster than accessing an array element

Just to reiterate - these figures are for 1,000,000 accesses done in a 
tight loop (in the IDE). If you do it for (say) 1000 iterations then the 
differences are within the margin of error of measuring a millisecond.

Overall, my suggestion would be probably to do a combination of both - 
if you are only reading from a custom property in a given loop, but are 
doing so multiple times for the same property (and the loop actually has 
a very high number of iterations!) then fetch into a local variable 
before the loop and then use that value (the same, to be fair, is true 
of calling functions which return fixed values and accessing array 
elements - especially ones on paths longer than one).

Hope this helps,

Mark.

-- 
Mark Waddingham ~ mark at livecode.com ~ http://www.livecode.com/
LiveCode: Build Amazing Things



More information about the use-livecode mailing list