Performance when copying a mesh

Hello, I’m working on compas_fab and compas_robots, trying to make deepcopy of RobotModels. I noticed a rather poor performance when copying a RobotModel with a detailed (high vertice count) visual mesh. A reasonable 6 axis robot with both visual and collision mesh will take roughly 30 seconds to copy.

I did some debugging and profiling and traced the problem to the deepcopy performance of Mesh objects. I made the following code to elaborate:

import time
from copy import deepcopy

import compas
from compas.datastructures import Mesh

mesh = Mesh.from_ply(compas.get("bunny.ply"))
print(mesh)


def run():
    start_time = time.time()
    _ = mesh.copy()
    print("Time to copy mesh: ", time.time() - start_time)

    start_time = time.time()
    _ = deepcopy(mesh)
    print("Time to deepcopy mesh: ", time.time() - start_time)

    start_time = time.time()
    _ = Mesh.from_jsonstring(mesh.to_jsonstring())
    print("Time to copy mesh from json: ", time.time() - start_time)

    start_time = time.time()
    _ = Mesh.from_vertices_and_faces(*mesh.to_vertices_and_faces())
    print("Time to copy mesh from vertices and faces: ", time.time() - start_time)

    start_time = time.time()
    with open("bunny.obj", "w") as f:
        mesh.to_obj(f)
    Mesh.from_obj("bunny.obj")
    print("Time to copy mesh from obj: ", time.time() - start_time)


run()

The result when running in non-debug mode:

<Mesh with 35947 vertices, 69451 faces, 104288 edges>
Time to copy mesh:  0.9314494132995605
Time to deepcopy mesh:  0.9586617946624756
Time to copy mesh from json:  0.8528554439544678
Time to copy mesh from vertices and faces:  0.5416598320007324
Time to copy mesh from obj:  1.532799482345581

But very often we run things in debug mode and the performance hit is rather significant:

<Mesh with 35947 vertices, 69451 faces, 104288 edges>
Time to copy mesh:  3.6830360889434814
Time to deepcopy mesh:  4.6975157260894775
Time to copy mesh from json:  1.7972691059112549
Time to copy mesh from vertices and faces:  1.558525562286377
Time to copy mesh from obj:  4.276987552642822

I think the data speaks for itself and the performance of copy() and deepcopy() are both worse then even the seemingly more convoluted route to go to json and back, or go to vertices and faces and back. I wonder if there can be some slightly better way of overloading the copy() or deepcopy() behaviour to make things slightly faster. I think something closer to the performance of the to_json route would make sense.

1 Like

Another snippet for going via an in-memory obj.

    from io import StringIO

    start_time = time.time()
    string_buffer = StringIO()
    mesh.to_obj(string_buffer)
    _ = Mesh.from_obj(string_buffer)
    print("Time to copy mesh from in-memory obj: ", time.time() - start_time)

what do you mean with “debug” mode?

Like VSCode F5 type of debug mode.