File size: 2,826 Bytes
bd8c5ee
 
 
 
 
b01a4ff
 
bd8c5ee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Run in a fresh `bun run browser` page's DevTools console. Uses the actual UI and worker.
window.crivoBenchmark = {
  runs: [],
  status: 'starting',
  userAgent: navigator.userAgent,
  threads: navigator.hardwareConcurrency,
  crossOriginIsolated: window.crossOriginIsolated
}
;(async () => {
  const report = window.crivoBenchmark
  const adapter = await navigator.gpu?.requestAdapter()
  report.gpu = adapter
    ? {
        ...Object.fromEntries(
          ['vendor', 'architecture', 'device', 'description'].map((k) => [k, adapter.info[k]])
        )
      }
    : null
  const NativeWorker = window.Worker
  let pending
  let metrics
  window.Worker = class extends NativeWorker {
    constructor(...args) {
      super(...args)
      this.addEventListener('message', ({ data }) => {
        if (data.kind === 'metrics') metrics = data.metrics
        if (data.kind === 'error') pending?.reject(Error(data.message))
        if (data.kind === 'result') {
          if (!data.result.ok) pending?.reject(Error(JSON.stringify(data.result.error)))
          else pending?.resolve({ ...metrics, totalMs: data.totalMs })
        }
      })
      this.addEventListener('error', () => pending?.reject(Error('Worker stopped')))
    }
    postMessage(data, ...args) {
      report.input = data.input
      super.postMessage(data, ...args)
    }
  }
  const run = () =>
    new Promise((resolve, reject) => {
      const timeout = setTimeout(() => reject(Error('Run timed out')), 240000)
      pending = {
        resolve: (data) => {
          clearTimeout(timeout)
          resolve(data)
        },
        reject: (error) => {
          clearTimeout(timeout)
          reject(error)
        }
      }
      document.getElementById('run').click()
    })
  for (const size of ['17m', '32m', '68m', '150m', '400m', '1b']) {
    for (const [device, dtype] of [
      ['cpu', 'q8'],
      ...(size === '1b' ? [] : [['cpu', 'fp32']]),
      ['gpu', 'fp32']
    ]) {
      const entry = { size, device, dtype, samples: [] }
      report.runs.push(entry)
      report.status = `${size} ${device} ${dtype}`
      for (const [id, value] of [
        ['size', size],
        ['device', device],
        ['dtype', dtype]
      ]) {
        const select = document.getElementById(id)
        select.value = value
        select.dispatchEvent(new Event('change'))
      }
      await new Promise((resolve) => setTimeout(resolve, 50))
      entry.first = await run()
      for (let i = 0; i < 23; i++) {
        await new Promise((resolve) => setTimeout(resolve, 50))
        const result = await run()
        if (result.loadMs !== 0) throw Error('Session was not reused')
        if (i >= 3) entry.samples.push(result)
      }
    }
  }
  report.status = 'complete'
})().catch((error) => {
  window.crivoBenchmark.error = String(error)
})