If we manually add vertices & set attributes, we can be much faster than the default .from_pydata() that Blender uses.
These benchmarks are just operating on the verts, but the same approach for adding edges and faces can be taken.
Benchmark below:
import bpy
import numpy as np
n = int(1e5)
data = np.random.rand(n * 3).astype(np.float32).reshape(n, 3)
def from_pydata():
mesh = bpy.data.meshes.new("mesh")
mesh.from_pydata(data, [], [])
def vertices_foreach_set():
mesh = bpy.data.meshes.new("mesh")
mesh.vertices.add(n)
mesh.vertices.foreach_set("co", data.ravel())
def attributes_foreach_set():
mesh = bpy.data.meshes.new("mesh")
mesh.vertices.add(n)
mesh.attributes["position"].data.foreach_set("vector", data.ravel())
def test_from_pydata(benchmark):
result = benchmark(from_pydata)
def test_vertices_foreach_set(benchmark):
result = benchmark(vertices_foreach_set)
def test_attributes_foreach_set(benchmark):
result = benchmark(attributes_foreach_set)
A total of 350x faster to manually allocate verts and then operate on their position attribute:

If we manually add vertices & set attributes, we can be much faster than the default
.from_pydata()that Blender uses.These benchmarks are just operating on the verts, but the same approach for adding edges and faces can be taken.
Benchmark below:
A total of 350x faster to manually allocate verts and then operate on their
positionattribute: