Skip to content

Instantly share code, notes, and snippets.

@scarf005
Last active May 23, 2023 13:53
Show Gist options
  • Save scarf005/25ea81b8b67c7008f2d74c871eff7c20 to your computer and use it in GitHub Desktop.
Save scarf005/25ea81b8b67c7008f2d74c871eff7c20 to your computer and use it in GitHub Desktop.
import {
bgBrightRed,
bold,
brightGreen,
brightRed,
brightWhite,
brightYellow,
} from "https://deno.land/std@0.186.0/fmt/colors.ts"
import { c, p } from "https://deno.land/x/copb@v1.0.1/mod.ts"
import { match } from "npm:ts-pattern"
const redBoldBg = c(p(bgBrightRed)(brightWhite)(bold))
const color = (ms: number) =>
match(ms)
.when((x) => x < 100, () => brightGreen)
.when((x) => x < 500, () => brightYellow)
.when((x) => x < 1000, () => brightRed)
.otherwise(() => redBoldBg)
const timeitInner = ({ start, end }: { start: number; end: number }) => {
const ms = Math.round(end - start)
const colorFn = color(ms)
return { ms, color: colorFn, msColored: colorFn(`(${ms}ms)`) }
}
/** wait for a promise and returns its value, time it took, and color. */
export const timeitVerbose = async <T>(val: Promise<T>) => {
const start = performance.now()
const result = await val
const end = performance.now()
return { result, ...timeitInner({ start, end }) }
}
export const timeitSyncVerbose = <T>(fn: () => T) => {
const start = performance.now()
const result = fn()
const end = performance.now()
return { result, ...timeitInner({ start, end }) }
}
type TimeitOption<T> = {
name: string | ((val: T) => string)
val: Promise<T>
}
/** wait for a promise and log how long it took. */
export const timeit = (quiet: boolean) => async <T>({ name, val }: TimeitOption<T>) => {
const { result, msColored } = await timeitVerbose(val)
const display = typeof name === "string" ? name : name(result)
if (!quiet) console.log(`${display} ${msColored}`)
return result
}
type TimeitSyncOption<T> = {
name: string | ((val: T) => string)
fn: () => T
}
export const timeitSync = (quiet: boolean) => <T>({ name, fn }: TimeitSyncOption<T>) => {
const { result, msColored } = timeitSyncVerbose(fn)
const display = typeof name === "string" ? name : name(result)
if (!quiet) console.log(`${display} ${msColored}`)
return result
}
import { timeitSyncVerbose } from "../timeit.ts"
type Pair<T, U> = {
f: (value: T) => U
log: (value: U) => string
}
type WithTime<T> = {
context: WithTimeCons<T>
map<U>({ f, log }: Pair<T, U>): WithTime<U>
get(): T
}
type WithTimeCons<T> = Readonly<{
value: T
quiet: boolean
total: number
}>
class Timed<T> implements WithTime<T> {
constructor(public context: WithTimeCons<T>) {}
map<U>({ f, log }: Pair<T, U>): WithTime<U> {
const { result, ms, msColored } = timeitSyncVerbose(() => f(this.context.value))
this.log(`${log(result)} ${msColored}`)
return new Timed({ value: result, quiet: this.context.quiet, total: this.context.total + ms })
}
get(): T {
this.log(`total: ${this.context.total}ms`)
return this.context.value
}
private log(line: string) {
if (!this.context.quiet) {
console.log(line)
}
}
}
const withTimer = <T>({ value, quiet = false }: { value: T; quiet?: boolean }): WithTime<T> =>
new Timed({ value, quiet, total: 0 })
if (import.meta.main) {
const result = withTimer({ value: 1 })
.map({
f: (x) => x + 1,
log: (v) => `getting result ${v}`,
})
.map({
f: (x) => x * 2,
log: (v) => `multiplication result ${v}`,
})
.get()
console.log(`result: ${result}`)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment