Using Association
to generate complicated data types is very comfortable, in particular if one uses those tricks from How to make use of Associations?. However, I observed that writing into deeper levels of associations can be quite slow in certain circumstance. Here is a minimal example:
m = 1000;
n = 30000;
A = RandomReal[{-1, 1}, {m, n}];
y = RandomReal[{-1, 1}, {n}];
u = RandomReal[{-1, 1}, {m}];
i = RandomInteger[{1, m}];
a = Association["Data" -> A];
a[["Data", i]] = y; // AbsoluteTiming // First
a[["Data", i + 1]] = y + 1.; // AbsoluteTiming // First
0.12598
0.141002
This is inacceptibly slow compared to a direct write into an array:
B = A;
B[[i]] = y; // AbsoluteTiming // First
B[[i + 1]] = y + 1.; // AbsoluteTiming // First
0.12496
0.000159
The first timing seems to be dominated by the cost of copying the values of A to B. This is executed with delay due to lazy copy. It's understood that this cost cannot be avoided completely. But as we can see, the second write operation is much faster.
I would have expected that a PackedArray
is stored within an Association
internally as a pointer so that all but the first modifications do not require copying. When done in some compiled library, this would not effect immutability of Association
.
Seemingly, the implementation of deeper write-indexing was done simpler than that; the most naive way coming to my mind being:
(B = a[["Data"]]; B[[i]] = y; b = Association["Data" -> B]); // AbsoluteTiming // First
(B = b[["Data"]]; B[[i + 1]] = y + 1.; c = Association["Data" -> B]); // AbsoluteTiming // First
0.13791
0.143413
And this is not so bad compared to Mathematica's performance.
So, who has ideas to improve on this? (Really, I would pretty much love to use large PackedArrays nested in Associations...)