-
Notifications
You must be signed in to change notification settings - Fork 78
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
Deep dive discussion on {Async,Promise}_hooks & performance #248
Comments
I would like @mike-kaufman or another from Microsoft to also attend, as they appear to be the primary driver of "JavaScript Async Context". |
I'd like to attend if I can, so I put my times up. I have some thoughts on the subject. It's okay if it doesn't line up for me though. Definitely @hashseed, @mcollina and @AndreasMadsen are the core people we need most in the conversation. |
It would be great to have as many people attend as possible. Please add your preferences, and I will try my best to find a good timeslot 🤞. |
Done!
Il giorno gio 18 ott 2018 alle 23:34 Ali Ijaz Sheikh <
notifications@github.com> ha scritto:
… It would be great to have as many people attend as possible. Please add
your preferences, and I will try my best to find a good timeslot 🤞.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#248 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AADL49un_DM_3_Gfk3Mg8gdIbrriEQx2ks5umPPJgaJpZM4Xru28>
.
|
These evening slots are in general hard for me and also difficult to predict. I don't add anything in doodle to avoid to bias it but I will try to attend. |
Will this conversation be recorded? |
I'll try to attend as well, but think it is more important that times are good for other participants so won't complete the doodle. |
Based on the poll, the best meeting time slot seems to be Oct 30, 11am PDT (1900 Central Europe) (your local time). Hangouts meeting link: https://meet.google.com/tov-fcdh-jfw |
Is that 18:00 UTC? I'm switching to daylight saving time on the 28th, so I'm a bit worried and would like a fixed timezone specifier. |
I'm very sorry, but I'm very interested in the result of this discussion. |
@AndreasMadsen AFAIK that should be Oct 30th 1800 UTC. Timezones are hard 😂. @wentout you're welcome to join the hangouts at the time of the meeting! |
Google Calendar should handle timezones and daylight saving time correctly, at least it does here when I look at the Node.js Foundation Calendar. |
Just a reminder that this meeting will start in about 1-hr's time. It would be useful to review the prior discussions before the meeting (see OP). At the time of the meeting, participants can join the meeting at: https://meet.google.com/tov-fcdh-jfw. |
I'm on the road and won't make it :( |
Here is the link to the domain issue: nodejs/node#23862 |
Here is the link to the |
The recording of the meeting is here: https://youtu.be/2SCNsozMkF8. Thanks for everyone for participating. Here's a brief summary of the action plan:
Let me know if I missed or misunderstood anything. Full details in the recording. |
I can do that. Should I just resubmit the same PR or are there any changes required before resubmitting it? |
@mmarchini there are some comments in the PR that needs to be fixed, mainly there is an ask that we maintain a stack of the current async resources. |
Ok, thanks. I'll take a look into it next week. |
@mcollina Could you please point to the fix regarding |
@Flarna here it is nodejs/node#23201. |
@mcollina That PR looks like it is just a small fix. As far as I can see, the same resource object is still being reused. I would expect a fix that allows |
I agree with @AndreasMadsen. If a user stores some metadata into the |
@Flarna to be clear the docs specifically says:
Once the issue with |
@AndreasMadsen I cannot reproduce the problem anymore. Can you share a snippet that reproduces it? 'use strict'
const sleep = require('util').promisify(setTimeout)
const { createHook, executionAsyncResource } = require('async_hooks')
const asyncHook = createHook({init})
const sym = Symbol('cls')
asyncHook.enable()
function getCLS () {
return executionAsyncResource()[sym]
}
function setCLS (data) {
return executionAsyncResource()[sym] = data
}
function init (asyncId, type, triggerAsyncId, resource) {
var cr = executionAsyncResource()
if (cr) {
if (type === 'HTTP_PARSER') {
if (cr.noReuse) {
throw new Error('no reuse')
}
cr.noReuse = true
}
resource[sym] = cr[sym]
}
}
var counter = 0
const server = require('http').createServer(function (req, res) {
setCLS(counter++)
sleep(10).then(function () {
res.setHeader('content-type', 'application/json')
res.end(JSON.stringify({ cls: getCLS() }))
})
})
server.listen(3000) |
@mcollina I'm not in a position to compile anything right now, but 'use strict'
const http = require('http')
const { createHook } = require('async_hooks')
const reused = Symbol('reused')
const asyncHook = createHook({
init (asyncId, type, triggerAsyncId, resource) {
if (resource[reused]) {
throw new Error('reuse detected')
}
resource[reused] = true;
}
})
asyncHook.enable()
const server = http.createServer(function (req, res) {
res.end();
})
server.listen(3000, function () {
http.get('http://127.0.0.1:3000', function () {
http.get('http://127.0.0.1:3000', function () {
console.log('passed');
server.close();
});
});
}); is the test you need. |
@mcollina tested it now, the issue is still there. |
Implementing a wrapper on HTTPParser will be tricky 🤔. Do we really need to reuse HTTPParsers though? I changed the max amount of parsers in the FreeList at to 0, which forces Node.js to always create a new parser, and our benchmarks don't show significant regressions:
(I might be running the wrong benchmarks though. Are there any other recommended benchmarks I should run?) |
Why don’t you send a PR that removes that reuse? Then we can run our
benchmark ci.
I think it might not be needed anymore because: a) we have a new GC b)
referencing from “old” objects to “new” objects is costly, and this reuse
was causing that. In an ideal world, reusing that should not be needed.
Il giorno sab 10 nov 2018 alle 00:02 Matheus Marchini <
notifications@github.com> ha scritto:
… Implementing a wrapper on HTTPParser will be tricky 🤔. Do we really need
to reuse HTTPParsers though? I changed the max amount of parsers in the
FreeList at to 0, which forces Node.js to always create a new parser, and
our benchmarks don't show significant regressions:
confidence improvement accuracy (*) (**) (***)
http/bench-parser.js n=100000 len=16 -2.47 % ±3.05% ±4.07% ±5.34%
http/bench-parser.js n=100000 len=32 -1.58 % ±3.74% ±4.98% ±6.48%
http/bench-parser.js n=100000 len=4 -0.02 % ±4.74% ±6.31% ±8.22%
http/bench-parser.js n=100000 len=8 -0.94 % ±3.44% ±4.58% ±5.96%
Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case there are 4 comparisons, you can thus
expect the following amount of false-positive results:
0.20 false positives, when considering a 5% risk acceptance (*, **, ***),
0.04 false positives, when considering a 1% risk acceptance (**, ***),
0.00 false positives, when considering a 0.1% risk acceptance (***)
[image: compare-plot]
<https://user-images.githubusercontent.com/4048656/48292582-c08f1b00-e42f-11e8-858d-a38f762a5be5.png>
(I might be running the wrong benchmarks though. Are there any other
recommended benchmarks I should run?)
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#248 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AADL4x8gQWOahwr1PvostXXUaOMNCBuPks5utgmYgaJpZM4Xru28>
.
|
That's what I was thinking. Also, I don't think there would be any difference between removing the reuse and wrapping HTTPParse (we would need to allocate the wrapper every time anyway). |
I think the main difference is that a wrapper object would be a simple javascript object linked to HTTPParser and this link is cut once the parser is moved into the freelist whereas a HTTPParser object has a native part attached so it's more heavy. |
As discussed in nodejs/diagnostics#248 and nodejs#21313, reusing HTTPParser resource is a blocker for landing `require('async_hooks').currentAsyncResource()`, since reusing an async resource interanlly would make it infeasible to use them reliably in WeakMaps. Two suggestions came up: have a wrapper around the HTTPParser which we would use as the async resource, or stop reusing HTTPParser in our HTTP server/client code. This commit implements the latter, since we have a better GC now and reusing HTTPParser might make sense anymore. This also will avoid one extra JS->C++ call in some cases, which should improve performance for these cases.
Change resource being used, previously HTTParser was being reused. We are now using IncomingMessage and ClientRequest objects. The goal here is to make the async resource unique for each async operatio Refs: nodejs#24330 Refs: nodejs/diagnostics#248 Refs: nodejs#21313 Co-authored-by: Matheus Marchini <mat@mmarchini.me>
Change resource being used, previously HTTParser was being reused. We are now using IncomingMessage and ClientRequest objects. The goal here is to make the async resource unique for each async operatio Refs: #24330 Refs: nodejs/diagnostics#248 Refs: #21313 Co-authored-by: Matheus Marchini <mat@mmarchini.me> PR-URL: #25094 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
As discussed in nodejs/diagnostics#248, nodejs#21313 and https://docs.google.com/document/d/1g8OrG5lMIUhRn1zbkutgY83MiTSMx-0NHDs8Bf-nXxM/preview reusing the resource object is a blocker for landing a resource based async hooks API and get rid of the promise destroy hook. This PR ensures that HttpAgent uses the a new resource object in case the socket handle gets reused.
Besides the reuse of
For the first one I created nodejs/node#27581 to avoid the reuse. Depending on the result of this one I can create one more to avoid the reuse of |
As discussed in nodejs/diagnostics#248, #21313 and https://docs.google.com/document/d/1g8OrG5lMIUhRn1zbkutgY83MiTSMx-0NHDs8Bf-nXxM/preview reusing the resource object is a blocker for landing a resource based async hooks API and get rid of the promise destroy hook. This PR ensures that HttpAgent uses the a new resource object in case the socket handle gets reused. PR-URL: #27581 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
As discussed in nodejs/diagnostics#248, #21313 and https://docs.google.com/document/d/1g8OrG5lMIUhRn1zbkutgY83MiTSMx-0NHDs8Bf-nXxM/preview reusing the resource object is a blocker for landing a resource based async hooks API and get rid of the promise destroy hook. This PR ensures that HttpAgent uses the a new resource object in case the socket handle gets reused. PR-URL: #27581 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
This issue is stale because it has been open many days with no activity. It will be closed soon unless the stale label is removed or a comment is made. |
@Flarna is the FileHandleReadWrap still reused? If so I suggest creating a separate issue for it on nodejs/core and closing this one. |
Reuse of FileHandleReadWrap should be fixed by nodejs/node#31972 |
During the WG meeting today we discussed that It would be good to meet and unblock the topic of async hooks / promise hooks performance. (#188).
Context:
Here's a doodle: https://doodle.com/poll/fqkzvw929ueys2u9 I want to be able to get at least @hashseed @mcollina @AndreasMadsen to be able to attend. Please mark your availability by Friday Oct 19 and I will get a deep dive discussion scheduled.
The text was updated successfully, but these errors were encountered: