Skip to content

Instantly share code, notes, and snippets.

@bramus
Last active July 8, 2024 17:26
Show Gist options
  • Save bramus/5669f8408ded2f4a91d4db2de7afcca0 to your computer and use it in GitHub Desktop.
Save bramus/5669f8408ded2f4a91d4db2de7afcca0 to your computer and use it in GitHub Desktop.
Benchmarking long vs short CSS classnames
import PerfTestRunner from '/lib/PerfTestRunner.js';
import { makeTree } from '/lib/DOM.js';
import { setCSS, resetCSS } from '/lib/CSS.js';
const $container = document.querySelector('#container');
makeTree($container, 1000, `<div>
<div class="aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"></div>
<div class="a"></div>
</div>`);
const selectors = {
'1. Long classname': '.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
'2. Short classname': '.a',
}
const runTest = (description, selector) => new Promise((resolve, reject) => {
/* Test logic here */
});

Performance of classnames

These tests use Chrome’s PerfTestRunner to benchmark the performance. The result is a number that indicates the “runs per second”. The higher the number, the better.

Without style parsing

This variation sets and resets the CSS as part as the setup/teardown, which is not part of the measurement. Inside the measured test, a style recalc is forced.

const runTest = (description, selector) => new Promise((resolve, reject) => {
	PerfTestRunner.measureRunsPerSecond({
		description: `Selector Test ${description}`,
		setup: () => {
			setCSS(`${selector} { color: red; }`);
		},
		run: function() {
			getComputedStyle($container); // force recalc style
		},
		iterationCount: 5,
		teardown: resetCSS,
		done: resolve,
	});
});
$ npm run benchmark selectors/classnames

> [email protected] benchmark
> node cli/index.js selectors/classnames

== Starting Benchmark ====== 
LOG Description: Selector Test 1. Long classname
LOG Running 5 times
LOG Ignoring warm-up run (7428502.520006985 runs/s)
LOG 7956294.767339723 runs/s
LOG 7955328.963225498 runs/s
LOG 7895903.614174318 runs/s
LOG 8090864.197233177 runs/s
LOG 8305157.775056413 runs/s
TIM blink_perf: 4162.01806640625 ms
LOG 
LOG Time:
LOG values 7956294.767339723, 7955328.963225498, 7895903.614174318, 8090864.197233177, 8305157.775056413 runs/s
LOG avg 8040709.8634058265 runs/s
LOG median 7956294.767339723 runs/s
LOG stdev 164189.53343161958 runs/s
LOG min 7895903.614174318 runs/s
LOG max 8305157.775056413 runs/s
LOG Description: Selector Test 2. Short classname
LOG Running 5 times
LOG Ignoring warm-up run (8231086.410572874 runs/s)
LOG 8069942.12541325 runs/s
LOG 7881659.651232712 runs/s
LOG 8297796.909858819 runs/s
LOG 8214590.123021921 runs/s
LOG 8573521.716646269 runs/s
TIM blink_perf: 4202.118896484375 ms
LOG 
LOG Time:
LOG values 8069942.12541325, 7881659.651232712, 8297796.909858819, 8214590.123021921, 8573521.716646269 runs/s
LOG avg 8207502.105234595 runs/s
LOG median 8214590.123021921 runs/s
LOG stdev 258490.7157687924 runs/s
LOG min 7881659.651232712 runs/s
LOG max 8573521.716646269 runs/s
== End Benchmark =========== 
{
  description: '1. Long classname',
  selector: '.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
  result: 8040709.863405826
}
{
  description: '2. Short classname',
  selector: '.a',
  result: 8207502.105234595
}

With Style Parsing

This variation sets and resets the CSS as part of the measured test

const runTest = (description, selector) => new Promise((resolve, reject) => {
  PerfTestRunner.measureRunsPerSecond({
    description: `Selector Test ${description}`,
    run: function() {
      setCSS(`${selector} { color: red; }`);
      resetCSS();
    },
    iterationCount: 5,
    done: resolve,
  });
});
$ npm run benchmark selectors/classnames

> [email protected] benchmark
> node cli/index.js selectors/classnames

== Starting Benchmark ====== 
LOG Description: Selector Test 1. Long classname
LOG Running 5 times
LOG Ignoring warm-up run (632412.5064188003 runs/s)
LOG 651192.3688548546 runs/s
LOG 649557.2882610039 runs/s
LOG 662206.1933380835 runs/s
LOG 652575.6770955006 runs/s
LOG 683982.0166202277 runs/s
TIM blink_perf: 3941.840087890625 ms
LOG 
LOG Time:
LOG values 651192.3688548546, 649557.2882610039, 662206.1933380835, 652575.6770955006, 683982.0166202277 runs/s
LOG avg 659902.7088339342 runs/s
LOG median 652575.6770955006 runs/s
LOG stdev 14332.674626582097 runs/s
LOG min 649557.2882610039 runs/s
LOG max 683982.0166202277 runs/s
LOG Description: Selector Test 2. Short classname
LOG Running 5 times
LOG Ignoring warm-up run (757905.1016874907 runs/s)
LOG 765798.3298473341 runs/s
LOG 730217.751166809 runs/s
LOG 700723.7794941305 runs/s
LOG 729289.0753778096 runs/s
LOG 699317.0731961479 runs/s
TIM blink_perf: 4101.078125 ms
LOG 
LOG Time:
LOG values 765798.3298473341, 730217.751166809, 700723.7794941305, 729289.0753778096, 699317.0731961479 runs/s
LOG avg 725069.2018164463 runs/s
LOG median 729289.0753778096 runs/s
LOG stdev 27198.568344545973 runs/s
LOG min 699317.0731961479 runs/s
LOG max 765798.3298473341 runs/s
== End Benchmark =========== 
{
  description: '1. Long classname',
  selector: '.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
  result: 659902.708833934
}
{
  description: '2. Short classname',
  selector: '.a',
  result: 725069.2018164463
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment