Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/bolt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 2024-06-11 - KMP String Allocation in Hot Paths
**Learning:** In Kotlin Multiplatform hot paths (like Hex parsing/formatting), relying on standard library string manipulations (`toLong(16)`, `toString(16).padStart()`) incurs massive performance overhead due to cross-platform string allocation and state machine conversions.
**Action:** When optimizing tight loops or parsing algorithms in KMP, replace standard string functions with manual character iteration, arithmetic, and bitwise shifts. For string building, prefer `CharArray.concatToString()` to bypass unnecessary platform-specific string allocation overhead.
28 changes: 24 additions & 4 deletions halogen-core/src/commonMain/kotlin/halogen/ThemeExpander.kt
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,36 @@ public object ThemeExpander {
require(hex.startsWith("#") && hex.length == 7) {
"Invalid hex color: \"$hex\". Expected format: #RRGGBB"
}
val rgb = hex.substring(1).toLong(16).toInt()
return rgb or (0xFF shl 24).toInt()
// ⚡ Bolt: Replaced Regex/String conversions with manual char iteration
// and bitwise shifts to eliminate KMP string allocation overhead in hot paths.
var rgb = 0
for (i in 1..6) {
val char = hex[i]
val digit = when {
char in '0'..'9' -> char - '0'
char in 'a'..'f' -> char - 'a' + 10
char in 'A'..'F' -> char - 'A' + 10
else -> throw IllegalArgumentException("Invalid hex character: $char")
}
rgb = (rgb shl 4) or digit
}
return rgb or (0xFF shl 24)
}

/**
* Convert an ARGB integer to a hex color string like "#1A73E8".
*/
public fun argbToHex(argb: Int): String {
val rgb = argb and 0xFFFFFF
return "#" + rgb.toString(16).padStart(6, '0').uppercase()
// ⚡ Bolt: Replaced toString(16).padStart() with manual char array assignment
// and concatToString() to prevent slow, platform-dependent string building overhead.
val chars = CharArray(7)
chars[0] = '#'
val rgb2 = argb and 0xFFFFFF
for (i in 0..5) {
val nibble = (rgb2 ushr ((5 - i) * 4)) and 0xF
chars[i + 1] = if (nibble < 10) (nibble + 48).toChar() else (nibble + 55).toChar()
}
return chars.concatToString()
}

private fun buildScheme(palette: HalogenPalette, isDark: Boolean): HalogenColorScheme {
Expand Down
Loading