I'm on Windows 10 Mathematica 12.1.1.

I would expect allocating a big ConstantArray and comparing would be slower but apparently it is not:

RepeatedTiming[RandomReal[1, 10000] == ConstantArray[0, 10000]]
(* {0.0000589, False} *)
RepeatedTiming[ContainsOnly[RandomReal[1, 10000], {0}]]
(* {0.00309, False} *)

This becomes even worse if I add SameTest->Equal which the documentation states allows some numerical tolerance:

RepeatedTiming[ContainsOnly[RandomReal[1, 10000], {0}, SameTest -> Equal]]
(* {7.92, False} *)

Why is the above more than ~100,000 times slower than the code that allocates a ConstantArray with a large ByteCount?! What is going on behind the scenes in ContainsOnly that's more expensive than allocation?

Admittedly, in this much bigger case involving sparse arrays ContainsOnly is faster, so I'd guess the allocation overhead eventually catches up:

RepeatedTiming[SparseArray[999999 -> 1] == ConstantArray[0, 1000000]]
(* {0.00212, False} *)
RepeatedTiming[ContainsOnly[SparseArray[999999 -> 1, 1000000], {0}]]
(* {0.0000169, False} *)
  • $\begingroup$ Look at the timing of Complement[RandomReal[1, 10000], {0}] $\endgroup$
    – Jason B.
    Aug 7, 2020 at 14:18
  • $\begingroup$ @JasonB. Thanks. Complement would have to construct a list though so I'd expect it to be a little slow. ContainsOnly simply has to return True or False. $\endgroup$
    – flinty
    Aug 7, 2020 at 14:30
  • 1
    $\begingroup$ I agree that ContainsOnly should be able to short circuit and return False at the first mismatch, and not continue with the remaining comparisons that Complement does. But it doesn't appear to be implemented that way. $\endgroup$
    – Jason B.
    Aug 7, 2020 at 16:27
  • 1
    $\begingroup$ What @JasonB said. That function is on my to-improve list, though not at the top. $\endgroup$ Aug 9, 2020 at 14:42


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.