# Why is extracting values from an Association with 1 level slower than extracting values from a list of depth 1?

I am not looking for a solution or work-around, but an explanation.

Here are six examples of doing a trivial operation on an association and a list.

Initially, I was curious about the cost of calling a function for which the matched pattern is a large association:

rAssoc = AssociationMap[RandomReal[{0, #}] &, Range[10^7]];
fA[r_] := Total[r]
gA[] := Total[rAssoc]

AbsoluteTiming[gA[];]  (*slightly longer 3.42, expense of passing association not large*)


What about doing the same thing for a list:

rList = RandomReal[{0, #}] & /@ Range[10^7];
fL[r_] := Total[r]
gL[] := Total[rList]



The list is much much faster. Why?

There is some discussion in this April 2018 StackExchange:

Let's and see if the same holds for an unpacked array:

Needs["Developer"]
PackedArrayQ[rList] (*True*)

AbsoluteTiming[rListUnpacked = FromPackedArray[rList];] (*0.13 seconds*)
fLU[r_] := Total[r]
gLU[] := Total[rListUnpacked]

AbsoluteTiming[fL[rListUnpacked];] (*0.57 seconds*)
AbsoluteTiming[gLU[];] (*0.58 seconds*)


It appears that the culprit may be Values:

AbsoluteTiming[Values[rAssoc];] (*3.37 seconds*)


I am curious why extracting the values for the Association is slower.

Lists in Wolfram Language are simple linear arrays in memory. Such arrays, especially packed numeric arrays, are amenable to numerous optimizations all the way from the C compiler through to the hardware: on-chip CPU caching, speculative evaluation, pipelining, etc.

Associations in Wolfram Language are implemented using hash array mapped tries. This is a complex data structure that incurs significant costs to traverse, and its non-linear layout defeats most of the optimization measures listed for arrays.

Consider, for example, the expression graph representing the internal structure of an association containing only 1000 keys rather than the 10^7 in the question:

AssociationMap[RandomReal[{0, #}] &, Range[10^3]] //
InternalAssociationNodes //
ExpressionGraph


Operating upon this structure involves a lot of pointer manipulation and bit twiddling. No wonder this structure is considerably more expensive to use than a simple linear array.

• This is a very clear (and visual) explanation. Accepting this as answered. May 27, 2021 at 7:25