Skip to content

Conversion of Python (NumPy) array to Godot PoolByteArray is slow #305

@kb173

Description

@kb173

We'd like to convert Matplotlib renderings into Godot textures. We got this working (see https://github.com/boku-ilen/landscapelab/blob/master/Python/PythonTest.py), but the performance is pretty bad. Specifically, this line:

pool_array = PoolByteArray(array.flatten())

which turns a NumPy array of size 3686400 into a Godot PoolByteArray, takes 500ms on average. I realize that it's a large array, but it seems like too big of a bottleneck - it's the most time-consuming operation of the entire script by far.

I initially suspected that the problem lies somewhere around here: https://github.com/touilleMan/godot-python/blob/master/generation/builtins_templates/array.tmpl.pxi#L44
My first idea was to modify it to self.resize() once and then set the elements by index, rather than appending, but this caused no difference in performance (which I found surprising). I tried the same in https://github.com/touilleMan/godot-python/blob/master/generation/pool_arrays_templates/pool_x_array.tmpl.pyx#L32 with a similarly non-significant effect.

However, I later realized that the problem seems to be inherent in setting data in any Godot Array one by one: when I iterate over 3686400 elements and put them into a PoolByteArray in GDScript, I get the same timings of around 500ms. If I instead construct a PoolByteArray out of a Godot Array (again in GDScript) directly, it takes <100ms on average.

Thus, it seems like the only way to drastically improve performance here would be to do a more direct memory-copy of a NumPy Array into a Godot Array or PoolByteArray. I don't know much about under-the-hood memory management in Python and NumPy; does anyone here have an idea of if and how this could be accomplished? Alternatively, maybe there's some indirection here that could be improved by adding more specialized code into the Cython codebase of the addon?

TL;DR: Manually constructing a PoolByteArray by setting each element is slow, both in GDScript and in PythonScript. Is there a way to do a more direct memory-copy of a NumPy Array into a Godot Array or PoolByteArray?

Thank you for the great plugin by the way! Even if the performance issues persist, being able to use Python libraries like Matplotlib in Godot is really powerful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions