Are there effective solutions to reduce GC caused by ProtoBuf deserialization?
Are there effective solutions to reduce GC caused by ProtoBuf deserialization?
In Unity projects, GC generated during Protobuf deserialization mainly comes from two sources: temporary allocations in memory such as strings and boxing operations and inefficient calls caused by reflection mechanisms. The following are mature and effective solutions to these issues. 1. Use Preserve and Forced AOT Initialization to Avoid Reflection GC In IL2CPP environments, due to AOT compilation limitations, generic reflection methods in Protobuf generated code may not be precompiled. This can lead to runtime dynamic invocation failures or significant GC overhead. To ensure all necessary reflection initialization code is preserved: This method does not need to be called; it only needs to exist so that it is preserved by the linker. Combined with the attribute to prevent code stripping, it effectively resolves exceptions and performance issues caused by missing AOT generated code. 2. Avoid String and Value Type Boxing for Zero GC Parsing Assistance Referring to TMP text optimization strategies, output handling during Protobuf parsing can be customized to reduce intermediate allocations. For example, in custom logging systems or UI updates, reuse a directly instead of creating new strings via . Globally reuse a for formatted output. When converting numeric fields to strings, use a zero GC approach such as and write results into a preallocated character buffer. Implement a custom to bypass boxing and directly handle primitive types. 3. Use Low Level Byte Access Instead of High Cost APIs For high frequency parsing scenarios such as network synchronization , consider bypassing full deserialization and directly reading key fields from the byte stream: This approach skips object construction overhead and is suitable for lightweight updates where only partial data is required. 4. Pool Message Instances with a Buffer Pool Frequent creation and destruction of Protobuf objects can significantly increase GC pressure. It is recommended to use an object pool to cache commonly used message instances: Combined with resetting state via , reuse can significantly reduce memory allocation frequency. Summary The core strategy is: Forced AOT initialization Prevention of code stripping Buffer reuse Reduction of unnecessary deserialization paths These techniques have been validated in multiple production projects and can effectively reduce Protobuf related GC to near zero levels.