uNetworking / uWebSockets.js

μWebSockets for Node.js back-ends :metal:
Apache License 2.0
8.09k stars 578 forks source link

Uncaught TypeError: domain.enter is not a function in REPL mode (uNetworking/uWebSockets.js#v17.3.0, Node.js v12.16.1) #282

Closed amitv87 closed 4 years ago

amitv87 commented 4 years ago

Run the below mentioned code from node in REPL mode

const uWS = require('uWebSockets.js');

const HTTP_LISTEN_PORT = 9001

function httpHandler(res, req) {
  res.end('Nothing to see here!');
}

const server = uWS.App();
server.any('/*', httpHandler);
server.listen(HTTP_LISTEN_PORT, function(success){
  console.log(success ? 'Listening to port' : 'Failed to listen on port', HTTP_LISTEN_PORT);
});

Node throws exception when server.listen() is invoked

Welcome to Node.js v12.16.1.
Type ".help" for more information.
> require('./test.js')
Uncaught TypeError: domain.enter is not a function
    at topLevelDomainCallback (domain.js:136:12)
    at Object.<anonymous> (/Volumes/awsm/uwsApp/test.js:11:8)
    at Module._compile (internal/modules/cjs/loader.js:1158:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1178:10)
    at Module.load (internal/modules/cjs/loader.js:1002:32)
    at Function.Module._load (internal/modules/cjs/loader.js:901:14)
    at Module.require (internal/modules/cjs/loader.js:1044:19)
    at require (internal/modules/cjs/helpers.js:77:18)
> (node:99538) [DEP0097] DeprecationWarning: Using a domain property in MakeCallback is deprecated. Use the async_context variant of MakeCallback or the AsyncResource class instead.
> process.versions
{
  node: '12.16.1',
  v8: '7.8.279.23-node.31',
  uv: '1.34.0',
  zlib: '1.2.11',
  brotli: '1.0.7',
  ares: '1.15.0',
  modules: '72',
  nghttp2: '1.40.0',
  napi: '5',
  llhttp: '2.0.4',
  http_parser: '2.9.3',
  openssl: '1.1.1d',
  cldr: '35.1',
  icu: '64.2',
  tz: '2019a',
  unicode: '12.1'
}
>
ghost commented 4 years ago

Thanks, will have a look

ghost commented 4 years ago

Great find, it is fixed in https://github.com/uNetworking/uWebSockets.js/commit/4be2f2bfc2d508dd4b90933fe226c7136e3501bf

However, if you actually go ahead and make a request with your browser it now fails like so:

> domain.js:129
    domain.enter();
           ^

TypeError: domain.enter is not a function
    at topLevelDomainCallback (domain.js:129:12)

I haven't kept up to date with what the Node.js crazy people have been up to, so I don't really get this whole async_context nonsense they introduced. I just pass {0, 0} as async_context - obviously it doesn't work with domains, but wasn't domains deprecated or something?

ghost commented 4 years ago

Okay, you're supposed to init an async_context for every callback or collection of callbacks you might call "async" in the future.

Like so:

node::async_context async_context = node::EmitAsyncInit(args.GetIsolate(), args.Holder(), "app yo", node::AsyncHooksGetTriggerAsyncId(args.GetIsolate()));

Where async_context is two doubles. This is done once, up front.

This solves the REPL case, however just like anything the Node.js team touches, this horrendously cuts performance to hell:

In REPL mode with async_context:

Running 10s test @ http://localhost:9001
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   180.44us   55.69us 641.00us   86.73%
    Req/Sec    27.60k     3.49k   33.09k    63.37%
  554657 requests in 10.10s, 41.79MB read
Requests/sec:  54917.63
Transfer/sec:      4.14MB

In REPL mode with EXPERIMENTAL_FASTCALL:

Running 10s test @ http://localhost:9001
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    95.35us   32.05us   0.88ms   83.37%
    Req/Sec    51.90k     6.45k   65.34k    70.30%
  1043230 requests in 10.10s, 78.60MB read
Requests/sec: 103294.77
Transfer/sec:      7.78MB

That is a loss of 48% performance. Seriously what the fuck are they even doing?

Meanwhile in Python land:

Running 10s test @ http://localhost:3000
  2 threads and 10 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    80.46us   28.18us 326.00us   80.75%
    Req/Sec    61.31k     7.61k  114.14k    75.12%
  1225572 requests in 10.10s, 84.15MB read
Requests/sec: 121353.90
Transfer/sec:      8.33MB

Some 120% higher..

ghost commented 4 years ago

Okay I'm not going to support REPL mode right now, or in the future unless someone forces me to. At least I now know what needs to be done to support it, should I have to.

Thanks for reporting.

amitv87 commented 4 years ago

Got it, thanks for the explanation.