Ignite缓存:Serializable与Externalizable孰优孰劣?性能异常求解
Great question—this is such a common gotcha because we’re taught that Externalizable should outperform Serializable by skipping reflection-based field parsing. But in Ignite’s specific environment, there are several key reasons you might see the opposite result. Let’s break them down:
1. Ignite’s BinaryMarshaller Optimizations for Serializable
Ignite’s default serialization engine, BinaryMarshaller, is heavily optimized for standard Serializable classes:
- It caches class metadata (field names, types, offsets) after the first serialization, so subsequent calls avoid expensive reflection lookups.
- It supports partial serialization for cached objects—if only a few fields change, Ignite can serialize just those fields instead of the entire object. This is impossible with
Externalizable, where you have to manually write/read every field every time. - It uses a compact binary format that replaces full class names with unique IDs, reducing payload size and parsing overhead.
Externalizabledoesn’t get this benefit; it has to write the full class name on every serialization.
2. Suboptimal Externalizable Implementations
Most developers don’t write Externalizable code that’s as optimized as Ignite’s built-in logic. Common mistakes include:
- Using inefficient I/O operations (e.g., calling
writeInt()for every single integer field instead ofwriteIntArray()for a batch). - Not reusing buffers or stream objects, leading to unnecessary object creation and garbage collection overhead.
- Overcomplicating the read/write logic (e.g., adding extra validation or transformation steps that aren’t needed, but add runtime cost).
In contrast, even though Serializable’s default implementation uses reflection, Ignite’s optimizations eliminate most of that overhead—making it faster than a poorly written Externalizable implementation.
3. JIT Compilation and Warm-Up Effects
If your test runs were too short, you might not have given the JVM time to optimize the code. Serializable with Ignite’s marshaller can benefit more from JIT warm-up because its core logic is in Ignite’s well-optimized library code. Custom Externalizable methods, on the other hand, might take longer to reach peak performance (or never get optimized as well if they’re not called frequently enough).
What You Can Do to Fix This
If you still want to use Externalizable for performance, try these steps:
- Optimize your implementation: Use bulk I/O methods, minimize object creation in
writeExternal()/readExternal(), and keep the logic as lean as possible. - Check your marshaller: Ensure you’re not using a non-optimized marshaller (like
JdkMarshaller).BinaryMarshalleris the default and the best choice for most cases. - Consider Ignite-specific serialization: For the best performance in Ignite, use
Binarylizable(Ignite’s custom interface) or annotate fields with@QuerySqlField—these are designed to work seamlessly with Ignite’s caching and serialization pipeline, often outperforming bothSerializableandExternalizable.
内容的提问来源于stack exchange,提问作者Ashish Bhosle

