optimized FOREACH performance for large linked lists

pull/89/head
jmoenig 2019-05-31 10:31:21 +02:00
rodzic 2596fabf11
commit cecf87f3e2
3 zmienionych plików z 39 dodań i 21 usunięć

Wyświetl plik

@ -83,6 +83,9 @@
* German * German
* French * French
### 2019-05-31
* Threads: optimized FOREACH performance for large linked lists
### 2019-05-29 ### 2019-05-29
* Threads, Objects: added "Find First" primitive to lists category * Threads, Objects: added "Find First" primitive to lists category
* Blocks, Threads, Objects: added "blitz" version of FIND * Blocks, Threads, Objects: added "blitz" version of FIND

Wyświetl plik

@ -7,7 +7,7 @@
<script type="text/javascript" src="src/morphic.js?version=2019-05-21"></script> <script type="text/javascript" src="src/morphic.js?version=2019-05-21"></script>
<script type="text/javascript" src="src/widgets.js?version=2019-04-05"></script> <script type="text/javascript" src="src/widgets.js?version=2019-04-05"></script>
<script type="text/javascript" src="src/blocks.js?version=2019-05-29"></script> <script type="text/javascript" src="src/blocks.js?version=2019-05-29"></script>
<script type="text/javascript" src="src/threads.js?version=2019-05-29"></script> <script type="text/javascript" src="src/threads.js?version=2019-05-31"></script>
<script type="text/javascript" src="src/objects.js?version=2019-05-29"></script> <script type="text/javascript" src="src/objects.js?version=2019-05-29"></script>
<script type="text/javascript" src="src/gui.js?version=2019-05-29"></script> <script type="text/javascript" src="src/gui.js?version=2019-05-29"></script>
<script type="text/javascript" src="src/paint.js?version=2019-02-22"></script> <script type="text/javascript" src="src/paint.js?version=2019-02-22"></script>

Wyświetl plik

@ -61,7 +61,7 @@ StageMorph, SpriteMorph, StagePrompterMorph, Note, modules, isString, copy,
isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color, isNil, WatcherMorph, List, ListWatcherMorph, alert, console, TableMorph, Color,
TableFrameMorph, ColorSlotMorph, isSnapObject, Map, newCanvas, Symbol*/ TableFrameMorph, ColorSlotMorph, isSnapObject, Map, newCanvas, Symbol*/
modules.threads = '2019-May-29'; modules.threads = '2019-May-31';
var ThreadManager; var ThreadManager;
var Process; var Process;
@ -2150,33 +2150,48 @@ Process.prototype.doWaitUntil = function (goalCondition) {
// Process interpolated iteration primitives // Process interpolated iteration primitives
/*
these primitives can be - for the most part easily - written as
custom blocks by users themselves. They are, or used to be, in
libraries that could be loaded additionally. Making them available
as primitives has the benefit of getting novices acquainted to
using HOFs plus some performance advantages, however at the cost
of losing the ability to inspect how they're written.
*/
Process.prototype.doForEach = function (upvar, list, script) { Process.prototype.doForEach = function (upvar, list, script) {
//Process.prototype.reportFindFirst = function (predicate, list) {
// perform a script for each element of a list, assigning the // perform a script for each element of a list, assigning the
// current iteration's element to a variable with the name // current iteration's element to a variable with the name
// specified in the "upvar" parameter, so it can be referenced // specified in the "upvar" parameter, so it can be referenced
// within the script. Uses the context's - unused - fourth // within the script.
// element as temporary storage for the current list index // Distinguish between linked and arrayed lists.
var next;
this.assertType(list, 'list'); this.assertType(list, 'list');
if (isNil(this.context.inputs[3])) {this.context.inputs[3] = 1; } if (list.isLinked) {
var index = this.context.inputs[3], if (this.context.accumulator === null) {
item = list.at(index); this.context.accumulator = {
this.context.outerContext.variables.addVar(upvar); source : list,
this.context.outerContext.variables.setVar(upvar, item); remaining : list.length()
if (index > list.length()) {return; } };
this.context.inputs[3] += 1; }
if (this.context.accumulator.remaining === 0) {
return;
}
next = this.context.accumulator.source.at(1);
this.context.accumulator.remaining -= 1;
this.context.accumulator.source =
this.context.accumulator.source.cdr();
} else { // arrayed
if (this.context.accumulator === null) {
this.context.accumulator = {
idx : 0
};
}
if (this.context.accumulator.idx === list.length()) {
return;
}
this.context.accumulator.idx += 1;
next = list.at(this.context.accumulator.idx);
}
this.pushContext('doYield'); this.pushContext('doYield');
this.pushContext(); this.pushContext();
this.evaluate(script, new List([item]), true); this.context.outerContext.variables.addVar(upvar);
this.context.outerContext.variables.setVar(upvar, next);
this.evaluate(script, new List([next]), true);
}; };
Process.prototype.doFor = function (upvar, start, end, script) { Process.prototype.doFor = function (upvar, start, end, script) {