## Improve unboxing further

From: #3349 (closed)

I also feel that I really miss in pure Python an efficient fixed size homogeneous mutable sequence that can contain instances of user-defined classes. (...) For very simple classes like

`Point3d`

and`Point4d`

, I wonder if the data could be saved continuously in memory and if some operations could be done without boxing/unboxing.

The new unboxing for instance fields added in 7.3.4 is great but only partially address the problem. If you have a list of instances, each instance is still not unboxed with respect to the list (i.e., the underlying storage isn't a flat list of numbers).

I have commented about this before elsewhere (see the dense array of struct section) and noted that you can manually layout the memory with `ffi.cdef`

and that actually performs way better than a list of instances in pypy. But this is arguably not python anymore. Is there some way the get the same result automatically?

Quick benchmark:

```
N = 10 ** 7
WAY = "ffi"
# WAY = "class"
def main():
print(WAY)
if WAY == "ffi":
from cffi import FFI
ffi = FFI()
ffi.cdef(
"""
typedef struct {
double x;
double y;
double z;
} node_t;
"""
)
def combine(point1, point2):
point1.x += point2.x
point1.y += point2.y
point1.z += point2.z
# Init list
points = ffi.new("node_t[]", N)
for i in range(N):
points[i].x = 1.0
points[i].y = 2.0
points[i].z = 3.0
# Add all of them
result = ffi.new("node_t*")
result.x = 0.0
result.y = 0.0
result.z = 0.0
for i in range(N):
combine(result, points[i])
print(result.x, result.y, result.z)
elif WAY == "class":
class Node:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def combine(point1, point2):
point1.x += point2.x
point1.y += point2.y
point1.z += point2.z
# Init list
points = [Node(1.0, 2.0, 3.0) for i in range(N)]
# Add all of them
result = Node(0.0, 0.0, 0.0)
for i in range(N):
combine(result, points[i])
print(result.x, result.y, result.z)
main()
```

WAY | time |
---|---|

ffi | 0.2s |

class (pypy 7.3.3) | 1.66s |

class (pypy 7.3.4) | 1.5s |