This guide provides best practices for using Rainbow library efficiently and getting the best performance from your colored terminal output.
Rainbow v4.2.0+ includes significant performance optimizations that can improve your application's performance by up to 578% for certain operations.
Problem: Traditional chained calls create multiple string copies:
// ❌ Inefficient - creates 4 intermediate strings
let slow = "Hello".red.bold.underline.onBlueSolution: Use the builder pattern for complex styling:
// ✅ Efficient - lazy evaluation, single string generation
let fast = "Hello".styled.red.bold.underline.onBlue.build()Performance Gain: ~578% improvement for complex chained calls.
Problem: Multiple individual style applications:
// ❌ Inefficient - multiple parsing and generation cycles
let slow = "Hello".red.bold.underline.italicSolution: Apply multiple styles in one operation:
// ✅ Efficient - single parsing and generation cycle
let fast = "Hello".applyingAll(
color: .named(.red),
styles: [.bold, .underline, .italic]
)Performance Gain: ~264% improvement for multiple style applications.
The internal string generator has been optimized with:
- Pre-allocated string buffers
- Reduced memory allocations
- Fast path for plain text segments
- Optimized ANSI sequence building
Performance Gain: ~20-30% improvement in string generation.
For different scenarios, use the most appropriate API:
// Single style - use simple properties
let simple = "Error".red
// Multiple styles - use batch operations
let multiple = "Warning".applyingAll(
color: .named(.yellow),
backgroundColor: .named(.black),
styles: [.bold, .underline]
)
// Complex chaining - use builder pattern
let complex = "Success".styled
.green
.bold
.onBlack
.underline
.build()
// Performance-critical code - use direct Rainbow API
let direct = Rainbow.generateString(for: entry)// ❌ Don't repeatedly style the same string
for i in 0..<1000 {
print("Item \(i)".red.bold) // Parses and generates 1000 times
}
// ✅ Style once, reuse the format
let template = "Item %@".applyingAll(color: .named(.red), styles: [.bold])
for i in 0..<1000 {
print(String(format: template, "\(i)")) // Only formats the number
}// For maximum compatibility
let compatible = "text".red
// For 256-color terminals
let enhanced = "text".bit8(196)
// For true-color terminals (use sparingly)
let truecolor = "text".bit24(255, 64, 128)// ❌ Process strings individually
let results = strings.map { $0.red.bold }
// ✅ Use builder pattern for better performance
let results = strings.map { $0.styled.red.bold.build() }
// ✅ Even better - use batch operations if styles are the same
let results = strings.map { $0.applyingAll(color: .named(.red), styles: [.bold]) }Rainbow includes comprehensive performance tests. Run them to benchmark your specific use case:
# Run all performance tests
swift test --filter PerformanceTests
# Run specific performance tests
swift test --filter PerformanceTests.testBuilderPatternPerformance
swift test --filter PerformanceTests.testBatchOperationPerformanceTraditional chained calls create multiple intermediate string objects:
// Creates 4 string objects
"text".red.bold.underline.onBlue
// ^1 ^2 ^3 ^4 (final)Builder pattern creates only the final string:
// Creates 1 string object
"text".styled.red.bold.underline.onBlue.build()
// ^1 (final)- Use builder pattern for complex styling to reduce memory pressure
- Avoid storing intermediate styled strings - compute them when needed
- Consider caching frequently used styled strings
- Profile your application to identify styling hotspots
Performance improvements achieved in Rainbow v4.2.0+:
| Operation | Traditional | Optimized | Improvement |
|---|---|---|---|
| Builder Pattern (complex chaining) | 37,006 ops/sec | 250,992 ops/sec | +578% |
| Batch Operations (multiple styles) | 33,156 ops/sec | 120,597 ops/sec | +264% |
| String Generator (optimized) | ~350,000 ops/sec | ~400,000 ops/sec | +14% |
Benchmarks run on Apple Silicon Mac with Swift 6.1.2
Most existing code will continue to work without changes. For performance-critical sections:
-
Identify hotspots - use performance profiling to find styling bottlenecks
-
Replace chained calls with builder pattern (available in v4.2.0+):
// Old let old = "text".red.bold.underline // New let new = "text".styled.red.bold.underline.build()
-
Use batch operations for multiple styles (available in v4.2.0+):
// Old let old = "text".red.bold.italic // New let new = "text".applyingAll(color: .named(.red), styles: [.bold, .italic])
All existing APIs remain fully functional. The optimizations are additive and don't break existing code.
For maximum performance in specific scenarios, you can use Rainbow's internal APIs:
// Create entry directly
let entry = Rainbow.Entry(segments: [
.init(text: "Hello", color: .named(.red), styles: [.bold])
])
// Generate string directly
let result = Rainbow.generateString(for: entry)If you're generating strings programmatically (not parsing existing colored strings), use direct entry creation to avoid parser overhead.
- Run performance tests to establish baseline metrics
- Profile your application to identify styling bottlenecks
- Use builder pattern for complex styling operations
- Consider caching frequently used styled strings
- Minimize repeated styling of the same content
If you discover additional performance optimizations or have use cases not covered by current optimizations, please:
- Create performance tests demonstrating the issue
- Propose optimizations with benchmarks
- Submit pull requests with performance improvements
- IMPROVEMENT_ROADMAP.md - Detailed technical analysis
- Performance Tests - Complete test suite
- Issue Tracker - Report performance issues