row-key.ts 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. import { createHarness, type Workload } from "./harness"
  2. type Row =
  3. | { readonly type: "message"; readonly messageID: string }
  4. | { readonly type: "part"; readonly messageID: string; readonly partID: string }
  5. | {
  6. readonly type: "group"
  7. readonly kind: "reasoning" | "exploration"
  8. readonly messageID: string
  9. readonly partID: string
  10. }
  11. const size = 10_000
  12. const iterations = 1_000_000
  13. const rows = Array.from({ length: size }, (_, index): Row => {
  14. if (index % 3 === 0) return { type: "message", messageID: `message-${index}` }
  15. if (index % 3 === 1) return { type: "part", messageID: `message-${index >> 2}`, partID: `text:${index}` }
  16. return {
  17. type: "group",
  18. kind: index % 2 === 0 ? "reasoning" : "exploration",
  19. messageID: `message-${index >> 2}`,
  20. partID: `call-${index}`,
  21. }
  22. })
  23. const precomputed = rows.map((row) => ({ row, id: concatenate(row) }))
  24. const bench = createHarness()
  25. function workload(read: (index: number) => string): Workload {
  26. let sink = 0
  27. return {
  28. run(index) {
  29. sink += read(index % size).length
  30. },
  31. consume: () => sink,
  32. }
  33. }
  34. function json(row: Row) {
  35. if (row.type === "message") return JSON.stringify([row.type, row.messageID])
  36. if (row.type === "part") return JSON.stringify([row.type, row.messageID, row.partID])
  37. return JSON.stringify([row.type, row.kind, row.messageID, row.partID])
  38. }
  39. function concatenate(row: Row) {
  40. if (row.type === "message") return `m${row.messageID.length}:${row.messageID}`
  41. if (row.type === "part") return `p${row.messageID.length}:${row.messageID}${row.partID.length}:${row.partID}`
  42. return `g${row.kind === "reasoning" ? "r" : "e"}${row.messageID.length}:${row.messageID}${row.partID.length}:${row.partID}`
  43. }
  44. console.log(`Session row key benchmark (${size.toLocaleString()} rows, ${bench.samples} samples)\n`)
  45. const result = bench.compare(iterations, [
  46. { name: "JSON tuple key", make: () => workload((index) => json(rows[index])) },
  47. { name: "Concatenated key", make: () => workload((index) => concatenate(rows[index])) },
  48. { name: "Precomputed key", make: () => workload((index) => precomputed[index].id) },
  49. ])
  50. console.log("\nRatios to JSON tuple (lower is faster)")
  51. console.log(`Concatenated: ${result.ratio(1, 0).toFixed(3)}x`)
  52. console.log(`Precomputed: ${result.ratio(2, 0).toFixed(3)}x`)
  53. console.log(`METRIC concatenated_key_ratio=${result.ratio(1, 0).toFixed(6)}`)
  54. console.log(`METRIC precomputed_key_ratio=${result.ratio(2, 0).toFixed(6)}`)
  55. bench.finish()