Skip to content

Improve performance of Utils.ArrayEquals - #1331

Merged
NicolasDorier merged 6 commits into
MetacoSA:masterfrom
Carti-it:bench-array-equals
Sep 7, 2026
Merged

NicolasDorier merged 6 commits into
MetacoSA:masterfrom
Carti-it:bench-array-equals

Conversation

@Carti-it

@Carti-it Carti-it commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor
Method a b Mean Error StdDev Ratio RatioSD Allocated Alloc Ratio
ArrayEqual_Master Byte[0] Byte[0] 0.8767 ns 0.0168 ns 0.0157 ns 1.00 0.02 - NA
ArrayEqual_PR Byte[0] Byte[0] 0.4866 ns 0.0270 ns 0.0252 ns 0.56 0.03 - NA
ArrayEqual_Master Byte[0] Byte[1] 1.5359 ns 0.0430 ns 0.0402 ns 1.75 0.05 - NA
ArrayEqual_PR Byte[0] Byte[1] 0.4870 ns 0.0127 ns 0.0112 ns 0.56 0.02 - NA
ArrayEqual_Master Byte[1] Byte[1] 1.4931 ns 0.0406 ns 0.0380 ns 1.70 0.05 - NA
ArrayEqual_PR Byte[1] Byte[1] 1.0676 ns 0.0187 ns 0.0166 ns 1.22 0.03 - NA
ArrayEqual_Master Byte[2] Byte[2] 2.0147 ns 0.0723 ns 0.1082 ns 2.30 0.13 - NA
ArrayEqual_PR Byte[2] Byte[2] 1.7478 ns 0.0227 ns 0.0213 ns 1.99 0.04 - NA
ArrayEqual_Master Byte[3] Byte[3] 1.3874 ns 0.0204 ns 0.0181 ns 1.58 0.03 - NA
ArrayEqual_PR Byte[3] Byte[3] 1.0474 ns 0.0202 ns 0.0179 ns 1.20 0.03 - NA
ArrayEqual_Master Byte[5] Byte[5] 3.9556 ns 0.0566 ns 0.0501 ns 4.51 0.10 - NA
ArrayEqual_PR Byte[5] Byte[5] 3.2429 ns 0.0727 ns 0.0680 ns 3.70 0.10 - NA
ArrayEqual_Master Byte[6] Byte[6] 3.9994 ns 0.0537 ns 0.0449 ns 4.56 0.09 - NA
ArrayEqual_PR Byte[6] Byte[6] 3.7730 ns 0.0481 ns 0.0450 ns 4.30 0.09 - NA
ArrayEqual_Master Byte[32] Byte[32] 21.1504 ns 0.3606 ns 0.4008 ns 24.13 0.61 - NA
ArrayEqual_PR Byte[32] Byte[32] 18.9925 ns 0.2618 ns 0.2449 ns 21.67 0.46 - NA
ArrayEqual_Master Byte[32] Byte[32] 1.4625 ns 0.0593 ns 0.0812 ns 1.67 0.10 - NA
ArrayEqual_PR Byte[32] Byte[32] 1.2298 ns 0.0190 ns 0.0178 ns 1.40 0.03 - NA

Comment thread NBitcoin/Utils.cs
return false;
return ArrayEqual(a, 0, b, 0, Math.Max(a.Length, b.Length));

return ArrayEqual(a, 0, b, 0, a.Length);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally, I was interested in

+#if HAS_SPAN
+			return a.AsSpan().SequenceEqual(b);
+#else
			return ArrayEqual(a, 0, b, 0, a.Length);
+#endif

but it behaves like this

Method a b Mean Error StdDev Ratio RatioSD Allocated Alloc Ratio
ArrayEqual_Master Byte[32] Byte[32] 22.2745 ns 0.4059 ns 0.4832 ns 24.86 0.64 - NA
ArrayEqual_PR Byte[32] Byte[32] 3.6044 ns 0.0907 ns 0.0848 ns 4.02 0.11 - NA
ArrayEqual_Master Byte[32] Byte[32] 1.3504 ns 0.0594 ns 0.0851 ns 1.51 0.10 - NA
ArrayEqual_PR Byte[32] Byte[32] 2.9751 ns 0.0841 ns 0.0826 ns 3.32 0.10 - NA

So for byte arrays that are equal it goes from 22 ns -> ~4 ns but it's worse for non-equal byte arrays. I guess non-equality is in general more common. One would have to go into "amortized time complexity"... well, I guess I cannot win with it.

@Carti-it
Carti-it force-pushed the bench-array-equals branch 2 times, most recently from ee468f2 to 9bc1860 Compare September 6, 2026 20:30
Comment thread NBitcoin/Utils.cs Outdated
return ArrayEqual(a, 0, b, 0, Math.Max(a.Length, b.Length));

if (a.Length != b.Length)
return a.Length == 0 && b.Length == 0;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not

if (a.Length != b.Length)
				return false;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be like that. I fixed it.

@NicolasDorier
NicolasDorier merged commit f3ad635 into MetacoSA:master Sep 7, 2026
5 of 6 checks passed
@Carti-it
Carti-it deleted the bench-array-equals branch September 7, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants