From c1ab40636d7c560d82e0741e0299d8ce6c91478b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 6 Mar 2026 00:38:20 +0000 Subject: [PATCH] perf(Navbar): optimize products lookup by collection id Replaced the O(N*M) nested loop (where N is the number of collections and M is the number of products) with an O(N+M) dictionary lookup in the `Navbar` component's `fetchCollectionsAndProducts` function. Co-authored-by: AJFrio <20246916+AJFrio@users.noreply.github.com> --- benchmarks/navbar-collections.js | 60 ++++++++++++++++++++++++++++ src/components/storefront/Navbar.jsx | 10 ++++- 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 benchmarks/navbar-collections.js diff --git a/benchmarks/navbar-collections.js b/benchmarks/navbar-collections.js new file mode 100644 index 0000000..edd25d6 --- /dev/null +++ b/benchmarks/navbar-collections.js @@ -0,0 +1,60 @@ +import { performance } from 'perf_hooks'; + +// Setup mock data +const NUM_COLLECTIONS = 100; +const NUM_PRODUCTS = 5000; + +const collectionsData = Array.from({ length: NUM_COLLECTIONS }, (_, i) => ({ + id: `collection_${i}`, + name: `Collection ${i}` +})); + +const productsData = Array.from({ length: NUM_PRODUCTS }, (_, i) => ({ + id: `product_${i}`, + collectionId: `collection_${Math.floor(Math.random() * NUM_COLLECTIONS)}`, + name: `Product ${i}` +})); + +function baseline() { + const start = performance.now(); + const collectionsWithProducts = collectionsData.map(collection => ({ + ...collection, + products: productsData.filter(product => product.collectionId === collection.id) + })); + return performance.now() - start; +} + +function optimized() { + const start = performance.now(); + const productsByCollectionId = productsData.reduce((acc, product) => { + if (!acc[product.collectionId]) { + acc[product.collectionId] = []; + } + acc[product.collectionId].push(product); + return acc; + }, {}); + + const collectionsWithProducts = collectionsData.map(collection => ({ + ...collection, + products: productsByCollectionId[collection.id] || [] + })); + return performance.now() - start; +} + +const iterations = 100; +let baselineTotal = 0; +let optimizedTotal = 0; + +// Warmup +for (let i=0; i<10; i++) { + baseline(); + optimized(); +} + +for (let i = 0; i < iterations; i++) { + baselineTotal += baseline(); + optimizedTotal += optimized(); +} + +console.log(`Baseline Avg: ${(baselineTotal / iterations).toFixed(2)} ms`); +console.log(`Optimized Avg: ${(optimizedTotal / iterations).toFixed(2)} ms`); diff --git a/src/components/storefront/Navbar.jsx b/src/components/storefront/Navbar.jsx index 9e08ef4..076d931 100644 --- a/src/components/storefront/Navbar.jsx +++ b/src/components/storefront/Navbar.jsx @@ -41,9 +41,17 @@ export function Navbar({ previewSettings, disableNavigation }) { setCollections(collectionsData) // Group products by collection + const productsByCollectionId = productsData.reduce((acc, product) => { + if (!acc[product.collectionId]) { + acc[product.collectionId] = [] + } + acc[product.collectionId].push(product) + return acc + }, {}) + const collectionsWithProducts = collectionsData.map(collection => ({ ...collection, - products: productsData.filter(product => product.collectionId === collection.id) + products: productsByCollectionId[collection.id] || [] })) setCollectionsWithProducts(collectionsWithProducts)