Performance Tips

This guide covers techniques to optimize Colorium for maximum performance in your applications.

Overview

AreaImpactDifficulty
CachingHighEasy
Batch ProcessingHighEasy
Object PoolingMediumMedium
Lazy EvaluationMediumEasy
Avoiding Unnecessary OperationsHighEasy
Using ConstantsMediumVery Easy

Caching

Cache Color Conversions

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
from colorium import Color
from functools import lru_cache

class ColorCache:
    def __init__(self):
        self._cache = {}

    def get_hsl(self, color):
        """Get HSL with caching"""
        key = (color.red, color.green, color.blue)
        if key not in self._cache:
            self._cache[key] = color.to_hsl()
        return self._cache[key]

    def get_hex(self, color):
        """Get hex string with caching"""
        key = (color.red, color.green, color.blue)
        if key not in self._cache:
            self._cache[key] = color.to_hex_string()
        return self._cache[key]

# Usage
cache = ColorCache()
color = Color(100, 150, 200)

# First call calculates
hsl1 = cache.get_hsl(color)

# Second call uses cache
hsl2 = cache.get_hsl(color)

Cache Similarity Results

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
from colorium import Color

class SimilarityCache:
    def __init__(self):
        self._cache = {}

    def get_similarity(self, color1, color2):
        """Get similarity with caching"""
        # Create sorted key for symmetric caching
        key = self._make_key(color1, color2)

        if key not in self._cache:
            self._cache[key] = color1.similarity(color2)

        return self._cache[key]

    def _make_key(self, color1, color2):
        """Create cache key"""
        # Sort colors for consistent key
        c1 = (color1.red, color1.green, color1.blue)
        c2 = (color2.red, color2.green, color2.blue)

        if c1 > c2:
            c1, c2 = c2, c1

        return (c1, c2)

# Usage
cache = SimilarityCache()
color1 = Color(100, 150, 200)
color2 = Color(120, 130, 180)

# First call calculates
sim1 = cache.get_similarity(color1, color2)

# Second call uses cache
sim2 = cache.get_similarity(color1, color2)

LRU Cache for Functions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from colorium import Color
from functools import lru_cache

@lru_cache(maxsize=1000)
def get_hsl_values(r, g, b):
    """Cache HSL conversion by RGB values"""
    color = Color(r, g, b)
    return color.to_hsl()

@lru_cache(maxsize=1000)
def get_hex_string(r, g, b):
    """Cache hex string conversion"""
    color = Color(r, g, b)
    return color.to_hex_string()

# Usage
hsl1 = get_hsl_values(100, 150, 200)
hsl2 = get_hsl_values(100, 150, 200)  # Uses cache

Batch Processing

Batch Convert Colors

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from colorium import Color

def batch_to_hex(colors):
    """Convert multiple colors to hex at once"""
    return [color.to_hex_string() for color in colors]

def batch_to_hsl(colors):
    """Convert multiple colors to HSL at once"""
    return [color.to_hsl() for color in colors]

def batch_lighten(colors, amount=0.1):
    """Lighten multiple colors at once"""
    return [color.clone().lighter(amount) for color in colors]

# Usage
colors = [
    Color(100, 150, 200),
    Color(200, 50, 100),
    Color(50, 200, 150)
]

hexes = batch_to_hex(colors)
hsls = batch_to_hsl(colors)
lightened = batch_lighten(colors, 0.2)

Batch Processing with Filter

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
from colorium import Color

def process_colors_batch(colors, operations):
    """Apply multiple operations to colors"""
    results = []

    for color in colors:
        result = color.clone()

        for op, args in operations:
            if op == 'lighten':
                result.lighter(*args)
            elif op == 'darken':
                result.darker(*args)
            elif op == 'saturate':
                result.saturate(*args)
            elif op == 'desaturate':
                result.desaturate(*args)

        results.append(result)

    return results

# Usage
colors = [
    Color(100, 150, 200),
    Color(200, 50, 100),
    Color(50, 200, 150)
]

operations = [
    ('lighten', (0.2,)),
    ('saturate', (0.3,))
]

processed = process_colors_batch(colors, operations)

Object Pooling

Color Pool for Repeated Use

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
from colorium import Color
from collections import deque

class ColorPool:
    def __init__(self, max_size=100):
        self.pool = deque(maxlen=max_size)
        self.in_use = set()

    def acquire(self, red, green, blue):
        """Get a color from the pool"""
        # Check if exact color exists
        for color in self.pool:
            if (color.red == red and
                color.green == green and
                color.blue == blue and
                color not in self.in_use):
                self.in_use.add(color)
                return color

        # Create new color
        color = Color(red, green, blue)
        self.pool.append(color)
        self.in_use.add(color)
        return color

    def release(self, color):
        """Return color to pool"""
        if color in self.in_use:
            self.in_use.remove(color)

# Usage
pool = ColorPool()

# Get color from pool
color1 = pool.acquire(255, 0, 0)

# Use color
print(color1.to_hex_string())

# Release back to pool
pool.release(color1)

# Reuse same color
color2 = pool.acquire(255, 0, 0)
print(color2 is color1)  # True (same object)

Clone Pool

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
from colorium import Color

class ClonePool:
    def __init__(self, template):
        self.template = template
        self.cache = {}

    def get_variant(self, operation, amount):
        """Get cached variant of template"""
        key = (operation, round(amount, 2))

        if key not in self.cache:
            color = self.template.clone()
            if operation == 'lighten':
                color.lighter(amount)
            elif operation == 'darken':
                color.darker(amount)
            elif operation == 'saturate':
                color.saturate(amount)
            self.cache[key] = color

        return self.cache[key].clone()

# Usage
base = Color(100, 150, 200)
pool = ClonePool(base)

# Get variants quickly
light = pool.get_variant('lighten', 0.2)
dark = pool.get_variant('darken', 0.3)
saturated = pool.get_variant('saturate', 0.5)

Lazy Evaluation

Lazy Color

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
from colorium import Color

class LazyColor:
    def __init__(self, red, green, blue):
        self._red = red
        self._green = green
        self._blue = blue
        self._color = None
        self._hsl = None
        self._hex = None

    @property
    def color(self):
        """Get Color instance (created lazily)"""
        if self._color is None:
            self._color = Color(self._red, self._green, self._blue)
        return self._color

    @property
    def hsl(self):
        """Get HSL (calculated lazily)"""
        if self._hsl is None:
            self._hsl = self.color.to_hsl()
        return self._hsl

    @property
    def hex(self):
        """Get hex string (calculated lazily)"""
        if self._hex is None:
            self._hex = self.color.to_hex_string()
        return self._hex

# Usage
lazy = LazyColor(100, 150, 200)

# Only HSL is calculated
print(lazy.hsl)

# Hex is calculated when needed
print(lazy.hex)

Lazy Operation Chain

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
from colorium import Color

class LazyOperation:
    def __init__(self, color):
        self.color = color
        self.operations = []

    def lighten(self, amount):
        self.operations.append(('lighten', amount))
        return self

    def darken(self, amount):
        self.operations.append(('darken', amount))
        return self

    def saturate(self, amount):
        self.operations.append(('saturate', amount))
        return self

    def execute(self):
        """Execute all operations lazily"""
        result = self.color.clone()
        for op, amount in self.operations:
            if op == 'lighten':
                result.lighter(amount)
            elif op == 'darken':
                result.darker(amount)
            elif op == 'saturate':
                result.saturate(amount)
        return result

# Usage
color = Color(100, 150, 200)
lazy = LazyOperation(color)

# Chain operations without executing
lazy.lighten(0.2).saturate(0.3).darken(0.1)

# Execute all at once
result = lazy.execute()

Avoiding Unnecessary Operations

Use Direct Access

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from colorium import Color

color = Color(100, 150, 200)

# Good - direct access
red = color.red
green = color.green
blue = color.blue

# Avoid - unnecessary conversion
rgb = color.to_rgb()
red = rgb['r']
green = rgb['g']
blue = rgb['b']

Use Built-in Methods

1
2
3
4
5
6
7
8
9
10
11
from colorium import Color

color = Color(100, 150, 200)

# Good - use built-in
color.lighter(0.2)

# Avoid - manual manipulation
hsl = color.to_hsl()
hsl['l'] += 0.2
new_color = Color.from_hsl(hsl['h'], hsl['s'], hsl['l'])

Check Before Converting

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from colorium import Color

def process_color(color, need_hex=False, need_hsl=False):
    """Process color with conditional conversion"""
    result = color.clone()

    # Only convert if needed
    if need_hex:
        hex_value = color.to_hex_string()
        print(f"Hex: {hex_value}")

    if need_hsl:
        hsl = color.to_hsl()
        print(f"HSL: {hsl}")

    return result

# Usage
color = Color(100, 150, 200)
process_color(color, need_hex=True)  # Only hex is converted

Using Constants

Pre-defined Constants

1
2
3
4
5
6
7
8
9
10
11
12
from colorium import RED, BLUE, GREEN, WHITE, BLACK

# Good - use constants
primary = RED
secondary = BLUE

# Avoid - create new colors
primary = Color(255, 0, 0)
secondary = Color(0, 0, 255)

# Constants are reused
print(RED is RED)  # True (same object)

Constant Collections

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from colorium import RED, BLUE, GREEN

class ColorConstants:
    """Collection of color constants"""
    PRIMARY = RED
    SECONDARY = BLUE
    SUCCESS = GREEN
    ERROR = RED
    WARNING = Color(255, 255, 0)
    INFO = Color(0, 0, 255)

# Usage
bg = ColorConstants.PRIMARY
text = ColorConstants.SECONDARY

Profiling

Measure Performance

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
from colorium import Color
import time

def profile_operation(operation, *args, iterations=10000):
    """Profile a color operation"""
    start = time.time()

    for _ in range(iterations):
        operation(*args)

    end = time.time()
    total_time = end - start
    avg_time = total_time / iterations

    print(f"Total time: {total_time:.3f}s")
    print(f"Avg time: {avg_time:.6f}s")
    print(f"Operations/sec: {iterations / total_time:.0f}")

# Profile different operations
color = Color(100, 150, 200)

print("Lighten:")
profile_operation(color.lighter, 0.2, iterations=10000)

print("\nTo HSL:")
profile_operation(color.to_hsl, iterations=10000)

print("\nTo Hex:")
profile_operation(color.to_hex_string, iterations=10000)

Performance Comparison

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
from colorium import Color
import time

def compare_methods(methods, iterations=10000):
    """Compare different methods"""
    results = {}

    for name, func in methods.items():
        start = time.time()

        for _ in range(iterations):
            func()

        end = time.time()
        results[name] = end - start

    # Find fastest
    fastest = min(results, key=results.get)

    for name, time_taken in sorted(results.items(), key=lambda x: x[1]):
        ratio = time_taken / results[fastest]
        print(f"{name:20}: {time_taken:.3f}s (x{ratio:.2f})")

    print(f"\nFastest: {fastest}")

# Compare methods
color = Color(100, 150, 200)

methods = {
    'direct': lambda: (color.red, color.green, color.blue),
    'to_rgb': lambda: color.to_rgb(),
    'to_hsl': lambda: color.to_hsl(),
    'to_hex': lambda: color.to_hex_string()
}

compare_methods(methods)

Optimization Checklist

CheckDescription
[ ] Use caching for repeated conversionsCache HSL, Hex, etc.
[ ] Batch process colorsProcess multiple colors together
[ ] Use constantsPre-defined color constants
[ ] Avoid unnecessary conversionsUse direct access when possible
[ ] Use object poolingReuse color objects
[ ] Lazy evaluationCalculate only when needed
[ ] Profile your codeFind bottlenecks
[ ] Use built-in methodsDon't reinvent the wheel

Next Steps


Previous: Custom Color Spaces Next: Integration Guide →

On this page
26 sections