Implementing a Desktop Compiler Optimization - NetLogo/Tortoise GitHub Wiki

We have a closed ticket to implement the desktop compiler's optimizations in Tortoise. This is a brief overview on the process to follow to implement one of them.

You may wish to start by reading up on how the NetLogo desktop compiler architecture, paying particular attention to the optimization steps.

For reference, a few example optimizations that have been done already and can be used as reference include "Nsums", "Nsums4", and "OtherWith".

Info

The NetLogo desktop optimizations (well, most of them), are defined in the package.scala file and live in the org.nlogo.compile.middle.optimize package. The Optimizations.scala file contains a class that collects those optimizations for application during compilation (after the first pass of parsing). One of the reasons they are collected there is so they can be selectively disabled in order to allow us to test NetLogo headless compiled code against NetLogo Web compiled code where we may not have implemented the optimizations yet.

On the Tortoise side, There is a different Optimizer.scala file. This file defines the NetLogo Web "middle layer" compilation optimizations - after parsing but before final transformation into Javascript. It provides classes and code to turn common NetLogo command and reporter combinations into more efficient versions. Then in the final compiler pass when these efficient primitives are found, they are replaced with the optimized Javascript code.

Process

We assume we want to implement the "AnyWith1" optimization in this process, as an example.

  • Make sure to understand what you're testing in NetLogo code. A lot of these optimizations take combinations of primitives that can be more efficient when they're processed together.
    • The reporter any? turtles with [ color = red ] would normally run turtles with [ color = red ] creating an agent set of red turtles followed by an any? check on that result, but they can be combined to save some time by reporting true when the first turtle with the condition is found.
  • Create a simple language test for it in Tortoise.txt in Tortoise so you can quickly test it using netLogoWeb/testOnly *Commands -- -z Tortoise using the sbt console.
    • This is just a fast, easy-to-run test for implementation purposes, it shouldn't be checked in with any commits.
  • Add the optimization in the proper DockingFixtures.scala section (Command or Reporter), matched against the NetLogo repository's Optimizations.scala, so it'll be used in all other tests, too.
  • Find the optimized prim version in the NetLogo repository. This will be the logic we'd like to duplicate.
    • Example: The _anywith class in _anywith.scala. But make sure to look at the version from headless and not netlogo-gui.
  • In Tortoise, create the appropriate primitive class and transformation object in Optimizer.scala.
    • You'll also need to add it to the apply() procedure to get it inserting itself into the AST.
    • For implementing _anywith you can check out _oneofwith, which is a similar optimization.
  • In Tortoise, add the matching prim in Prims.scala.
    • This is where the compiled primitive from the AST is translated into the CoffeeScript code that will actually be run by the engine.
    • After adding the prim, you should re-run your quick Tortoise.txt test and confirm it fails - the optimization is seen, but you haven't implemented the functionality yet so it breaks. If the test passes, something may not be right.
  • In Tortoise, add the optimized code in the appropriate place in the engine, depending on the prim and optimization.
    • For _anywith, this applies to agent sets, so we'd look to an agent set class to implement it.
  • Run tests, work on it until it passes.
  • Run a broader set of tests (netLogoWeb/test:fast and netLogoWeb/testOnly *Reporters are good ones), make sure they all still pass.
  • Publish the Tortoise artifacts locally and use them in Galapagos to test a model using the now optimized primitives. You should be able to use a web developer console to actually step through your optimized code.

Desktop Compiler Optimizations

All desktop compiler optimizations are implemented as of September 2020. see the Optimizations.scala file for the full list and to check if maybe we're missing some new ones (hopefully a docking test or model test would fail if so).