Skip to main content

Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines
(+1)

Lil performance question: I have used LiveCode for years, and its built-in language is not fast. So when I try out a new language, the first thing I do after Hello World is a for loop to get a sense of the speed of the language. I tried that with Lil on an M1 MacBook, and found that 

on click do
each x in range 1000000
end
 alert["Done!"]
end

takes about 2 seconds to run. This is about 30x slower than even LiveCode. This is not a criticism, just a question: any thoughts on ways to speed up Lil?

(4 edits) (+2)

There's a lot of room for improvement in Lil performance. The each loop in your example is particularly expensive because "each" is a map operation yielding a result list, range eagerly creates an entire list, and each loop body is executed in its own scope. Contrast with "while", which is considerably faster due to involving less bookkeeping and keeping much less in memory at once:

while x<1000000
  x:1+x
end

Or, when it's possible, just using the natural "conforming" over lists:

1+range 1000000

Performance for each over a huge list is particularly bad in c-lil; I'll do some investigating.

Interesting -- I'm not terribly familiar with list generation: I've played with Python, so I know it's a thing, but LiveCode has nothing like it built in, and I would never do something like

repeat with i = 1 to 1000000
    put i,"" after aList
end repeat
repeat for each item i in aList
    -- do something
end repeat

I just checked and found that the while loop was even slower :-)

I'm not sure this accomplishes the same task, albeit that the task is synthetic in the first place, but in any case, this is about 20x faster:

on click do
range 10000000
 alert["Done!"]
end
(1 edit) (+1)

Oh, there's one other thing I should note that's probably making us talk past one another somewhat: Lil in Decker is deliberately capped at a specific number of "ops" (VM bytecode steps) per "frame" (display updates at 60fps) . This is an arbitrary creative constraint intended to help decks behave more consistently across different machines with wildly different levels of performance. The "FRAME_QUOTA" constant in the JavaScript implementation controls this cutoff.

Oh, HA! Okay, that makes sense. "constant in the JavaScript implementation" -- meaning updating it requires rebuilding Decker from source? Or is it configurable?

You can rebuild from source, or, in a web build, just open the file in your favorite text editor, search for "FRAME_QUOTA", and tweak as desired. I may raise the limit and/or make it configurable at runtime in the future.

Is there an API to check “fraction of script steps remaining this frame” from inside a Lil script? (For operations with shorter limits, like accessing a property on a Contraption, is there one that checks the operation limit?)

I’m consider9ing Decker to write a loosely-chess-inspired roguelike, and I’d want to use this to know when to stop searching for a move on the current frame and advance a “thinking” animation so the deck does not act frozen during the opponent’s turn.

(1 edit) (+1)

There is not presently a way to inspect the remaining per-frame quota (or other limits) from within executing scripts.

As a developer you can get a rough idea of how close your scripts are to quota by enabling the "Script Profiler" feature from within the Decker menu. This will display a live chart of the percentage of quota scripts have consumed over the past few seconds.

If you want to provide the user with visual feedback during long-running scripts, you need only draw visible updates from time to time. When a script runs out of quota it is simply paused momentarily to allow Decker to service input and then automatically resumed, unless the user explicitly halts it.

(1 edit)

LiveCode script (and the GPLv3 community fork OpenXTalk) has arrays which can be considerably faster then using comma-seperated-values for  text container 'lists' (but when I do I use tab as a delimiter).
Also LC / OXT has a second language, the Extension Builder lang for making 'Widgets' and wrapping external code libraries, which does have an actual List type where the ordered elements can be of any type, Text, Numbers, JSON, Java, or C and ObjC types, Pointers, etc.