-
Notifications
You must be signed in to change notification settings - Fork 494
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add functionality for serializing depot manifests #1113
Conversation
79fea9f
to
9094e44
Compare
9094e44
to
f2dfe4f
Compare
@psychonic How soon is the next SteamKit release? Want to know when I can integrate these changes into DepotDownloader. |
Usually its whenever I decide to publish one 😄 |
Thank you for your contribution to the serialization logic of if ( !uniqueChunks.Exists( x => x.SequenceEqual( chunk.ChunkID! ) ) )
{
uniqueChunks.Add( chunk.ChunkID! );
} This approach, unfortunately, leads to each existence check having a time complexity of O(N), resulting in an overall complexity of O(N^2) for this section of the code. This becomes significantly problematic for large manifests, such as those exceeding 100GB, where the serialization process could extend up to 30 minutes or more. To address this issue and enhance the performance, I suggest utilizing a class ByteArrayComparer : IEqualityComparer<byte[]>
{
public bool Equals(byte[] x, byte[] y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null || y == null) return false;
return x.SequenceEqual(y);
}
public int GetHashCode(byte[] obj)
{
if (obj == null) throw new ArgumentNullException(nameof(obj));
// Adjust the hash code calculation as needed to ensure uniform distribution
return BitConverter.ToInt32(obj, 0);
}
}
// Usage...
var uniqueChunks = new HashSet<byte[]>(new ByteArrayComparer());
foreach (var chunk in file.Chunks)
{
var protochunk = new ContentManifestPayload.FileMapping.ChunkData()
{
sha = chunk.ChunkID,
crc = BitConverter.ToUInt32(chunk.Checksum!, 0),
offset = chunk.Offset,
cb_original = chunk.UncompressedLength,
cb_compressed = chunk.CompressedLength
};
protofile.chunks.Add(protochunk);
// Directly use HashSet.Add for O(1) complexity
uniqueChunks.Add(chunk.ChunkID!);
} By implementing this solution, we can significantly improve the performance of the serialization process for large depot manifests. I hope you find this suggestion helpful and consider integrating it into your pull request. Thank you again for your valuable contribution. |
foreach ( var file in Files ) | ||
{ | ||
var protofile = new ContentManifestPayload.FileMapping(); | ||
protofile.filename = file.FileName.Replace( '/', '\\' ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was incorrectly replacing slashes if the filename was not decrypted.
Discovered while adding a roundtrip test: 7559904
This adds functionality for serializing depot manifests into Steam-compatible protobuf files. The output matches .manifest files found in Steam's depotcache folder unless there are non-ASCII filenames present. It seems that Steam handles filename sorting slightly differently, not quite sure what's going on there.
I'm intending to use this as a stepping stone towards migrating DepotDownloader to using Steam protobuf manifests.