New vs cached object (v4)

Revision 4 of this benchmark created on


Preparation HTML

<script>

const iterations = 32; // Adjust this number to find the tipping point

// Setup
const tailwindClasses = [
  'shadow-sm', 'shadow-md', 'shadow-lg',
  'text-sm', 'text-base', 'text-lg', 'text-xl',
  'font-normal', 'font-medium', 'font-semibold', 'font-bold',
  'bg-red-500', 'bg-blue-500', 'bg-green-500', 'bg-yellow-500',
  'hover:bg-red-600', 'hover:bg-blue-600', 'hover:bg-green-600', 'hover:bg-yellow-600',
  'p-2', 'p-4', 'p-6',
  'px-2', 'px-4', 'px-6',
  'py-1', 'py-2', 'py-3',
  'rounded', 'rounded-md', 'rounded-lg',
  'transition', 'transition-colors', 'transition-transform'
];

function getRandomClasses(count) {
  const classes = new Set();
  while (classes.size < count) {
    classes.add(tailwindClasses[Math.floor(Math.random() * tailwindClasses.length)]);
  }
  return Array.from(classes);
}

// Extended composeStyle function
function composeStyle(styleString) {
  switch (styleString) {
    // Shadows
    case 'shadow-sm': return { boxShadow: '0 1px 2px 0 rgba(0, 0, 0, 0.05)' };
    case 'shadow-md': return { boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)' };
    case 'shadow-lg': return { boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)' };
    
    // Text sizes
    case 'text-sm': return { fontSize: '0.875rem', lineHeight: '1.25rem' };
    case 'text-base': return { fontSize: '1rem', lineHeight: '1.5rem' };
    case 'text-lg': return { fontSize: '1.125rem', lineHeight: '1.75rem' };
    case 'text-xl': return { fontSize: '1.25rem', lineHeight: '1.75rem' };
    
    // Font weights
    case 'font-normal': return { fontWeight: '400' };
    case 'font-medium': return { fontWeight: '500' };
    case 'font-semibold': return { fontWeight: '600' };
    case 'font-bold': return { fontWeight: '700' };
    
    // Background colors
    case 'bg-red-500': return { backgroundColor: '#EF4444' };
    case 'bg-blue-500': return { backgroundColor: '#3B82F6' };
    case 'bg-green-500': return { backgroundColor: '#10B981' };
    case 'bg-yellow-500': return { backgroundColor: '#F59E0B' };
    
    // Hover background colors
    case 'hover:bg-red-600': return { ':hover': { backgroundColor: '#DC2626' } };
    case 'hover:bg-blue-600': return { ':hover': { backgroundColor: '#2563EB' } };
    case 'hover:bg-green-600': return { ':hover': { backgroundColor: '#059669' } };
    case 'hover:bg-yellow-600': return { ':hover': { backgroundColor: '#D97706' } };
    
    // Padding
    case 'p-2': return { padding: '0.5rem' };
    case 'p-4': return { padding: '1rem' };
    case 'p-6': return { padding: '1.5rem' };
    case 'px-2': return { paddingLeft: '0.5rem', paddingRight: '0.5rem' };
    case 'px-4': return { paddingLeft: '1rem', paddingRight: '1rem' };
    case 'px-6': return { paddingLeft: '1.5rem', paddingRight: '1.5rem' };
    case 'py-1': return { paddingTop: '0.25rem', paddingBottom: '0.25rem' };
    case 'py-2': return { paddingTop: '0.5rem', paddingBottom: '0.5rem' };
    case 'py-3': return { paddingTop: '0.75rem', paddingBottom: '0.75rem' };
    
    // Border radius
    case 'rounded': return { borderRadius: '0.25rem' };
    case 'rounded-md': return { borderRadius: '0.375rem' };
    case 'rounded-lg': return { borderRadius: '0.5rem' };
    
    // Transitions
    case 'transition': return { transition: 'all 150ms cubic-bezier(0.4, 0, 0.2, 1)' };
    case 'transition-colors': return { transition: 'background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1)' };
    case 'transition-transform': return { transition: 'transform 150ms cubic-bezier(0.4, 0, 0.2, 1)' };
    
    default: return {};
  }
}

// Test case 1: Always generating objects
function testAlwaysGenerate() {
  return cases.map(set =>
  	set.map((style) => composeStyle(style))
  )
}

// Test case 2: Using a cache
function testWithCache() {
  const cache = {};
  return cases.map(set =>
  	set.map(style => {
      if (!cache[style]) {
        cache[style] = composeStyle(style);
      }
      return cache[style];
    })
  )
}

const cases = []
for (let i = 0; i < iterations; i++) {
	cases.push(getRandomClasses(i % 15))
}
</script>

Test runner

Ready to run.

Testing in
TestOps/sec
Always Create
testAlwaysGenerate()
ready
Always Cache
testWithCache()
ready
Always Create and Spread
testAlwaysGenerate()
	.map(v => Object.assign({}, ...v))
ready
Always Cache and Spread
testWithCache()
	.map(v => Object.assign({}, ...v))
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.