On Performance of Array Access
Mark Waddingham
mark at livecode.com
Fri Aug 31 09:58:04 EDT 2018
Generally, I don't tend to like to 'jump the gun' on anything related to
optimization lest it is not what it seems when running in the real world
but...
I'm becoming increasingly confident that a recent foray of mine into yet
another attempt to improve the speed of array access in LC9 might have
actually born some quite tasty fruit. Pleasingly the code changes
required are small, highly localized and quite possibly more than
suitable for including in a 9.0.x maintenance release.
The current WIP PR can be found here:
https://github.com/livecode/livecode/pull/6671
Amusingly this didn't even start as an attempt at optimization, but an
attempt to see if I could do anything about heap fragmentation!
The patch itself does three things:
1) Minimizes the in-memory size of the core types - all 'book-keeping'
records are now <=32 bytes on 64-bit systems
2) Makes use of tArray[x]...[z] type expressions much more efficient
when both evaluating and mutating
3) Makes use of integer indicies in arrays much more efficient
I've been running it on a number of benchmarks, the two most notable
follow.
LARGE ARRAY CONSTRUCTION
The following simple code example was supplied in Bug 17434 by Richard
as it appears to show a memory leak (its actually heap fragmentation,
but that's another story):
put 100 into tMax
repeat with i = 1 to tMax
repeat with j = 1 to tMax
repeat with k = 1 to tMax
put any item of "bob,carol,ted,alice" into sA[i][j][k]
end repeat
end repeat
end repeat
The code constructs an 100x100x100 matrix (rendered as a nested array,
rather than a flat one).
Timings in various versions (on my 2018 MBP laptop) are:
6.7.11: 1117ms
9.0.1: 4020ms
PR6671: 1017ms
This would seem to be a not too uncommon a pattern of code - judging by
JBV's recent post on here (which was essentially doing the same thing).
We can modify the above slightly to make it more focussed on array
performance (i.e. taking out the need to construct / copy a random
portion of a string):
put 100 into tMax
repeat with i = 1 to tMax
repeat with j = 1 to tMax
repeat with k = 1 to tMax
put "bob,carol,ted,alice" into sA[i][j][k]
end repeat
end repeat
end repeat
Timings for this are:
6.7.11: 1055ms
9.0.1: 3281ms
PR6671: 497ms
ARRAY RECORD FILTERING
The following code example was derived by me for my recent LCG talk
based on a real-world code supplied by Mark Talluto. It iterates over a
sequence of arrays, creating a new one where each record only has a
subset of the keys. The keys to keep are taken from a stringlist:
private function _BenchmarkArrayFilterRecords pRecords, pColumnNames
local tFilteredRecords, tFilteredRecord
repeat for each element tRecord in pRecords
repeat for each item tColumnName in pColumnNames
put tRecord[tColumnName] into tFilteredRecord[tColumnName]
end repeat
put tFilteredRecord into \
tFilteredRecords[the number of elements in tFilteredRecords
+ 1]
end repeat
return tFilteredRecords
end _BenchmarkArrayFilterRecords
Timings for 100000 iterations of the above are:
6.7.11: 16872ms
9.0.1: 8305ms
PR6671: 4315ms
The following is the same as the above, except the keys to keep are
taken from the keys of an array:
private function _BenchmarkArrayFilterRecordsSet pRecords,
pColumnNameSet
local tFilteredRecords, tFilteredRecord
repeat for each element tRecord in pRecords
repeat for each key tColumnName in pColumnNameSet
put tRecord[tColumnName] into tFilteredRecord[tColumnName]
end repeat
put tFilteredRecord into \
tFilteredRecords[the number of elements in tFilteredRecords
+ 1]
end repeat
return tFilteredRecords
end _BenchmarkArrayFilterRecordsSet
Timings for 100000 iterations of the above are:
6.7.11: 16508ms
9.0.1: 6397ms
PR6671: 3001ms
REAL WORLD CASE
Now, I'm always a little skeptical about using synthetic benchmarks for
performance. However, both of the above are actually real-world
examples. Furthermore, when running a rather large LCS project on an
engine with PR6671, I got a 2x speed up - one particular input took
3mins to process, rather than 6mins (one phase of processing actually
saw a 5x speed up!).
Anyway, thought this might make some potentially pleasing Friday
afternoon news :)
Warmest Regards,
Mark.
--
Mark Waddingham ~ mark at livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps
More information about the use-livecode
mailing list