-
Notifications
You must be signed in to change notification settings - Fork 445
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
Investigate byte buffer based apis #816
Comments
From a Foundation session at WWDC: It looks like NIOFoundationCompat has a So, it may be worth figuring out how to make our serialization methods generic over |
There is also |
Just going to hijack this issue, we are going to investigate how we can get |
On thing I've debating in the past was to do something like the C++ Coded(Input|Output)Streams to wrap part of the serialization, move the existing plumbing on top of those. That might be a way to provide a non |
So our current thinking is to provide a protocol based abstraction that users of SwiftProtobuf can conform their bag of bytes types to. They can then pass their types to our generic methods and we can either read the bytes or write the bytes from their types. This is currently just an idea we have been thinking about. Once we dive into this more we will share more information here. We are also aware of the |
I know I've mentioned it in some contexts; one thing that would help performance was if we could create binary format in reverse order. This would allow creation of binary to be single pass as we wouldn't have to pre-compute the length for message fields. It clearly doesn't work if one is trying to support an api that could directly stream to a file/socket. And growing on the front isn't something most buffer apis do either (with resizes/memcopys). The few impls I've seen that do this usually "grow" by allocating discrete chunks so the file output is assembled via those chunks (sorta like Edit: Found it, #713 has some of that. |
We have started working on this now. The first PR is out now (#1326) with more to follow. Please feel free to look at it and leave any comments. |
I'd like to give some more context on what the proposed changes are, and why we're doing this. MotivationAs stated above by @FranzBusch, the end goal is to remove Proposed changesOverall, the idea is to make this transition opt-in instead of opt-out. There are two big places where
For the first item, the way we plan to achieve the removal of func serializedData() throws -> Data
init(serializedData: Data) throws
func jsonUTF8Data() throws -> Data
init(jsonUTF8Data: Data) throws ...to this: func serializedBytes<Bytes: SwiftProtobufContiguousBytes>(as: Bytes.Type = [UInt8]) throws -> Bytes
init<Bytes: SwiftProtobufContiguousBytes>(serializedBytes: Bytes) throws
func jsonUTF8Bytes<Bytes: SwiftProtobufContiguousBytes>(as: Bytes.Type = [UInt8]) throws -> Bytes
init<Bytes: SwiftProtobufContiguousBytes>(jsonUTF8Bytes: Bytes) throws Users will be able to conform their bag of bytes types to a new Names are TBC, but the overall end-goal structure of modules will be as follows:
For the second item, the short-term plan is to move away from Other changes to consider
Hope this clarifies some of the questions: please let me know your thoughts and if you have any follow-up queries. |
I guess |
Right, |
I'm not following that first bullet, what are the protos you are referring too here? For the second, if we go the route of a generation option, that could lead into complexity since generation is via an aspect, there isn't a good way to pass things down the build graph, and if two To the overall proposal, both points make sense to me; but I do wonder about landing (1) The (de)serialisation of binary and JSON protos completely first. Then doing a second wave of PRs for (2) The edit: and the second change seems to be the most source disrupting, so it would allow the first to hopefully be completed while sorting out the details of the second. (and I (personally) feel the second is worth while no matter what happens on the second). |
For completeness we should likely also document how we think we'll handle things in the SwiftPM plugin integration. |
Is this specifically about |
I agree, and I will split the PR that's currently in draft in two, to follow this recommendation.
Noted - I will add a mention to this, but I believe this should be pretty straightforward, simply exposing the new
Yes, that's exactly what I was referring to, sorry for the confusion. |
This isn't going to be thought out, but I'll record it incase it spurs ideas for anyone else… Re: Anyway, just wondering if there are other things that could be done with overloads/custom types/etc. to help in this space. |
I am not sure if exposing that kind of flexibility is what we want in the end. Let's assume the stdlib at some point provides types that can be used for the byte fields. If that happens we probably want to migrate to that type for the W.r.t. to the WKTs: I was thinking along the same lines as you with the overloads in the compat module; however, the only thing we really can do there is provide overloads that both copy and are suffix with something, i.e.: var someFieldData: Data { Data(self.someField } Which is both not nice and a performance footgun. |
The generation option idea (like If we think
There are already some custom hooks for any, so we might be able to minimize some of the costs for that one. But the other two could be non idea, I don't have much visibility on their usage to have an idea on the impact. But if we made the *Data ones the new/expensive ones, folks would have to update to use them and we could also tag them as deprecated to help get folks to realize they need to update code paths. |
I've created the PR above changing the target structure of the project to have the three modules: With regards to the WKTs, we think the best way forward is to do what was discussed above:
I'll work on updating the other existing PRs with these changes and your comments next. |
The multiple module aspect of this is likely to be an issue for CocoaPods. Opened #1334 for tracking since we accepted the first patch on the steps towards this. |
Ah yeah pod support is an interesting one. I might throw in a bit of a controversial take here. Maybe we should consider dropping pod support in the next major Furthermore, I think that a major version is perfect for this since CocoaPod users can still use the 1.x release which remains completely functional. Additionally, they can never get into version conflict problems where a downstream pod is using 2.x if we don't offer it. This would be a way better transition than what we have down in NIO etc. where we dropped support in a minor. |
It's functionally complete today (I don't think we've pulled over one or two things we recently did related to generation option case handling and the SwiftPM plugin). But nothing says it will stay that way in the future. I don't think we can say protobuf won't get something new at some point, and if they put a conformance test on #1159 or #1160, it won't be able to pass without some likely non trivial work. I wish there was a way to know how many people use the CocoaPods support. Edit: I'll say keeping/dropping CocoaPods support is ultimately up to Apple folks as owners of this project. |
Following up to @FranzBusch's idea – Going to https://cocoapods.org/ and typing in protobuf:
Going to https://cocoapods.org/ and typing in grpc:
|
Personally, I'd be happy to continue supporting CocoaPods if there's someone interested in doing the work. |
Looking in ~/.cocoapods/repos/master, doing
If CocoaPods really does have a single module per podspec limit, it is likely gonna take changes to the sources to support it. I'm not sure if the system could be gamed to use multiple podspec files from the single repo to pull off the multiple modules. |
We also decided 2.0 would be where we dropped the checked in SwiftProtobuf.xcodeproj, so we've dropped on other integration system "method" already. |
So our experience with NIO and gRPC was that supporting Pods/Carthage was getting harder and harder while being able to make use of the latest SPM features. I would be in favor of only supporting SPM with 2.0 and keeping the 1.x branch open for Cocoapods. We did the same for gRPC with a call to the community to support this going forward. Let's see where we are at when we wanna release 2.0 and we can make decision then? |
I'm going to close this out as 1.27 has some new apis around serialization that don't require |
Swift GRPC (via swiftnio?) is having to turn their buffers into
Data
object to then parse the protos. It might make sense to see if we can extend the parsing apis (binary atleast, but maybe also json and TextFormat), to make use of SE-0237 so other projects can bridge their own storage types into something that swift protobuf can parse without having to do extra copies.In their, the MutableCollection part of SE-0237 might also work for writing out message, but I'm not completely sure how worth it would be since they likely can extra from the
Data
pretty efficiently and likely have to for other things.The text was updated successfully, but these errors were encountered: