Repository navigation
Conversation
Named `wx-rx-view` where the x is a for absolute or r for relative. In dest, src order since there is some precedence in existing buffer copy. All functions call the multimethod `helins.binf.protocol/copy-view`. For the multimethod: There is a specialized implementation for java ByteBuffer -> ByteBuffer. There is a specialized implementation for backing buffer -> backing buffer which is the path used by js/DataView. Then there is a default implementation that allocates an intermediate buffer. The default implementation is not hit in the tests since the specialized versions are used instead. It can be verified that it works for both clojure/script by commenting out the specialized implementations then running the tests.
|
It is a valid use case. I thought about it quite a few times. The "problem" is that BinF is polymorphic. Well, this is a feature. While most projects will simply need That means that for most efficiency during copying, you have to know the types of what you handle. As you point out, if you know that you are using As your PR shows, there is no trivial solution. I admit I didn't consider multimethods, jumped straight to protocols at that time. I haven't yet taken the time to thoroughly review your implementation. My main concern is that a multimethod might be taxing for small copies, maybe even more so than allocating an intermediary buffer. I'fll first write better tests (following #3) and then see what we can do here. I prefer not to rush as it is adding quite a bit of complexity. Did you use it with success? Did you need any other type that was not implementing |
|
When I have a little time I might do some performance investigations. I feel historically whenever I have copied stuff between a view or stream like thing in whatever language/library it is typically a large chunk at a time. Like my specific case right now is copying over vertex attributes from a glb file over into a view of a gpu buffer. In these patterns the multimethod overhead is ignorable and what matters is the implementation speed. Thus great to have the option to specialize. Obviously the multimethod overhead will change the arithmetic if there is a lot of shuttling of small chunks of unaltered data between views. For all the stuff I am doing right now java/ByteBuffer and js/ArrayBuffer feel like the correct underlying data. So no right now I don't need implementations for other types. But off the top of my head I would have thought that And for JS there is the experimental streams api. Again I don't know how well binf would deal with a stream as its underlying. I guess just implement the relative protocols. And I think the protocol way is a very good fit. It does allow for other implementations if needed. And the predominant usage is doing quite a lot of small operations with one view at a time. Thus only single dispatch is needed and the protocols wins on minimizing overhead. Functions operating on two views needing multiple dispatch are the edge case. All the code in the PR is just additive so it can quite happily live in an auxiliary library if that is a better home for it. Right now it is sitting just fine in a utility namespace in my project. |
Rationale
I have hit a few scenarios where I want to copy bytes from one view to another. It feels natural for this to be part of the main
binfnamespace. The alternative is to do something likera-bufferfollowed bywa-buffer. But it is nice to just copy directly between the views when possible rather than going via an intermediate buffer.Example + boilerplate
What is added
Various functions named in format
wx-rx-viewwhere thexisafor absolute orrfor relative.Arguments are in dest, src order since there is some precedence in existing buffer copy function.
All functions call a new multimethod
helins.binf.protocol/copy-view.Notes on the multimethod
There is a specialized implementation for java ByteBuffer -> ByteBuffer that uses
.put.There is a specialized implementation for backing buffer -> backing buffer which is the path used by js/DataView.
Then there is a default implementation that allocates an intermediate buffer that will work for anything that implement the relevant binf protocols.
The default implementation is not hit in the tests since the specialized versions are used instead. It can be verified that it works for both clojure/script by commenting out the specialized implementations then running the tests.
Notes and Caveats