I got 10x faster performance from this simple Node.js refactor

Поделиться
HTML-код
  • Опубликовано: 29 окт 2024

Комментарии • 168

  • @WebDevCody
    @WebDevCody  2 месяца назад +13

    If anyone wants to try rewriting this and go and rust so I can do a performance benchmark against them. I’ll be really happy to do another video about that. I just don’t know if I have the time to try to re-implement this whole canvas logic and go.

    • @neociber24
      @neociber24 2 месяца назад

      Rust have the "image" crate, if you have never written Rust you are gonna enjoy it a lot, or die because the borrow checker.

    • @thales-maciel
      @thales-maciel 2 месяца назад

      I made one, I tried to comment it here two times, but it keeps getting deleted. thales-maciel/opt101

  • @SeibertSwirl
    @SeibertSwirl 2 месяца назад +89

    Mwaahahahaha I’m baaaAAAAaaaack!!!! Love you babe! You’re doing great!

  • @zi_t
    @zi_t 2 месяца назад +12

    6:39 our world needs more of this teaching style.
    definitely underrated teaching strategy: “i am assuming you got it, but i am going to pretend you don’t got it”
    *then proceeds to draw super intuitive diagram with explanation
    i love it!

    • @WebDevCody
      @WebDevCody  2 месяца назад +2

      Thanks man yeah, I’ll be honest. Sometimes it’s hard to teach when you don’t know the skill level of your audience so I just kind of throw things at the wall and hopefully it’s good.

    • @zi_t
      @zi_t 2 месяца назад

      @@WebDevCody it is, really, good. i appreciate the content! been trying really hard to understand the "black box" of how the tools i use work (i.e. react, nextjs, node, supabase/postgres)

  • @cubeddu
    @cubeddu 2 месяца назад +2

    This was fun! I liked the fact that there was some improv incorporated into it and the playing around to skew better performance was solid!

  • @anthonyortiz7924
    @anthonyortiz7924 2 месяца назад +31

    In this day and age I am frustrated that we're still stuck in this message based worker dispatching single-threaded environment rather than use shared memory thread marshalling in a multi-threaded environment.

    • @perc-ai
      @perc-ai 2 месяца назад +4

      this is the state of web dev in 2024 everyone still using JS ...

    • @waleedbukhari8988
      @waleedbukhari8988 2 месяца назад

      What makes js good is what makes it bad.

    • @perc-ai
      @perc-ai 2 месяца назад +1

      @@waleedbukhari8988 just stop bro lol. It's not a language that should even exist in 2024 given the current state of technology

    • @hamm8934
      @hamm8934 2 месяца назад

      @@waleedbukhari8988 I used to be very charitable to javascript for many years, but recently I haven't had to use it much (I've just been continue to use Go and dotnet) and honestly going back to javascript for the first time in over 6 months has really shown me how brittle and hacky javascript is.

    • @personofsomething6205
      @personofsomething6205 2 месяца назад

      Same with python lol ​@perc-ai

  • @michellefelix1355
    @michellefelix1355 2 месяца назад +3

    Very nice video 👌🏻
    I specially loved the final part where you start optimizing.
    On first thought I was expecting that the sequential write operation would be taking a lot of time, but it turned out not being the case (A good reminder to check time and focus on the big offenders 👍🏻)

  • @AnshumanBhardwaj
    @AnshumanBhardwaj 2 месяца назад

    Love this format of videos. Straight into problem solving and easy wins once you get them. Also, interesting that you point out the diminishing rewards for such approach as well. 👏👏

  • @jly_dev
    @jly_dev 2 месяца назад +9

    People typically dislike microservices because of the added complexity, and to an extent I agree. That being said, using Node for my main server, and offloading long-running or CPU-bound operations to a Go microservice is a solid pattern. Node excels in I/O and in flexibility, and Go excels at perfomance.

    • @vinialves12362
      @vinialves12362 2 месяца назад

      What do you mean Node excels in I/O?

    • @jly_dev
      @jly_dev 2 месяца назад

      @@vinialves12362 The non-blocking async model and incredibly fast/flexible JSON (de)serialization

    • @naughtiousmaximus7853
      @naughtiousmaximus7853 2 месяца назад +4

      Or use Typescript knowledge to learn C# and you can do all this in one language.

    • @jly_dev
      @jly_dev 2 месяца назад

      @@naughtiousmaximus7853 Fair, C# and Kotlin are growing on me. That being said, TS/JS are more flexible and Go is faster / simpler / uses less memory

    • @paarma1752
      @paarma1752 2 месяца назад

      ​@@naughtiousmaximus7853exactly what I've been doing for the last 10 years ❤ I try to stay away from any server side JS implementations as much as possible, but sometimes man's gotta do what man's gotta do. Go is a fun language though and I've used it for a bunch of algorithmic stuff. But for backend it's just not powerful enough as a language. Like no LINQ, inferior generics, no expression trees... imperative-only code is surely simple, but it's also jumpy and bug-prone, as you have to use a lot of statements to achieve you goal - let's say - to build a projection from a slice. Whereas in C# it's just a single functional (multi)line of LINQ proceeding from top to bottom.

  • @modernsanskari4398
    @modernsanskari4398 2 месяца назад +5

    Awesome, golang may work good here. Pls make a video on comparison between golang n node js/any js framework or serverless way to do it.
    Like what mental model we should have do IO intensive and for CPU intensive works.

  • @JarheadCrayonEater
    @JarheadCrayonEater 2 месяца назад

    I've used that frequently over the years when I need several node-red instances running at the same time for different parts of my application.
    Worker threads with communication to/from the main process to track states and share data.
    Makes for a really flexible server with dynamic processes.

  • @jalbers3150
    @jalbers3150 2 месяца назад +15

    I'd like to see node workers vs single threaded Go

    • @hamm8934
      @hamm8934 2 месяца назад

      its not even close

    • @Ss-zg3yj
      @Ss-zg3yj 2 месяца назад

      @@hamm8934 I am 100% sure multi-thread Node will beat any single-thread. stop clowning

    • @hamm8934
      @hamm8934 2 месяца назад +5

      @@Ss-zg3yj prime has a video of this. Its not even close. Controlling for hardware and code structure parity, Go is >60x faster than node, especially in long running services with high active clients due to node’s over reliance on the heap.
      Node is honestly so slow unfortunatey

    • @slipknot1943
      @slipknot1943 2 месяца назад

      Im mean its all about what works for you. Its much easier to write everything in js but it has its downsides. As does go. Pick your poison

    • @Ss-zg3yj
      @Ss-zg3yj 2 месяца назад

      @@hamm8934 prime hates JS. he also likes HTMX 🤡

  • @k98killer
    @k98killer 2 месяца назад

    "I'm gonna just keep adding code until it works" is a very relatable sentence lol

  • @RasmusSchultz
    @RasmusSchultz 2 месяца назад +1

    instead of doing round-robin, I would try something like promise-limit at the top instead - in your particular case, you may be doing okay, because every task happens to be the same amount of work, but ideally you would want to launch a new task as soon as any other task is finished.

  • @mitchellwintrow4495
    @mitchellwintrow4495 2 месяца назад

    Thanks for this man! I love your content.

  • @devpatel8109
    @devpatel8109 2 месяца назад

    Good job mann.....
    Love the teaching style......

  • @stevanfreeborn
    @stevanfreeborn 2 месяца назад

    This was really helpful! Thanks for sharing.

  • @thirtykey
    @thirtykey 2 месяца назад +6

    the workers api is one of my least favorite things about node. go is soooo good in this regard

  • @pbdivyesh
    @pbdivyesh 2 месяца назад

    Amazingly awesome! I generally don't like the video but here I've

  • @mihajlosupic
    @mihajlosupic 2 месяца назад

    From start I new I know this but you made a great video and I enjoyed watching it

  • @Cuca-hn3md
    @Cuca-hn3md 2 месяца назад +1

    i didnt knew the concept of semaphores before, i used to solve those problems with mutex and queues.

  • @codestacklab
    @codestacklab Месяц назад

    great work

  • @poznianski
    @poznianski 2 месяца назад +9

    two new things for me:
    1. logs slow down the app
    2. first time saw console.time and console.timeEnd
    interesting video overall, good job

    • @Ss-zg3yj
      @Ss-zg3yj 2 месяца назад

      you must be proud of own incompetence, if you saying this out loud lol

    • @charleschukwuemeka8482
      @charleschukwuemeka8482 2 месяца назад

      ​@@Ss-zg3yjWTF....

  • @sanasarjanjughazyan9861
    @sanasarjanjughazyan9861 2 месяца назад

    One more potential improvement can be decreasing with for the drawImage based on t (shift), I didn’t use Canvas, so not sure weather it’ll optimize it for you, but basically you don’t need to draw every single pixel for every frame.

  • @ichigokuro3986
    @ichigokuro3986 2 месяца назад +2

    @Web Dev Cody Why didnt you use the cluster module?

  • @dkr91
    @dkr91 2 месяца назад +2

    Workers usually run on servers, thus having it as a .JS is fine? If you would like to write it in TS, you would need to compile it before being able to use it on the server. For this reason I do normally see that the worker file is just a .js file to prevent having to implement more complexity

    • @dreamecho100
      @dreamecho100 2 месяца назад

      JSDoc?

    • @thirtykey
      @thirtykey 2 месяца назад

      I ran into this exact issue. I was writing in TS and compiling to single file in a docker image. Had to change it so it keeps the file structure and guarantees I know where the file will be. Atrocious.

  • @kevs3654
    @kevs3654 Месяц назад

    Single thread is the reason why we like HPA on kubernetes :)

  • @nowayicommented1314
    @nowayicommented1314 2 месяца назад

    __dirname is not defined because you’re in ESM.
    Also you could use TS for the worker by transpiling the worker before initializing it

  • @GoodwillHeadset
    @GoodwillHeadset 2 месяца назад

    Is it possible to move the 'frame' of the canvas rather than drawing the same image over and over? Also I would be careful at then end making the canvas a shared resource without some form of lock on it.

    • @GoodwillHeadset
      @GoodwillHeadset 2 месяца назад

      context.translate(x,y)? Not sure if that re-draws but may be faster.

    • @WebDevCody
      @WebDevCody  2 месяца назад

      yeah I could try that

  • @tete0148
    @tete0148 2 месяца назад +1

    Doesn't sharing the canvas allow for race conditions between a ctx clear and a context ?

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      All workers use its own canvas

  • @ddavid8888888
    @ddavid8888888 2 месяца назад +1

    Your keyboard sounds sick, can you please share what keyboard is it?

  • @hell0kitje
    @hell0kitje 2 месяца назад

    hi whats ur vsc theme?

  • @oryankibandi3556
    @oryankibandi3556 2 месяца назад +2

    Might it be beneficial to avoid terminating workers and instead reuse them to avoid the overhead of creating and terminating?

    • @WebDevCody
      @WebDevCody  2 месяца назад

      I keep them alive on the real app, this was just an example

    • @maxmaximus7773
      @maxmaximus7773 2 месяца назад

      @@WebDevCody can you provide some code example of how you reuse the workers on the real app please?

    • @WebDevCody
      @WebDevCody  2 месяца назад +2

      @@maxmaximus7773 just don’t terminate them. They’ll remain running and listening for messages, so just keep sending messages to them

  • @ugurcodes
    @ugurcodes 2 месяца назад

    I love workers haven't been found chance to use them in my projects but looking forward to it. If I'm not mistaken, this worker will be run in the server right? I guess you are doing some kind of reels/tiktok creation saas? what do you think about using web workers so that this process will be done in the user's browser? Is it too much load for the users?
    any way, you are truly inspiration to me, love your videos, keep them coming!

    • @WebDevCody
      @WebDevCody  2 месяца назад

      I don’t know if it’s possible to do in the browser, but it might be that’s an interesting concept. I should look into yeah right now it’s for building out videos and TikTok shorts and stuff. I’m just trying to play around with. I have some fun though.

  • @salman0ansari
    @salman0ansari 2 месяца назад

    i would love to see a video about doing the same job in go

  • @jack171380
    @jack171380 2 месяца назад

    Be careful, shared mutable state is very dangerous

  • @Krawcu_
    @Krawcu_ 2 месяца назад

    General question, i dont have any experience in backend scaling, but what do you think of using your backend as a docker image and running a bunch of them all at once with load balancer on a single VM? Is it a good pattern? (is it a microservice? idk the definition of it really) 💀

    • @WebDevCody
      @WebDevCody  2 месяца назад

      If I need scale I’d run my docker container on a lambda and give it 10gb of memory. It should work just fine

    • @gamingbud926
      @gamingbud926 2 месяца назад

      Was just looking into this as I am nearing the launch stages of an app I've been working on. In Node.js, you can use Clusters. These are sort of like threads, but they are individual Node.js processes. When your app starts, you can spin up x amount of clusters of your API in order to consume all the cores on the machine. Beyond that, you'd probably need to spin up new servers.

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      @@gamingbud926 little different from what I’m trying to do here. That’s scaling a single machine to handle more api requests, I’m scaling a single endpoint to do its cpu intensive tasks faster

  • @blizzy78
    @blizzy78 2 месяца назад

    so you're basically recreating Goroutines in JavaScript

    • @WebDevCody
      @WebDevCody  2 месяца назад

      Not recreating, this is built into node

    • @blizzy78
      @blizzy78 2 месяца назад

      @@WebDevCody right, I didn't mean that in the literal sense

  • @codestacklab
    @codestacklab Месяц назад

    hi cody , i have seen alot of your content , and it's cool , i also know js,ts,dmbs, ruby,go,mono repos ,git , devops ,
    with great proficiency, i am also planning a side project , can you make a full video on like how to perfectly release a product?.
    i can make a full production ready product , on a validated idea.
    i hope you will make that video.

  • @virtual5754
    @virtual5754 2 месяца назад

    My biggest question is how do you have 11 cores? Did they forget to put 1 more core into your processor?

    • @WebDevCody
      @WebDevCody  2 месяца назад

      Idk it’s a mac book

    • @ba8e
      @ba8e 2 месяца назад

      @@WebDevCody They have to be brave!

  • @chepossofare
    @chepossofare 2 месяца назад

    While i love your optimizations, working with js seems to try to get supercar performances with a station wagon.

  • @AhmadMughal1
    @AhmadMughal1 2 месяца назад

    Conceptually would this be considered similar to how golang handles routines and has channels which you can listen on if a routine is finished.
    From my understanding (i might be wrong) golangs compiler does not spin actual threads but instead creates a lighter version you can say.
    Isn't this similar in that sense?
    And last thing is why are they still pushing the single thread thing if they already have this implemented to some extent is beyond me.

    • @WebDevCody
      @WebDevCody  2 месяца назад

      the go runtime has a built in scheduler, so yes go routines are not always separate dedicated threads, but they are processed from a thread group I believe

  • @asd848
    @asd848 2 месяца назад

    What VS Code theme is that?

    • @WebDevCody
      @WebDevCody  2 месяца назад

      Bearded theme fest web dev cody

  • @dennisloska
    @dennisloska 2 месяца назад +1

    Using ArrayBuffer instead of the canvas api might be even faster.

  • @JohnLovell-FTW
    @JohnLovell-FTW 2 месяца назад

    What about "writing" the image to a memory array and not to disk?

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      That is a possible thing I could look into. There is a way to stream to ffmpeg. All of these images can eat up a lot of memory for longer videos, so I felt it was safer to put them on disk until ffmpeg kicked off

  • @zhasulanserikov9890
    @zhasulanserikov9890 2 месяца назад

    how about removing consoles ? will it change a little? just curios EDIT: ignore, you did it in last minutes :)

  • @efronic
    @efronic 2 месяца назад

    Idea - Maybe write the same app with Go/Rust and see how the performance differs?

    • @hamm8934
      @hamm8934 2 месяца назад

      Primeagen had a video like this with websockets

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      Yeah, I wanna try if I get time

    • @neociber24
      @neociber24 2 месяца назад

      Pretty sure may be massively faster in a compiled language

  • @MAK_007
    @MAK_007 8 дней назад

    We need to stop sayin that nodejs is single threaded. Nodejs is not single threaded anymore
    Every programming language in this world will use single thread by default unless and until you actually import and use the respective multithreading libraries provided by those languages and we do the same thing for nodejs by using multithreading library.
    During the early days of javascript there were no worker threads hence it was called single threaded at that time. But thats the case anymore. Its multi threaded now just like any other language

  • @cianwalker1829
    @cianwalker1829 2 месяца назад +1

    “It’s not going to be that efficient” - does its basic asynchronous architecture not kind of negate its single-threadedness to a large extent?

    • @WebDevCody
      @WebDevCody  2 месяца назад +2

      only for IO related tasks such as network requests, reading / writing to files. Something like drawing to a canvas which is very cpu intensive it will not

    • @cianwalker1829
      @cianwalker1829 2 месяца назад

      @@WebDevCody ah yes HTTP aside, actually processing things - JS shouldn’t REALLY be used for this if possible but suppose front end devs have to?

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      @@cianwalker1829 why not? If it does what I need but take maybe 5 seconds longer, why would I introduce more complexity on a project by bringing in yet another language and ecosystem when node was able to solve the problem? If at some point I really need to squeeze out performance, then sure I’d spent a month learning go and hoping they have packages already already for me to do canvas operations like this. But that’s also a risk because I may spend all this time just to find using a faster language wasn’t even that much faster, and now I’ve lost a month of dev time

    • @cianwalker1829
      @cianwalker1829 2 месяца назад

      @@WebDevCody sorry yes I meant what I said as a question more than a statement.

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      @@cianwalker1829 oh, to answer your question then, node works fine and runs millions of services around the world currently.

  • @MikeNugget
    @MikeNugget 2 месяца назад

    SQLite reads and writes small blobs (for example, thumbnail images) 35% faster¹ than the same blobs can be read from or written to individual files on disk using fread() or fwrite()

    • @WebDevCody
      @WebDevCody  2 месяца назад

      Might be worth looking into that. The issue is with ffmpeg I point it to a directory and it combines all my images into a video. I’d need to look into streaming into ffmpeg I think

  • @HeRvAsH93
    @HeRvAsH93 2 месяца назад

    You could probably shave off some time if you removed some of the most frequent console logs. Would be interesting to see the perf improvement if you did. Great vid tho, cheers

    • @HeRvAsH93
      @HeRvAsH93 2 месяца назад

      Should have watched till the end before commenting lol

  • @anothermouth7077
    @anothermouth7077 2 месяца назад

    Ugh i hate this in nodejs. I once had to process a CSV which turned out to be machine intensive and then we had to spawn workers and used Bull for queuing, bad experience

  • @derekpowersblight
    @derekpowersblight 2 месяца назад

    Hell it's about time... 😂

  • @IlyaVernigora
    @IlyaVernigora 2 месяца назад

    Nodejs is NOT “single threaded” for quite a long time.

    • @WebDevCody
      @WebDevCody  2 месяца назад

      They use a thread pool under the hood for io. We all know what I’m talking about.

  • @lidinzx
    @lidinzx 2 месяца назад

    woow multithread for node is so complicated, in go is really simple with channels

  • @iercan1234
    @iercan1234 2 месяца назад

    thx

  • @vinialves12362
    @vinialves12362 2 месяца назад +1

    That's cursed API

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      @@vinialves12362 yeah it’s a bit rough

  • @oreqr
    @oreqr 2 месяца назад +1

    Try running it with a bun

  • @rakeshpradhan1999
    @rakeshpradhan1999 2 месяца назад

    Great 👍

  • @sachinkhatri1077
    @sachinkhatri1077 2 месяца назад

    Man please mention theme name. The theme is really beautiful ❤

    • @WebDevCody
      @WebDevCody  2 месяца назад

      bearded theme feat web dev cody

    • @sachinkhatri1077
      @sachinkhatri1077 2 месяца назад

      @@WebDevCody is this available for download? I want this theme for my vs studio. Edit:- found it thank you so much

  • @fabriziotofanelli
    @fabriziotofanelli 2 месяца назад

    You should start to watch some Erick Wendel's videos... One of his videos is exactly about this

    • @WebDevCody
      @WebDevCody  2 месяца назад

      I’ll try to remember to check it out

  • @KAPILKUMAR-rl4yi
    @KAPILKUMAR-rl4yi 2 месяца назад

    very nice video, can I get the source code please to do some more analysis

  • @Ss-zg3yj
    @Ss-zg3yj 2 месяца назад

    I guess you could just use Bull at that point.

  • @ajzack983
    @ajzack983 2 месяца назад

    fun vid

  • @vaaaaaas
    @vaaaaaas 2 месяца назад

    Web devs in 2024 suddenly discovering parallelism. Wait until you hear about not blocking on IO.

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      I invented concurrency

  • @bigspidey
    @bigspidey 2 месяца назад

    Nice theme what's the name pls

  • @yante7
    @yante7 2 месяца назад

    well yeah concurrency is usually a lot faster than a loop

    • @WebDevCody
      @WebDevCody  2 месяца назад

      Who would have thought?! Usually I just overclock my ec2 instances so the electrons fire faster!

  • @bokunochannel84207
    @bokunochannel84207 2 месяца назад +1

    semaphore of 1 doesn't make any sense imo. semaphore of 1 s not semaphore. but a mutex.
    i'm not a js developer. but i know some js stuff. did you "fan out" the job to the workers?

    • @WebDevCody
      @WebDevCody  2 месяца назад

      I round robin to the workers. Gpt calls this a binary semaphore. Whatever it’s called, it helps limit work in progress and that’s all I care about.

    • @bokunochannel84207
      @bokunochannel84207 2 месяца назад

      ​@@WebDevCody you haven't reach the ceiling yet, also need a bit of work with the graph.

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      @@bokunochannel84207 ceiling for the workers being able to process more? Not sure what you mean

    • @wwefan9391
      @wwefan9391 2 месяца назад

      ​@@WebDevCodyyea i mean, a binary semaphore is basically just a mutex lol

  • @tusharphb6596
    @tusharphb6596 2 месяца назад

    Use mjs for worker

  • @lengors7327
    @lengors7327 2 месяца назад

    Nowhere near 10x times faster 😅
    Anyways, you could optimize it by batching all the work on the main thread and then send a single message to each of the workers in one go. Then for terminate you just need to receive the same amount of messages as there are workers

    • @WebDevCody
      @WebDevCody  2 месяца назад

      wait, it took 50 seconds without this change, and ran in under 5 seconds after the change. what's 50 / 5? 10 🤣

    • @lengors7327
      @lengors7327 2 месяца назад

      @@WebDevCody Was talking only about moving the work to workers, stopped after that due to the title assumed it was the only optimization you were going to do. My bad. I"m sorry.
      That said, it's still not 10x faster 😅. You started with 43 (not 50) and ended with 5.3 (not counting the runs without logs because that effectively gives you a different output), so that's about 8x times faster.

    • @WebDevCody
      @WebDevCody  2 месяца назад

      @@lengors7327 😜 you got me, I might have done some rounding

  • @pinoniq
    @pinoniq 2 месяца назад +1

    this only works if you have a cpu that has multiple threads. your average 1vcpu vps wont work here

  • @SeibertSwirl
    @SeibertSwirl 2 месяца назад +4

    FIRST!!!!

  • @salman0ansari
    @salman0ansari 2 месяца назад

    just use a multithreaded language at this point
    this is unnecessary complex

    • @WebDevCody
      @WebDevCody  2 месяца назад

      You don’t think bringing in another language in another ecosystem is not adding its own complexity?

  • @729usbow
    @729usbow 2 месяца назад

    Just give up, the specific stack you are using is not made for performance, accept your fate

  • @Lorofol
    @Lorofol 2 месяца назад +1

    Would love to see you do this again with go channels/goroutines

  • @buu_mm6784
    @buu_mm6784 2 месяца назад

    Promise.all?

    • @WebDevCody
      @WebDevCody  2 месяца назад +1

      Doesn’t do anything for cpu intensive tasks. It only helps for IO bound operations.