Skip to content

Could be made faster? #10

@osa1

Description

@osa1

The constant lists in types.dart could be made Float64Lists which would be more efficient to use on all targets (native, JS, Wasm).

Classes Float2 and Vector3f etc. should be avoided in the lists to avoid indirections, and extra allocations when dynamically alloated (doesn't apply to use case in this library as they're all consts). Instead you can store two floats in a Float64List per element, instead of Float2, and similar for other element types (e.g. 3 doubles for Vector3f).

Relatedly, this is not a good idea:

// TODO(spydon): Convert these to use vector_math

vector_math is slow unless you need the storage getters. If you don't, the fastest would be storing the numbers directly in typed arrays (store multiple numbers per element if needed), and the second fastest would be the current version in this library.

If you migrate to vector_math everything will be slower, because it will add one more layer of indirection when accessing the actual numbers, as it stores the numbers in a separate typed array.

Similarly it would be more efficient to allocate, keep in memory, and use if functions like https://pub.dev/documentation/fast_noise/latest/fast_noise/noise3.html could return a typed array.

(I'm curious what these doubles represent in the output of functions like noise3 and how I'm supposed to use them if I want to generate e.g. a PNG?)

Another slow type that this libaray uses is Int32:

@pragma('vm:prefer-inline')
int hash2D(int seed, int x, int y) {
IntX hash = Int32(seed);
hash ^= _xPrime * x;
hash ^= _yPrime * y;
hash = hash * hash * hash * 60493;
hash = (hash >> 13) ^ hash;
return hash.toInt();
}

fixnum classes are slow because they add one layer of indirection to the actual number.

I'm not sure if the hash function depends on 32-bit arithmetic, but if you use 32-bit numbers for performance reasons, than using int will be faster.

Here's how hash2D looks today when compiled to Wasm with dart compile wasm -O4:

  (func $hash2D (;314;) (param $var0 i64) (param $var1 i64) (result i64)
    (local $var2 (ref $_Environment_56))
    i64.const 1337
    call $Int32
    i32.const 81
    local.get $var0
    i64.const 1619
    i64.mul
    struct.new $BoxedInt
    call $Int32.^
    i32.const 81
    local.get $var1
    i64.const 31337
    i64.mul
    struct.new $BoxedInt
    call $Int32.^
    local.tee $var2
    local.get $var2
    call $Int32.*
    local.get $var2
    call $Int32.*
    global.get $global66
    call $Int32.*
    local.tee $var2
    call $Int32.>>
    local.get $var2
    call $Int32.^
    struct.get $_Environment_56 $field2
  )

All these calls and allocations (call $Int32, struct.new $BoxedInt) will disappear if you use int.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions