Skip to content

[SharedCache] Rework metadata serialization to reduce memory overhead#6127

Closed
bdash wants to merge 1 commit into
Vector35:devfrom
bdash:dsc-serialization
Closed

[SharedCache] Rework metadata serialization to reduce memory overhead#6127
bdash wants to merge 1 commit into
Vector35:devfrom
bdash:dsc-serialization

Conversation

@bdash
Copy link
Copy Markdown
Contributor

@bdash bdash commented Nov 14, 2024

api/MetadataSerializable.hpp is removed in favor of including core/MetadataSerializable.hpp. Both headers defined types with the same name leading to One Definition Rule violations and surprising behavior.

The serialization and deserialization context are now created on-demand during serialization rather than being a member of MetadataSerializable. This reduces the size of every serializable object by ~220 bytes.

The serialization / deserialization context is passed explicitly as an argument to Serialize / Deserialize rather than it being found via member variable on this. As a result, Serialize / Deserialize can now be free functions rather than member functions.

The Serialize overloads are updated to consistently accept their values by const reference rather than by value. This avoids an unnecessary copy of the values during serialization.

Since MetadataSerializable is not used for dynamic dispatch, the virtual methods are removed and the class is updated to be a class template using CRTP. This allows delegating to the derived class's Load and Store methods without the additional size overhead of the vtable pointer in every serializable object.

These changes reduce the memory footprint after loading the macOS shared cache and loading a single dylib from it from 8.3GB to 4.6GB:

Before:

binaryninja [71457]: 64-bit    Footprint: 8234 MB (16384 bytes per page)

After:

binaryninja [41691]: 64-bit    Footprint: 4614 MB (16384 bytes per page)

@bdash
Copy link
Copy Markdown
Contributor Author

bdash commented Nov 14, 2024

@0cyn

api/MetadataSerializable.hpp is removed in favor of including
core/MetadataSerializable.hpp. Both headers defined types with the same
name leading to One Definition Rule violations and surprising behavior.

The serialization and deserialization context are now created on-demand
during serialization rather than being a member of
`MetadataSerializable`. This reduces the size of every serializable
object by ~220 bytes.

The context is passed explicitly as an argument to `Serialize` /
`Deserialize`. As a result, `Serialize` / `Deserialize` can now be free
functions rather than member functions.

Since `MetadataSerializable` is not used for dynamic dispatch,
the virtual methods are removed and the class is updated to be a class
template using CRTP. This allows delegating to the derived class's
`Load` and `Store` methods without the additional size overhead of the
vtable pointer in every serializable object.

These changes reduce the memory footprint of Binary Ninja after loading
the macOS shared cache and loading a single dylib from it from 8.3GB to
4.6GB.
@0cyn
Copy link
Copy Markdown
Contributor

0cyn commented Dec 10, 2024

Merged via ce88a94a

@0cyn 0cyn closed this Dec 10, 2024
@bdash bdash deleted the dsc-serialization branch December 19, 2024 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants