michael-buschbeck / mychs-macro-magic

A simple, sane, and friendly little scripting language for your Roll20 macros.
MIT License
1 stars 1 forks source link

Work around Roll20 "possible infinite loop detected" on using `sendChat()` with large amounts of text #189

Closed michael-buschbeck closed 2 years ago

michael-buschbeck commented 2 years ago

The new autorun macro (see #165) feature has been used to great effect to pre-parse sizable chunks of reusable macro code.

However, it has exposed a crippling inefficiency in Roll20's handling of anything that expands to a large amount of text through the sendChat() API function that frequently leads to "possible infinite loop detected" API sandbox crashes due to the sandbox becoming unresponsive for significant amounts of time (30 seconds or more).

This issue has nothing to do with MMM itself – it can be reproduced without MMM even being installed/enabled simply by using sendChat() to send loads of lines looking like this…

!foo xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

…which (intentionally) don't address any installed API script at all and are effectively completely ignored. (Those lines still pass by any API scripts' chat:message handlers, of course, but it turns out this happens reasonably quickly and the slowdown happens after control has returned from sandbox code to Roll20.)

Experimentation with those !foo dummy macro lines above (and MMM disabled) demonstrate that it's not even the sheer total number of lines sent through sendChat() – it's in fact the number of lines sent though sendChat() before control returns to Roll20 from within the sandbox.

The following experiment sends chunks of lines separated by \n in a single sendChat() call, then schedules the next chunk using setTimeout() with a 1-millisecond delay:

Supplemental observation: With larger chunks, the first few chunks fly past quickly and then chunks start taking progressively longer until they essentially come to a standstill.

Supplemental experiment: Separating those !foo lines with anything else than \n (e.g. with X), producing the same amount of data but only a single "physical" line, makes all of the experiments above fly by very quickly without any slowdown at all.

Preliminary hypothesis:

Rationale:

michael-buschbeck commented 2 years ago

Supplemental supplemental experiment: Enclosing an entire chunk of lines with \n separators with {{ and }} – which makes it into a single multi-line message as far as Roll20 is concerned – also makes the issue go away.

Since MMM already supports processing multi-line chat messages produced by including {{ }} pairs in script code (see #26), doing just that for our lengthy autorun macro (after escaping all embedded {{ and }} as {\{ and }\}, respectively) serves as a passable workaround:

!rem {{
%{macroSheetLibrary|initGlobals}
!rem }}