Skip to content

Instantly share code, notes, and snippets.

@thecodewarrior
Last active January 4, 2024 01:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save thecodewarrior/4fbcffc61eef6151476136179bffcfe8 to your computer and use it in GitHub Desktop.
Save thecodewarrior/4fbcffc61eef6151476136179bffcfe8 to your computer and use it in GitHub Desktop.
Benchmark for different console.log.bind() styles - https://jsbench.me/wxlqydjuo0/1

These are various ways of supporting prefixed logs while preserving line numbers and allowing custom additions to the format string. The importance of the custom format string is that if you wanted to do custom css, using a plain console.log.bind() wouldn't work, since you need %c to apply css, and that must occur in the first parameter.

// plaintext
console.log.bind("%cwarn%c >", "color: yellow", "")("something")
// trying to use a format string in the bound method doesn't work
console.log.bind("%cwarn%c >", "color: yellow", "")("%c%s", "color: red", "RED!")
// appending the format string to the first argument does
console.log.bind("%cwarn%c >" + " %c%s", "color: yellow", "")("color: red", "RED!")

image

Test cases

  • Raw: just console.log(foo), as a baseline for logs in general
  • Static: a plain bound function, as a baseline for bound-function logs
  • On-demand: returns a new bound function every time
  • Object cache: caches the bound functions in an object
  • Map cache: caches the bound functions in a Map

Results

Test Firefox Chrome Safari
Raw 357K ops/s ± 1.64% 235K ops/s ± 1.57% 1.9M ops/s ± 0.52%
Static 247K ops/s ± 4.27%
30.98% slower
157K ops/s ± 1.98%
33.23% slower
1.4M ops/s ± 0.7%
22.27% slower
On-demand 207K ops/s ± 5.58%
42.09% slower
156K ops/s ± 1.31%
33.65% slower
1.2M ops/s ± 0.54%
34.49% slower
Object cache 210K ops/s ± 5.62%
41.39% slower
151K ops/s ± 3.73%
35.85% slower
1.3M ops/s ± 0.58%
28.57% slower
Map cache 204K ops/s ± 6.25%
43% slower
150K ops/s ± 2.16%
36.14% slower
1.3M ops/s ± 0.62%
28.56% slower
const loggerFormat = '%cwarn%c %cdata.wm.LoginState%c';
const formatArgs = [
"font-weight: normal; text-transform: lowercase; padding: 0 3px; border-radius: 5px; color: hsl(54 100% 20%); background-color: hsl(54 100% 50%);",
'',
"font-weight: normal; color: #888;",
''
];
const staticFn = console.log.bind(console, loggerFormat, ...formatArgs);
function onDemandFn(fmt) {
return console.log.bind(console, loggerFormat + " " + fmt, ...formatArgs);
}
const cacheObject = Object.create(null)
function objectCacheFn(fmt) {
return cacheObject[fmt] ??= console.log.bind(console, loggerFormat + " " + fmt, ...formatArgs);
}
const cacheMap = new Map();
function mapCacheFn(fmt) {
let cachedFn = cacheMap.get(fmt);
if(!cachedFn) {
cachedFn = console.log.bind(console, loggerFormat + " " + fmt, ...formatArgs);
cacheMap.set(fmt, cachedFn)
}
return cachedFn
}
let i = 0;
// Raw
console.log(`some message ${i++ % 100}`);
// Static
staticFn(`some message ${i++ % 100}`);
// On-demand
onDemandFn(`extra fmt ${i++ % 100}`)("some message");
// Object cache
objectCache(`extra fmt ${i++ % 100}`)("some message");
// Map cache
mapCache(`extra fmt ${i++ % 100}`)("some message");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment