Skip to content

Commit 568064c

Browse files
committed
Improve perf app page
1 parent 9e9d22a commit 568064c

File tree

3 files changed

+3491
-204
lines changed

3 files changed

+3491
-204
lines changed

packages/idb-cache-app/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414
"react-dom": "^18.3.1"
1515
},
1616
"devDependencies": {
17+
"@instructure/ui": "^9.9.0",
18+
"@instructure/ui-buttons": "^9.9.0",
19+
"@instructure/ui-flex": "^9.9.0",
20+
"@instructure/ui-heading": "^9.9.0",
21+
"@instructure/ui-metric": "^9.9.0",
22+
"@instructure/ui-number-input": "^9.9.0",
23+
"@instructure/ui-text-input": "^9.9.0",
24+
"@instructure/ui-view": "^9.9.0",
1725
"@rsbuild/core": "^1.0.19",
1826
"@rsbuild/plugin-react": "^1.0.6",
1927
"@types/random-seed": "^0.3.5",

packages/idb-cache-app/src/App.tsx

Lines changed: 112 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ import "./App.css";
22
import { IDBCache } from "@instructure/idb-cache";
33
import { useCallback, useEffect, useState } from "react";
44
import { uuid, deterministicHash, generateTextOfSize } from "./utils";
5+
import { Button } from "@instructure/ui-buttons";
6+
import { MetricGroup, Metric } from "@instructure/ui-metric";
7+
import { View } from "@instructure/ui-view";
8+
import { Flex } from "@instructure/ui-flex";
9+
import { Heading } from "@instructure/ui-heading";
10+
import { NumberInput } from "@instructure/ui-number-input";
511

612
// For demonstration/testing purposes.
713
// Do *not* store cacheKey to localStorage in production.
@@ -25,11 +31,6 @@ const cache = new IDBCache({
2531

2632
const DEFAULT_NUM_ITEMS = 1;
2733

28-
const initialNumItems =
29-
Number.parseInt(
30-
localStorage.getItem("numItems") || String(DEFAULT_NUM_ITEMS),
31-
) || DEFAULT_NUM_ITEMS;
32-
3334
const DEFAULT_ITEM_SIZE = 10240;
3435

3536
const initialItemSize =
@@ -42,22 +43,21 @@ const App = () => {
4243
const [hash2, setHash2] = useState<string | null>(null);
4344
const [setTime, setSetTime] = useState<number | null>(null);
4445
const [getTime, setGetTime] = useState<number | null>(null);
45-
const [numItems, setNumItems] = useState<number>(initialNumItems);
4646
const [itemSize, setItemSize] = useState<number>(initialItemSize);
4747
const [isEncrypting, setIsEncrypting] = useState<boolean>(false);
4848
const [isDecrypting, setIsDecrypting] = useState<boolean>(false);
4949

5050
const encryptAndStore = useCallback(async () => {
5151
console.time("generating content");
5252
setIsEncrypting(true);
53-
const paragraphs = Array.from({ length: numItems }, (_, index) =>
53+
const paragraphs = Array.from({ length: DEFAULT_NUM_ITEMS }, (_, index) =>
5454
generateTextOfSize(itemSize, `${cacheBuster}-${index}`),
5555
);
5656
console.timeEnd("generating content");
5757

5858
const start = performance.now();
5959

60-
for (let i = 0; i < numItems; i++) {
60+
for (let i = 0; i < DEFAULT_NUM_ITEMS; i++) {
6161
await cache.setItem(`item-${i}`, paragraphs[i]);
6262
}
6363

@@ -66,14 +66,14 @@ const App = () => {
6666

6767
setHash1(deterministicHash(paragraphs.join("")));
6868
setIsEncrypting(false);
69-
}, [numItems, itemSize]);
69+
}, [itemSize]);
7070

7171
const retrieveAndDecrypt = useCallback(async () => {
7272
setIsDecrypting(true);
7373
const results: Array<string | null> = [];
7474
const start = performance.now();
7575

76-
for (let i = 0; i < numItems; i++) {
76+
for (let i = 0; i < DEFAULT_NUM_ITEMS; i++) {
7777
const result = await cache.getItem(`item-${i}`);
7878
results.push(result);
7979
}
@@ -82,7 +82,7 @@ const App = () => {
8282
setGetTime(end - start);
8383
setHash2(results.length > 0 ? deterministicHash(results.join("")) : null);
8484
setIsDecrypting(false);
85-
}, [numItems]);
85+
}, []);
8686

8787
// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
8888
useEffect(() => {
@@ -135,9 +135,9 @@ const App = () => {
135135

136136
<div className="min-h-screen bg-gray-50 p-8">
137137
<div className="max-w-4xl mx-auto p-6 bg-white shadow-md rounded-lg">
138-
<h1 className="text-4xl font-bold text-center text-primary mb-6">
138+
<Heading level="h1" margin="0 0 small 0">
139139
@instructure/idb-cache
140-
</h1>
140+
</Heading>
141141

142142
<form>
143143
<fieldset className="border border-gray-300 rounded-lg p-4 mb-6">
@@ -149,32 +149,27 @@ const App = () => {
149149
<span>
150150
Cache key: <code className="text-sm">{cacheKey}</code>
151151
</span>
152-
<button
153-
type="button"
154-
className="btn btn-sm"
152+
<Button
155153
onClick={() => {
156154
localStorage.removeItem("cacheKey");
157155
window.location.reload();
158156
}}
159157
>
160158
Reset
161-
</button>
159+
</Button>
162160
</div>
163161
<div className="flex items-center justify-between">
164162
<span>
165-
Cache buster (salt):{" "}
166-
<code className="text-sm">{cacheBuster}</code>
163+
Cache buster: <code className="text-sm">{cacheBuster}</code>
167164
</span>
168-
<button
169-
type="button"
170-
className="btn btn-sm"
165+
<Button
171166
onClick={() => {
172167
localStorage.removeItem("cacheBuster");
173168
window.location.reload();
174169
}}
175170
>
176171
Reset
177-
</button>
172+
</Button>
178173
</div>
179174
</div>
180175
</fieldset>
@@ -184,139 +179,109 @@ const App = () => {
184179
Performance Test
185180
</legend>
186181
<div className="flex flex-col gap-4">
187-
<div className="form-control">
188-
<label className="label">
189-
<span className="label-text font-medium">
190-
Size of each item (kb):
191-
</span>
192-
<input
193-
// biome-ignore lint/a11y/noAutofocus: <explanation>
194-
autoFocus={true}
195-
className="input input-bordered w-full max-w-xs"
196-
type="number"
197-
value={Math.round(itemSize / 1024)}
182+
<Flex gap="medium">
183+
<Flex.Item shouldGrow>
184+
<NumberInput
185+
renderLabel="Size of data (kb):"
198186
onChange={(e) => {
199-
setItemSize(Number(e.target.value) * 1024);
200-
localStorage.setItem(
201-
"itemSize",
202-
String(Number.parseInt(e.target.value) * 1024),
187+
const newValue = Math.max(
188+
Number.parseInt(e.target.value) * 1024,
189+
1024,
203190
);
191+
setItemSize(newValue);
192+
localStorage.setItem("itemSize", String(newValue));
204193
}}
205-
/>
206-
</label>
207-
</div>
208-
209-
<div className="form-control">
210-
<label className="label">
211-
<span className="label-text font-medium">
212-
Number of items:
213-
</span>
214-
<input
215-
className="input input-bordered w-full max-w-xs"
216-
type="number"
217-
value={numItems}
218-
onChange={(e) => {
219-
setNumItems(Number(e.target.value));
220-
localStorage.setItem("numItems", e.target.value);
194+
onIncrement={() => {
195+
const newValue = Math.max(
196+
Math.round(itemSize) + 1 * 1024,
197+
1024,
198+
);
199+
setItemSize(newValue);
200+
localStorage.setItem("itemSize", String(newValue));
221201
}}
222-
/>
223-
</label>
224-
</div>
225-
226-
<div className="flex flex-col gap-4">
227-
<button
228-
className="btn btn-primary"
229-
type="button"
230-
onClick={encryptAndStore}
231-
>
232-
Encrypt and store
233-
<span
234-
className="loading loading-spinner"
235-
style={{
236-
visibility: !isEncrypting ? "hidden" : "visible",
202+
onDecrement={() => {
203+
const newValue = Math.max(
204+
Math.round(itemSize) - 1 * 1024,
205+
1024,
206+
);
207+
setItemSize(newValue);
208+
localStorage.setItem("itemSize", String(newValue));
237209
}}
210+
isRequired
211+
value={Math.round(itemSize / 1024)}
238212
/>
239-
</button>
240-
<div className="stats shadow">
241-
<div
242-
className="stat place-items-center"
243-
style={{
244-
visibility: hash1 ? "visible" : "hidden",
245-
}}
246-
>
247-
<>
248-
<div className="stat-title">Took</div>
249-
<div className="stat-value">
250-
{setTime !== null
251-
? `${Math.round(setTime)} ms`
252-
: "N/A"}
253-
</div>
254-
<div className="stat-desc">to encrypt and store</div>
255-
</>
256-
</div>
257-
258-
<div
259-
className="stat place-items-center"
260-
style={{
261-
visibility: hash1 ? "visible" : "hidden",
262-
}}
263-
>
264-
<>
265-
<div className="stat-title">Hash</div>
266-
<div className="stat-value">{hash1}</div>
267-
<div className="stat-desc">of data</div>
268-
</>
269-
</div>
270-
</div>
271-
</div>
272-
273-
<div className="flex flex-col gap-4">
274-
<button
275-
className="btn btn-secondary"
276-
type="button"
277-
onClick={retrieveAndDecrypt}
278-
>
279-
Retrieve and decrypt
280-
<span
281-
className="loading loading-spinner"
282-
style={{
283-
visibility: !isDecrypting ? "hidden" : "visible",
284-
}}
213+
</Flex.Item>
214+
<Flex.Item shouldGrow>
215+
<NumberInput
216+
renderLabel="Number of chunks:"
217+
interaction="disabled"
218+
value={Math.ceil(itemSize / 25000)}
285219
/>
286-
</button>
220+
</Flex.Item>
221+
</Flex>
287222

288-
<div className="stats shadow">
289-
<div
290-
className="stat place-items-center"
291-
style={{
292-
visibility: hash2 ? "visible" : "hidden",
293-
}}
294-
>
295-
<>
296-
<div className="stat-title">Took</div>
297-
<div className="stat-value">
298-
{getTime !== null
299-
? `${Math.round(getTime)} ms`
300-
: "error"}
301-
</div>
302-
<div className="stat-desc">to retrieve and decrypt</div>
303-
</>
304-
</div>
223+
<View
224+
as="span"
225+
display="inline-block"
226+
margin="none"
227+
padding="medium"
228+
background="primary"
229+
shadow="resting"
230+
>
231+
<Flex direction="column">
232+
<Button color="primary" onClick={encryptAndStore}>
233+
Encrypt and store
234+
</Button>
235+
<View padding="medium 0 0 0">
236+
<MetricGroup>
237+
<Metric
238+
renderLabel="to encrypt and store"
239+
renderValue={
240+
setTime !== null
241+
? `${Math.round(setTime)} ms`
242+
: "N/A"
243+
}
244+
/>
245+
<Metric
246+
renderLabel="hash of data"
247+
renderValue={hash1}
248+
/>
249+
</MetricGroup>
250+
</View>
251+
</Flex>
252+
</View>
305253

306-
<div
307-
className="stat place-items-center"
308-
style={{
309-
visibility: hash2 ? "visible" : "hidden",
310-
}}
311-
>
312-
<>
313-
<div className="stat-title">Hash</div>
314-
<div className="stat-value">{hash2}</div>
315-
<div className="stat-desc">of data</div>
316-
</>
317-
</div>
318-
</div>
319-
</div>
254+
<View
255+
as="span"
256+
display="inline-block"
257+
margin="none"
258+
padding="medium"
259+
background="primary"
260+
shadow="resting"
261+
>
262+
<Flex direction="column">
263+
<Button color="primary" onClick={retrieveAndDecrypt}>
264+
Retrieve and decrypt
265+
</Button>
266+
267+
<View padding="medium 0 0 0">
268+
<MetricGroup>
269+
<Metric
270+
renderLabel="to retrieve and decrypt"
271+
renderValue={
272+
getTime !== null
273+
? `${Math.round(getTime)} ms`
274+
: "error"
275+
}
276+
/>
277+
<Metric
278+
renderLabel="hash of data"
279+
renderValue={hash2}
280+
/>
281+
</MetricGroup>
282+
</View>
283+
</Flex>
284+
</View>
320285
</div>
321286
</fieldset>
322287
</form>

0 commit comments

Comments
 (0)