New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Precompute data at top level with `grab` #511

Merged
merged 5 commits into from Mar 1, 2018

Conversation

Projects
None yet
1 participant
@bvssvni
Member

bvssvni commented Mar 1, 2018

The grab expression is used to capture data explicitly in closures. Until now, it could not be used outside closures. For more information about grab, see #316

This PR adds a feature which lets you precompute data in sources with grab. It leads to better performance when using immutable data in inner loops.

The motivation behind this feature is to improve performance for procedurally generated content, which often uses a lot of immutable data (e.g. audio), and when the data can not be passed in to the script, e.g. by calling a Dyon function from Rust for each sample (44100 times a second).

For example, here is a program without grab:

fn main() {
    start := now()
    for i 10000000 {
        a := link {1 2 3 4 5 6 7 8 9 10 11 12}
    }
    println(now() - start)
}

It takes 8.28 seconds to run this on my computer.

Here is the same program with grab:

fn main() {
    start := now()
    for i 10000000 {
        a := grab link {1 2 3 4 5 6 7 8 9 10 11 12}
    }
    println(now() - start)
}

The time is now reduced to 1.84 seconds.

Notice that this only works with pure data. You can not do any computation, e.g. grab 1 + 3. This is because precomputing happens when the script is loaded, which should not execute any code.

The following data can be precomputed:

  • Array fill, e.g. [false; 24]
  • Array, e.g. [1, 2, 3]
  • Object, e.g. {a: 1, b: 2}
  • 4D vector, e.g. (1, 2, 3, 4)
  • Link structure, e.g. link {1 "hi" false}

The data structures can be nested, e.g. [[1, 2], [3, 4]] or [{a: 1, b: 3}, {a: 2, b: 4}].

Since the grab expression at top level injects the variable into the AST, when you mutate the variable Dyon will use copy-on-write. This means that grab expressions at top level is slower when mutating the variable, but faster when only reading from it.

@bvssvni bvssvni merged commit 939a8e1 into PistonDevelopers:master Mar 1, 2018

@bvssvni bvssvni deleted the bvssvni:precompute branch Mar 1, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment