Replies: 3 comments 1 reply
-
Kinda. JS/TS runs always single threaded. However, many things that happen under the hood, like network and IO activity are handled by different "system" threads in the Deno runtime. So your code does utilize some multithreading although the actual JS/TS itself runs single threaded. People do often underestimate how light, fast, and powerfull this superficially single threaded async code can be. Well implemented async runtime does have great level of concurrency, even though there is no parallel execution as folks typically understand it. For many typical web server tasks, this can be more efficient than true multithreading. If your workload is more IO/database/network heavy, then you might be better off sticking to the "default" async execution, which is technically single threaded kinda, but can do a lot of stuff concurrently. Oftentimes more than true multithreaded code, since there is all kinds of additional overhead involved in orchestrating parallel threads. To actually, explicitly run JS/TS in a multithreaded way, you can use Web workers. Some modules or libraries you use may already do that under the hood. Actual parallel execution using Web workers can be great for some workloads. Those are typically CPU-heavy or math-heavy blocking workloads like image processing. This is mostly the same in both Deno and Node. |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for your detailed answer. As I would like to work some upload tasks and every IO is blocking I would prefer to make it in dedicated worker. I expect you mean this https://docs.deno.com/runtime/manual/runtime/workers and https://examples.deno.land/web-workers. QuestionShould I switch to the worker at that line CodeMy code is below and I call it with this line. The curl command is after the code 😃 . deno run --allow-env --allow-net --allow-write first-steps/http_server.ts import { Server } from "https://deno.land/std@0.204.0/http/server.ts";
import { v1 } from "https://deno.land/std@0.204.0/uuid/mod.ts";
const handler = async (_request: Request): Promise<Response> => {
console.log(_request);
console.log(v1.generate());
const formData = await _request.formData();
const file = formData.get("myFile") as File | null;
console.log(file);
if (file) {
try {
const reader = file.stream().getReader();
const result = await reader.read();
if (result.value) {
const { writable } = await Deno.open(`tmp/${file.name}`, {
write: true,
create: true,
});
file.stream().pipeTo(writable);
}
} catch (e) {
console.error(e);
}
}
// some more logic
const resp = await fetch("https://api.github.com/users/denoland", {
// The init object here has a headers object containing a
// header that indicates what type of response we accept.
// We're not specifying the method field since by default
// fetch makes a GET request.
headers: {
accept: "application/json",
},
});
return new Response(resp.body, {
status: resp.status,
headers: {
"content-type": "application/json",
},
});
};
const server = new Server({ handler });
console.log("server listening on http://localhost:4505");
if ( Deno.env.get("TLS_KEY") ){
const listener = Deno.listenTls({
hostname: "127.0.0.1",
port: 443,
transport: "tcp",
cert: Deno.readTextFileSync("./server.crt"),
key: Deno.readTextFileSync("./server.key"),
});
await server.serve(listener);
} else {
const listener = Deno.listen({ port: 4505 });
await server.serve(listener);
} Curlcurl -vF myFile=@first-steps/http_server.ts \
-H'Content-Type: multipart/form-data' http://localhost:4505/ |
Beta Was this translation helpful? Give feedback.
-
Not sure what you mean by "every IO is blocking". IO in Deno is usually async, which means your JS/TS code is free to serve for example other requests while one request or any other async call is waiting for IO. When you await something in a serve handler, that particular response is effectively "blocked" until the promise is resolved, but meanwhile, Deno is free to continue executing other async tasks, like serving other requests in the queue. It does not block all of your code. By quick look, all of your code here seems to be reasonably async, and using async streams. I suspect you wouldn't get much benefit from moving any of it to a worker thread. The code above should already be able to handle many, many concurrent requests with ease. I say "suspect" mainly because I'm not exactly sure how _request.formData() internally works, more on that below.
If there is any significant blocking happening, it would probably happen in the await _request.formData(). If that method internally reads all of the request body and parses it all at once to extract the uploaded files, then that would be a problem both for memory consumption and blocking the event loop for a significant period of time. If it's smart enough to create file streams dynamically in an async manner, then all good, you should be able to handle multiple requests concurrently even though it's technically single threaded. I'm guessing it's the latter since most everything in Deno tends to be nicely async in that manner. Maybe someone more knowledgeable can chime in on that. |
Beta Was this translation helpful? Give feedback.
-
Hi.
I'm new to deno and ask me if it's multi threaded for TS/JS Workload as far as I know is node single threaded.
Beta Was this translation helpful? Give feedback.
All reactions