Giter Club home page Giter Club logo

Comments (20)

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024 2

Making it automatic looks easiest. Then it would just work. And wrappers can remove all their header copying crap and always use the given Request object

from uwebsockets.js.

uasan avatar uasan commented on May 27, 2024 1

Those. if we call request.keep(), we can access the request object, in the following microtasks?

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

Internally it should be

uWS::HttpRequest* = uWS::HttpRequest*->makeDynamicClone();
uWS::HttpRequest*->freeDynamicClone();

it just makes 1 block with the headers and all

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

A wrapper is:

function myFetch(request) {
return new Response("hello");
}

app.get('*', (res, req) => {
if myFetch(req) returned Response then
res.end(the response)
else if returned void or unresolved promise
req.keep(); // moves uWS.HttpRequest from global to local, swaps the underlying ptr to makeDynamicCopy(), on GC calls freeDynamicCopy()
endif
});

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

Yes if you call keep() it would move from being a stack allocated thing to being dynamic and available until it gets GC:d. So it's a very simple function and wrappers would not need to copy out all headers one by done but can just keep the Request after calling keep() on it

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

But it's slow as heck, so the key here is to only do it if the first invocation of the CB does not return a Response or calls end. So the whole idea is: only use it for slow path

from uwebsockets.js.

uasan avatar uasan commented on May 27, 2024

I'm understood, thank you.

But the problem with all abstractions is that they usually do not know whether the request handler will be executed in the fast way or in the slow way, so the abstraction always chooses the slow way to be universal, so they will always call the keep method.

By what percentage does the response slow down if you always call the request method keep?

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

whether the request handler will be executed in the fast way or in the slow way

You don't need to know if it will be. You need to know if it was. Finding out if the request was ended is easy. That's the whole point of doing this after as a late stage slow path

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

The library could even do this automatically, but it would add a cost to all async handlers. But those are kind of costly either way

from uwebsockets.js.

uasan avatar uasan commented on May 27, 2024

Here's a more realistic example of abstraction:

async function myFetch(request) {
  return await sql;
}

app.get('*', async (response, request) => {
  try {
    const result = await myFetch(request);
    response.end(result);
  } catch (error) {
    response.end(error);
  }
});

Comment from your example:

else if returned void or unresolved promise

There are misconceptions in this statement, the fact is that it is impossible to find out the state of a promise, whether it has resolved or not, such a promise interface, we can only wait for the result, so this is always the slow way and always calls the keep method

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

There is no misconception. The library knows perfectly well whether the Response has ended or not. Like said, async/await functions will always take the slow path for a number of reasons (in Node.js, the microtask queue is not drained immediately after a call into JS which is terrible for perf. but I don't care it is a Node.js problem and doesn't affect non-async functions)

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

Non-async functions like those in HelloWorld.js will end the request by calling Response.end() immediately and in this case there is no overhead since it never clones the request object

from uwebsockets.js.

uasan avatar uasan commented on May 27, 2024

The library knows perfectly well whether the Response has ended or not.

No, the point of abstractions is that the application code of the route handlers does not know anything about the implementation of the server, i.e. an asynchronous function that an abstraction calls never calls a response end, because this is the exclusive privilege of the abstraction, those. The response state after calling the handler will always be unfinished.

P.S.
If the application functions themselves will call the response end then there is no point in abstraction )

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

"the library" = uWS. It knows whether you responded or not

from uwebsockets.js.

uasan avatar uasan commented on May 27, 2024

Then the uWS should automatically call keep method for all asynchronous handlers, i.e. all asynchronous requests will be on the slow path, this will reduce the speed?

from uwebsockets.js.

porsager avatar porsager commented on May 27, 2024

I think what you mean @uasan is that you'd like an option to "not" copy the request if you know you will not use anything from it in some of your async handlers?

from uwebsockets.js.

uasan avatar uasan commented on May 27, 2024

Yes, it’s better that by default uWS doesn’t do something that can be expensive, I agree if copying is done only explicitly, through calling the keep method

from uwebsockets.js.

uNetworkingAB avatar uNetworkingAB commented on May 27, 2024

it could be negligible in comparison with async flow either way. needs benchmarking

from uwebsockets.js.

kartikk221 avatar kartikk221 commented on May 27, 2024

This is a great proposal and would significantly help performance for wrappers / libraries like hyper-express where currently, the headers and other request properties are always consumed from HttpRequest and cached locally. With the ability to instruct HttpRequest to live past the first sync execution, we could convert the properties into getters which then lazy initialize the neccessary data and consume it as needed.

As for the best way of implementing it, automatic is ideal but having a method like request.keep() along with a request.destroy() would be fine as well since it is very easy to know If a request will be handled asynchronously.

from uwebsockets.js.

kartikk221 avatar kartikk221 commented on May 27, 2024

You don't need to know if it will be. You need to know if it was. Finding out if the request was ended is easy. That's the whole point of doing this after as a late stage slow path

I am asssuming to automate this behavior, you will be checking to see whether a response was sent after the route handler returns? I use a similar trick here to determine whether I need to cork before sending a response with a boolean flag:
https://github.com/kartikk221/hyper-express/blob/f712634ed5648b9c91d34beb0a845ab95ff3c6a8/src/components/Server.js#L526-L530

One more thing that I thought of is wouldn't someone calling uWS.HttpResponse.onAborted(() => {}) be a strong indicator that they will handle the request in an asynchronous manner (slow path) hence keeping uWS.HttpRequest around in memory would be a safe bet?

from uwebsockets.js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.