From 3f9be25aada4be24591dfc71b43b7275c1c18cd1 Mon Sep 17 00:00:00 2001 From: Scorbajio Date: Mon, 10 Jun 2024 05:59:47 -0700 Subject: [PATCH] verkle: Add tests for verkle bytes helper (#3441) * Add tests for verkle bytes helper * Optimize matchingBytesLength --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --- packages/verkle/src/util/bytes.ts | 22 +++++++++--- packages/verkle/test/util/bytes.spec.ts | 47 +++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 packages/verkle/test/util/bytes.spec.ts diff --git a/packages/verkle/src/util/bytes.ts b/packages/verkle/src/util/bytes.ts index 9a5b83da93..a3d1bc5938 100644 --- a/packages/verkle/src/util/bytes.ts +++ b/packages/verkle/src/util/bytes.ts @@ -8,15 +8,29 @@ */ export function matchingBytesLength(bytes1: Uint8Array, bytes2: Uint8Array): number { let count = 0 - - // The minimum length of both arrays const minLength = Math.min(bytes1.length, bytes2.length) - for (let i = 0; i < minLength; i++) { + // Unroll the loop for better performance + for (let i = 0; i < minLength - 3; i += 4) { + // Compare 4 bytes at a time + if ( + bytes1[i] === bytes2[i] && + bytes1[i + 1] === bytes2[i + 1] && + bytes1[i + 2] === bytes2[i + 2] && + bytes1[i + 3] === bytes2[i + 3] + ) { + count += 4 + } else { + // Break early if a mismatch is found + break + } + } + + // Handle any remaining elements + for (let i = minLength - (minLength % 4); i < minLength; i++) { if (bytes1[i] === bytes2[i]) { count++ } else { - // Stop counting as soon as a mismatch is found break } } diff --git a/packages/verkle/test/util/bytes.spec.ts b/packages/verkle/test/util/bytes.spec.ts new file mode 100644 index 0000000000..850a2bdb14 --- /dev/null +++ b/packages/verkle/test/util/bytes.spec.ts @@ -0,0 +1,47 @@ +import { assert, describe, it } from 'vitest' + +import { matchingBytesLength } from '../../src/util/bytes.js' + +describe('matchingBytesLength', () => { + it('should return 0 when both arrays are empty', () => { + const bytes1 = new Uint8Array([]) + const bytes2 = new Uint8Array([]) + assert.equal(matchingBytesLength(bytes1, bytes2), 0) + }) + + it('should return 0 when one of the arrays is empty', () => { + const bytes1 = new Uint8Array([1, 2, 3]) + const bytes2 = new Uint8Array([]) + assert.equal(matchingBytesLength(bytes1, bytes2), 0) + }) + + it('should return 0 when arrays have no matching elements', () => { + const bytes1 = new Uint8Array([1, 2, 3]) + const bytes2 = new Uint8Array([4, 5, 6]) + assert.equal(matchingBytesLength(bytes1, bytes2), 0) + }) + + it('should handle arrays with same elements but different lengths', () => { + const bytes1 = new Uint8Array([1, 2, 3]) + const bytes2 = new Uint8Array([1, 2, 3, 4]) + assert.equal(matchingBytesLength(bytes1, bytes2), 3) + }) + + it('should handle arrays with matching elements at end', () => { + const bytes1 = new Uint8Array([1, 2, 3]) + const bytes2 = new Uint8Array([0, 1, 2, 3]) + assert.equal(matchingBytesLength(bytes1, bytes2), 0) + }) + + it('should handle arrays with matching elements at start', () => { + const bytes1 = new Uint8Array([1, 2, 3]) + const bytes2 = new Uint8Array([1, 2, 3, 4, 5]) + assert.equal(matchingBytesLength(bytes1, bytes2), 3) + }) + + it('should handle arrays with large number of elements', () => { + const bytes1 = new Uint8Array(Array.from({ length: 1000000 }, (_, i) => i)) + const bytes2 = new Uint8Array(Array.from({ length: 1000000 }, (_, i) => i)) + assert.equal(matchingBytesLength(bytes1, bytes2), 1000000) + }) +})