More random numbers for today. I added the column opening
to my script where the existential is opened once outside the inner loop.
class underlier <- calls/sec for argument type ->
let storage existential generic opaque opening
existential 180,092,272.35 487,780,665.79 489,594,135.56 5,316,311,553.
opaque 225,860,863.85 5,338,981,670. 5,322,045,425. 5,325,086,015.
concrete 227,004,424.47 5,824,208,845. 5,810,492,484. 5,324,748,000.
class underlier <- calls/sec for argument type ->
var storage existential generic opaque opening
existential 184,689,333.57 486,358,144.22 488,900,752.41 5,330,500,095.
opaque 221,990,732.53 5,698,008,422. 5,707,700,891. 5,205,465,715.
concrete 222,325,502.50 5,707,700,891. 5,546,553,821. 5,199,980,163.
class underlier <- calls/sec for inout argument type ->
var storage existential generic opaque opening
existential 486,643,113.64 485,837,035.14 482,159,328.65 457,771,011.02
opaque 5,617,873,024. 5,733,840,054. 460,277,748.81
concrete 5,797,241,188. 5,813,714,048. 459,033,516.64
struct underlier <- calls/sec for inout argument type ->
var storage existential generic opaque opening
existential 281,167,625.83 5,685,264,656. 5,810,492,484. 5,806,872,490.
opaque 60,963,720,930 64,133,088,685 5,817,342,579.
concrete 60,611,329,479 5,817,342,579. 5,299,518,605.
The thing that struck me about the first set of numbers was the cost of using existential storage. This was disappointing for someone who only a week ago was suggesting a strategy of not eliding storage to some
at all.
There is a solution to this however. If you want to perform intensive processing on something in an existential: first, open it by calling a function with a some
argument to get the generic form and perform your processing in that function. That this works is demonstrated in the forth column of the first and fourth row of results showing performance as if the value had never been in an existential (For some reason this optimisation doesn't work if you compile for iOS ).
But my point is NONE OF THIS MATTERS; Modern CPUs are so incredibly fast. It is seldom that optimisation is worth pursuing. This "analysis" has thrown up a couple of other options I'd not have thought of before. Using let
rather than var
makes a difference. "Opening outside the loop" and passing around by reference using inout
can make a difference too.
As it does not really affect real life performance and there are other optimisations one can apply, the belief that use of existentials is something to worry about seems unfounded to me.