Skip to content

Remove protobufjs in favor of protons-runtime #60

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

Open
wants to merge 26 commits into
base: main
Choose a base branch
from

Conversation

talentlessguy
Copy link
Contributor

@talentlessguy talentlessguy commented Feb 8, 2025

This closes #31

Switches to protons-runtime

All tests pass now

@alanshaw
Copy link
Member

@talentlessguy you might gain more savings switching to protons and protons-runtime instead? It would dudupe with protons-runtime in ipfs-unixfs-exporter.

@alanshaw
Copy link
Member

Note: I think in general I'd prefer to switch to protobuf-es as it seems to have a big community and usage behind it.

@talentlessguy
Copy link
Contributor Author

@talentlessguy you might gain more savings switching to protons and protons-runtime instead? It would dudupe with protons-runtime in ipfs-unixfs-exporter.

thanks for the suggestion

@achingbrain
Copy link
Member

FWIW, last time I ran the benchmark suite, protons was just over 20% faster than protobuf-es when serializing/deserializing - https://github.com/ipfs/protons/tree/main/packages/protons-benchmark#usage

These kind of performance characteristics are very important to high traffic deployments like Lodestar so it's unlikely to be switched away from elsewhere.

@talentlessguy
Copy link
Contributor Author

FWIW, last time I ran the benchmark suite, protons was just over 20% faster than protobuf-es when serializing/deserializing - https://github.com/ipfs/protons/tree/main/packages/protons-benchmark#usage

do you mean protobufjs, and not protons?

@achingbrain
Copy link
Member

No, I mean protons:

image

protobuf.js is also quite a bit faster than protobuf-es but it's CJS and the stack is ESM-only so that rules it out.

@talentlessguy
Copy link
Contributor Author

I wonder how hard it would be to replace protobuf-es with protons, will give it a shot rn

@achingbrain
Copy link
Member

I guess the only thing is that protons compiles protobuf definitions to TypeScript and this is still a js project.

@talentlessguy talentlessguy changed the title Remove protobufjs in favor of protobuf-es Remove protobufjs in favor of protons-runtime Feb 22, 2025
@alanshaw
Copy link
Member

alanshaw commented Apr 3, 2025

@achingbrain is the benchmark encode or decode? We're only encode in this repo.

@talentlessguy talentlessguy marked this pull request as ready for review May 19, 2025 19:15
@talentlessguy talentlessguy requested a review from alanshaw May 19, 2025 19:15
src/codec.js Outdated
Data: content.byteLength > 0 ? content : undefined,
filesize: content.byteLength,
Data: content.byteLength > 0 ? content : EMPTY_BUFFER,
filesize: BigInt(content.byteLength),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the dag-pb encoder support bigint?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about dag-pb, is it relevant to the PR?

Data: content.byteLength > 0 ? content : undefined,
filesize: content.byteLength,
Data: content.byteLength > 0 ? content : EMPTY_BUFFER,
filesize: content.length === 0 ? Object.assign(0n, { __forceEncode: true }) : BigInt(content.length),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need __forceEncode here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding these undefined fields and setting __forceEncode seems to be repeated often - shouldn't it be moved to encodePB so we get less change in other places?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is because protons-runtime ignores 0n because it thinks it's a default and because of that doesn't include it in the protobuf

Copy link
Member

@achingbrain achingbrain May 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Protons is a proto3 implementation though it tries it's best with proto2. The big difference is there's no "required" modifier any more because the authors considered it harmful.

If you want a value to always be in the protobuf in proto3 you should mark it optional and set a value. This is compatible on the wire with required in proto2.

E.g. these will result in the same bytes:

syntax = "proto2";

message Derp {
  required int64 Value = 1;
}
syntax = "proto3";

message Derp {
  optional int64 Value = 1;
}

You can see the proto3 definition ipfs-unixfs uses here and the bytes generated are compatible with older proto2 parsers.

There was some discussion about this on the libp2p specs repo a while back which goes over the various pros and cons and how to maintain backwards compatibility - libp2p/specs#465

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So what's the best solution? migrating js-unixfs to use proto3 or just keep it the way it is?

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.

Remove dependency on protobufjs
3 participants