-
Notifications
You must be signed in to change notification settings - Fork 340
HTTP2 functionality requires changes to work with TTD #372
Comments
I certainly agree that the aliasing of the backing array is a bit of a hack but it's an effective one in terms of performance. The speedup is absolutely non-trivial. Just as an FYI, I'm also doing this with a key part of the Performance API implementation. Until we have a better solution with a similar or improve performance profile, it's likely to be something we stick with. |
@jasnell thanks for the insight- would Mark's suggestion of creating macros for this pattern be something we could PR upstream? |
Hi James, I am sure the perf improvement is non-trivial. The cost of cross-runtime calls is painful is going to be painful on a hot-paths like this. In the short term my big concerns are (1) adding TTD and managing merge conflicts and (2) general maintainability. As the code is written now there is no encapsulation or indication that a write is happening to a JS aliased array (and which one it might be). As per my previous comment I think a adding some macros on the C++ side for this idiom would help a lot with these issues and simplify later code changes. In the longer term I think this is a good opportunity to start looking at what a Node.js embedder API would look like. For example in the case of fs.stat there is a similar native/JS shared array for the fs stats data that is directly written into to avoid the cost of multiple cross runtime boundary calls. But even with this optimization the JS layer still needs to unpack each value in the array and assign to a property in a JS object (line 245 in fs.js). Having an API like: |
The possibility of adding a macro makes sense. It could get a bit complicated. |
@jasnell I spent some time talking with @mike-kaufman about the macro option. I think we are going to give it a try to see how it seems to work out. |
Spent some time looking at this yesterday. The macro solution feels pretty kludgy IMO. What about introducing an Functions should be inlined so perf impact should be minimal. E.g., a class roughly like the following: template <class T, class U>
class AliasedBuffer {
public:
AliasedBuffer(const int count);
~AliasedBuffer();
T* GetBuffer();
v8::Local<U> GetJSArray();
// set the value at specified index. Since this is an explicit write, chakra's fork
// can add in code to do TTD-specific tracking. Need to know this is a write
// vs a read, so overloading operator[] won't work AFAIU (let me know if not the case)
void SetValue(const int index, T value);
// get value at specified index.
const T GetValue(const int index);
private:
T* buffer_; // raw buffer that is written to
v8::Global<U> jsArray_; // JS array over the buffer
};
} So, then a client can have something like ...
private:
AliasedBuffer* fields_;
public:
init() {
fields_ = new AliasedBuffer<double, Float64Array>(kfieldsCount);
}
doSoemthing() {
double status = ...;
fields_->SetValue(kMyStatusFieldIndex, status);
} @jasnell , @mrkmarron , @digitalinfinity - let me know your thoughts on this approach. Particularly
|
Ping @addaleax ... would like your input on this also if you don't mind |
Fwiw, async-hooks is another place where this also came up. @mike-kaufman Your proposed solutions sounds good to me!
You could make |
Ahh, I see, thanks. My preference is to have separate get/set methods, as it seems simpler, but I'd like to keep things consistent w/ what's in the code base. Let me know if there's anything to suggest one direction or the other. |
I think this works also. The important bit is going to be ensuring that these backing buffers can be set per-Environment and that they are persistent over time. I have no perf concerns with this approach. I agree that an One other consideration is this: In some cases, we have a single TypedArray backed by a single ArrayBuffer backed by a single backing array. In other cases, we have multiple TypedArray instances backed by a single aggregate ArrayBuffer backed by a single backing array. This is done simply because it is more efficient than having multiple ArrayBuffers. It would be nice if this approach accounted for that model as well. I believe this is easily something that we could get merged into core and would help make our application of this pattern more consistent. Thank you very much for working on this. |
@jasnell - Can you point me to any examples of this? I didn't see it when I was looking around yesterday.
OK, makes sense, i'll overload the operators. |
Just to make sure it doesn’t get lost, |
where's the best place to add unit-tests for such a class? |
Take a look at test/cctest |
@jasnell, @addaleax - thanks for your help. Plz take a look at nodejs/node#15077. |
Some changes to http2 require updates to support TTD properly: the upstream commit is
nodejs/node@e46ae99 and will need similar changes to those in #194, or otherwise will require a change in how we handle this scenario.
I spoke with @mrkmarron and he had this to offer:
The text was updated successfully, but these errors were encountered: