Skip to content

Ghost Serialization v1.2.2

Choose a tag to compare

@juanchurtado1991 juanchurtado1991 released this 23 Jun 03:30
· 538 commits to main since this release

πŸ‘» Ghost Serialization v1.2.2 β€” Kotlin 2.1.10, KSP2 Support & Single-Pass Optimization

We are thrilled to release v1.2.2 of Ghost Serialization! This release brings full compatibility with Kotlin 2.1.10 and KSP2, alongside key performance optimizations that solidify Ghost as the fastest JSON engine for Kotlin Multiplatform.
With these updates, Ghost sweeps 1st place in all 6 JSON benchmark categories (Decode/Encode Γ— String/Bytes/Streaming) on the Twitter macro dataset.

⚑ Key Highlights

  • Kotlin 2.1.10 & KSP2 Support: Complete migration to KSP 2.1.10-1.0.31 with KSP2 enabled (ksp.useKSP2=true) for faster incremental compiler builds.
  • Single-Pass String Scan (GhostJsonStringReader): Combines key boundary detection and perfect hashing in a single unrolled loop over raw memory, cutting key-matching memory reads in half.
  • Zero-Allocation String Decoding: Replaces array allocation routines with intrinsic character access (rawData[index].code), boosting String decoding performance to +32.1% faster than Kotlinx Serialization (KSer) with 69.6% less memory.
  • Ktor Server & Client Extensions: Integrated direct byte-first respondGhost (Server) and bodyGhost (Client) functions to bypass Ktor pipeline overhead entirely.

πŸ“‹ Full Changelog

πŸš€ Performance

  • Single-Pass String Scan: Eliminated a redundant double-scan in the hot path of internalSelect. The new findClosingQuoteWithHash combines locating the closing quote and computing the 4-byte dispatch hash into a single loop, cutting key matching reads in half.

πŸ› οΈ Optimizations

  • Adapter Integration (Ktor, Retrofit, Spring Boot): Migrated Ktor, Retrofit, and Spring Boot adapters to use the new cached-serializer public APIs (Ghost.encodeToBytes and Ghost.deserialize), removing internal overhead.
  • RandomAccess List Loops: Replaced default Iterator-based loops with index-based loops in ListSerializer, IntArraySerializer, and LongArraySerializer for RandomAccess collections (like ArrayList) to avoid iterator heap allocations under heavy loops.
  • Map Entry-Set Iteration: Optimized MapSerializer to iterate entries directly instead of performing double hash lookups via key sets.
  • Fast-Path ASCII String Writer Scans: Refactored ASCII scans in GhostJsonStringWriter with hoisted local registers for native bulk copying.
  • Dynamic String Writer Heap Sizing: Reduced the default initial capacity of FlatCharArrayWriter from 8 KB to 1 KB (2 KB heap) and fine-tuned mobile buffer retention heuristics to lower memory footprint on Android and iOS.
  • Streaming Segment-Buffering: Implemented an internal 8 KB segment buffer directly in StreamingGhostSource to copy and hold active Okio segments, bypassing virtual dispatch.

✨ Added

  • Ktor Server & Client Direct Serialization: Added high-performance respondGhost (Server) and bodyGhost (Client) extensions, bypassing Ktor's ContentNegotiation pipeline.
  • Cached Serializer Overloads: Exposed new public overloads for encodeToString, encodeToBytes, deserialize, and deserializeStreaming that accept pre-resolved GhostSerializer<T> parameters.
  • Native String Reader Opt-in (ghost.textChannel): GhostJsonStringReader overloads are now opt-in via KSP configuration. When disabled (default), the string dispatch table is omitted, saving 4 KB of memory per DTO.

🧹 Refactored

  • Zero Magic Strings & Numbers: Centralized all template strings, error messages, and control identifiers into GhostEmitterConstants and GhostJsonConstants.
  • KMP Deprecations Cleanup: Replaced deprecated platform constructors with standard Kotlin Multiplatform CharArray.concatToString().

πŸ“¦ Quick Start

# gradle/libs.versions.toml
[versions]
ghost = "1.2.2"
ksp   = "2.1.10-1.0.31"
[libraries]
ghost-api           = { module = "com.ghostserializer:ghost-api", version.ref = "ghost" }
ghost-serialization = { module = "com.ghostserializer:ghost-serialization", version.ref = "ghost" }
ghost-compiler      = { module = "com.ghostserializer:ghost-compiler", version.ref = "ghost" }