My GraphQL Performance Problem

Поделиться
HTML-код
  • Опубликовано: 10 сен 2024
  • I ran into a performance problem related to GraphQL. I go through how I debugged and fixed it.
    Links from video:
    / 1212392789637521410
    news.ycombinat... ​

    ----
    Follow me online: voidpet.com/be...
    #benawad

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

  • @porgeet
    @porgeet 4 года назад +64

    Thanks for sharing, this type of content is extremely useful. Not many people share the process of figuring out a problem, very helpful. 10/10 would watch again.

  • @TheNewton
    @TheNewton 4 года назад +54

    tl;dw 10:40 overfetching fields & 11:12 type-graphql performance, optimized by lowering results fetched and using beta branch of type-graphql

  • @Frogquest
    @Frogquest 4 года назад +9

    I find these types of videos where you troubleshoot actual problems to be incredibly enlightening. I don't think there's enough of this type of content. Bravo! I didn't quite understand the connection to type-graphql though TBH and would love it if you explained that a little more. Really appreciate following along with your thought processes though.

    • @bawad
      @bawad  4 года назад +1

      I'm using type-graphql to create my graphql schema, so one thing it does is wrap all my resolvers in some type-graphql code. That code apparently has some problems

  • @pkop4
    @pkop4 4 года назад +45

    Points to one advantage of using Hasura, written in Haskel, and uses a meta-data engine that pre "compiles" types and queries, maps to efficient Postgresql queries...minimizing overhead/redundancy of both layers.

    • @uziboozy4540
      @uziboozy4540 4 года назад +3

      Didn't even know they did that under the hood.
      Maybe it's time to reconsider using Hasura instead of Prisma.

    • @cobalt2489
      @cobalt2489 3 года назад +1

      Or use diesel & actix with rust. To make your API goo BRRRRRRRR

  • @metropolis10
    @metropolis10 4 года назад +2

    Fantastic video. Thank you so much for showing step by step your debugging process of a problem. I always learn a ton when I watch someone else try to solve a problem!

  •  4 года назад +10

    Hey Ben, great video. Personally I think that one of performance issues is certainly the overfetching. You shoud fetch only data needed for search component, not for recipe detail. Excited to see performance difference while not overfetching :)

    • @bawad
      @bawad  4 года назад

      yeah that was certainly part of the problem

    • @cklee_
      @cklee_ 4 года назад

      @@bawad any way to lazy load the query for the recipe detail after the initial fetch for the search component?

    • @bawad
      @bawad  4 года назад

      @@cklee_ yeah that's what I'm planning on doing

    • @herohamp2
      @herohamp2 4 года назад +1

      What I did for one of my sites is launch the request to the load the data for a search result on over not on click, so that by the time the user clicks it has already been loaded and will be instant. That should keep the instant loads of recipes like shown here while reducing the graphql overhead

  • @Butcheren0
    @Butcheren0 10 месяцев назад

    Glad you figured it out. Facing a similar issue, our problem is that it is only occasionally slow without any perticular query seemingly causing it. This causes CPU to spike in our pods which again causes timeouts etc.

  • @scottamolinari
    @scottamolinari 4 года назад +8

    Great content. Please continue showing problem solving processes like this. I think it's more valuable than straight tutorials.
    Ah, and can you post in Twitter about what results you got once you pushed to production? (if not another video)? :)

    • @bawad
      @bawad  4 года назад +1

      will do

  • @MrEmanuelherrera
    @MrEmanuelherrera 4 года назад +1

    Thanks Ben for explaining and sharing the problem.

  • @alkismavridis1
    @alkismavridis1 4 года назад +4

    I think this is a very much library specific issue. GraphQL is a specification, not an implementation. There are lots of implementation libraries for it that target multiple programming languages and platforms. So, it would be more meaningful to say that this or that implementation is slow, not graphQL as a whole.
    We, for example, use graphQL mostly in java (the library is called graphql-java-tools) and we did not measure any significant overhead... 🙃
    Your solution for nodejs was great, though. We should inspect catefully our runtime implementations. Thanks for the video!

    • @bawad
      @bawad  4 года назад +1

      agreed

  • @driziiD
    @driziiD 4 года назад +11

    really impressive performance-tuning
    i learned a lot
    high-quality content as always

  • @xmorse
    @xmorse 4 года назад +7

    Probably a problem related to overuse of promises, every promise adds a lot of over head and the garbage collector has to remove all these allocated promises, every field in your type graphql schema is probably implemented as an async function

    • @bawad
      @bawad  4 года назад +2

      yep I think it is related to that

    • @BIELSIMON
      @BIELSIMON 4 года назад

      Okay but what is the solution then, in nodejs since it is single threaded everything has to be async

    • @bawad
      @bawad  4 года назад

      one solution is to remove promises where stuff should just be sync

    • @BIELSIMON
      @BIELSIMON 4 года назад

      Yes, makes sense. But don't you think that those cases are already (or should) be optimized automatically by the js engine? I'm no google engineer and I think I'd know how to do it...

    • @BIELSIMON
      @BIELSIMON 4 года назад

      I am very interested in this because this can basically determine whether it is possible to make a truly performant graphql api. If it turns out that it is not, graphql will be delegated to edge cases such as specific public facing apis and apis for mobile devices or network constrained environments. I really like graphql and would like this not to be the case though.

  • @boopfer387
    @boopfer387 4 года назад +3

    curious on if you messed with a Graph database like Neo4j?

  • @unlimitself
    @unlimitself 4 года назад +10

    This is why I started using GoLang. The performance is mind blowing. Other static typed close to C languages are also good.

    • @andresmontoya7852
      @andresmontoya7852 4 года назад +2

      No, I think the error is that GraphQL resolves the problems that http 1.1 had. That's why serverless options works better, because they work over http 2 or 3.

    • @uziboozy4540
      @uziboozy4540 4 года назад +1

      I just can't stand looking at Go code.. A functional combination of C and Python, but with terrible type support..
      If you're really looking for a mind blowing language, master Rust instead.

    • @unlimitself
      @unlimitself 4 года назад

      @@uziboozy4540 Sure. Rust is great as well. That is why, I mentioned any "Other static typed close to C" language.

  • @vsalbuq
    @vsalbuq 4 года назад +1

    I don't understand what you do yet, but I will. That's why I've subscribed. I'm just exposing myself to your videos and some things are coming by osmosis.
    Until the end of the year I'll probably understand that. Thanks for the video, anyways.

    • @bawad
      @bawad  4 года назад

      if you're new to GraphQL, I recommend starting with graphql.org/learn/ and ruclips.net/p/PLN3n1USn4xln0j_NN9k4j5hS1thsGibKi

  • @DrPanesar
    @DrPanesar 4 года назад +5

    Hi Ben. What version of type-graphql did you need to upgrade too?

    • @bawad
      @bawad  4 года назад

      0.18.0-beta.8
      edit: 0.18.0-beta.9 just came out with even more improvements

  • @ngneerin
    @ngneerin 2 года назад

    This is the type of content missing from the web. Continue with such videos

  • @eduriseworld
    @eduriseworld 4 года назад +29

    Extremely useful content Ben.
    Thank you for sharing. ❤️
    Please take a look at our Project Based React tutorials as well.
    Keep doing the great work 👍

    • @bawad
      @bawad  4 года назад +2

      Any particular kind of project you had in mind?

    • @eduriseworld
      @eduriseworld 4 года назад

      Hey @@bawad, yes we do have a bunch of project ideas for tutorials specifically. Which will help people get up and running with React and also newer tech such Apollo which you're very good at. So keep doing the great work and we will keep moving forward as well.

    • @bawad
      @bawad  4 года назад +16

      oh lmao this is an advertisement, I thought you were wanting to see me make more project based react tutorials

  • @hdauven8434
    @hdauven8434 4 года назад +2

    Hey Ben, it would be interesting to see the performance difference between the regular GraphQL library and Type-GraphQL. That would show whether it really is the culprit of performance issues in your implementation.

    • @bawad
      @bawad  4 года назад +1

      yeah this would be good to do, I'm just too lazy to set it up in graphql-js
      here's a benchmark though github.com/MichalLytek/type-graphql/pull/488#issuecomment-564592663

  • @Kanexxable
    @Kanexxable 4 года назад

    how do you set up graph ql with the typescript complier ! Note I don't want to use type Graph QL i just want to use typescript as my compiler

  • @justfly1984
    @justfly1984 4 года назад

    We have decided to use web-sockets on top of AWS API gateway. native, realtime, cross-browser support and pretty type-safe. We had multiple perf issues and caching issues on previous GraphQL project so this time we use good old REST and pure web-sockets.

  • @LucasBatistussi
    @LucasBatistussi 3 года назад +3

    BFF (Back End For Frontend) pattern says hi 🙋

  • @petecapecod
    @petecapecod 4 года назад

    Great video thanks for showing us how to debug GraphQL requests

  • @raka2958
    @raka2958 4 года назад

    Can someone recommend a project based course to learn javascript (+ ecosystem) ? Took one udemy course but abandoned it as it dragged too much

  • @C493d
    @C493d 2 года назад

    Was this really the solution or did you take any further steps after?

  • @sinefinehabitarevolo
    @sinefinehabitarevolo 4 года назад +1

    This is a great breakdown video. How were you able to get the query field breakdown to DataDog?

    • @bawad
      @bawad  4 года назад

      check out datadog APM they have a node.js lib

  • @jamesherrero7334
    @jamesherrero7334 4 года назад

    3:51 you mention that you're using apollo tracing, how did you make it give you that diagram?

    • @bawad
      @bawad  4 года назад

      That's Apollo platform

  • @dealloc
    @dealloc 4 года назад +1

    For efficient searching, especially considering you have a hierarchy of data that can be searched for, it would be more efficient to use something like Elasticsearch, Solr or Algolia (as a service). GraphQL isn't ideal for free form search, as you will have to do all the optimization yourself, and even then, GraphQL has the overhead it has to process the data before returning it.
    Now, this only makes sense as your app grows, so there's no need to be on the edge on it, but just wanted to pitch in!

    • @bawad
      @bawad  4 года назад

      Wouldn't I still go through GraphQL to query Elasticsearch or do you recommend directly talking to elastic?

    • @dealloc
      @dealloc 4 года назад

      @@bawad As with authentication services, it is best to have separate endpoints for those types of services.
      I recommend that you create an endpoint (or separate service with its own endpoint, whichever you prefer) to handle requests for search which then in turn uses the search mechanism of your choosing (e.g. Elastic).

  • @aleksd286
    @aleksd286 4 года назад +1

    how did you test how fast you could md5 hash something?

    • @bawad
      @bawad  4 года назад +2

      console.startTime('md5')
      imgix.sign()
      console.endTime('md5')

  • @ProjektArcadia
    @ProjektArcadia 4 года назад

    It would be nice to see some more performance comparisons.
    The same queries with the current and beta type-graphql version, with and without overfetching and with both optimizations.

  • @yah3136
    @yah3136 4 года назад +3

    Don't overfetch, save the planet

  • @vinayakshahdeo7578
    @vinayakshahdeo7578 4 года назад

    Ben can you help how to take a screenshot in react and append it as a file input automatically?

    • @bawad
      @bawad  4 года назад

      sorry, not sure how to do that

  • @estranhokonsta
    @estranhokonsta 4 года назад +1

    Debugging is tiresome and frustrating :(
    To me what jumps right away is the same as you said: the huge garbage collection. It still took one fifth of the total time from what you showed us.
    To debug it, first i would only use one request (the one that is causing the performance problem) and not so many of them. And i also wouldn't take out anything form it, including the postgress queries. This to avoid some others non-linear problems that can obscure the data. Then only after that one can begin to add or cut thing as needed.
    The main thing to check in those situations is if the bug comes from our code or from some other modules.
    What i would do is go up from there to see in which field resolve it originated (since it is a graphql API). Probably checking the 3 "(anonymous)" calls above the 'applyMiddleWares' and see if the resolve functions are from the same fields. Then you can try and dig dipper into them with some test code or just logging the timestamps and number of time they are called and also using normal breakpoints if needed.
    The garbage collection seem to be called by tslib.js which is supposed to 'manage' the typescript helpers. Probably a sign of some problem in the decorators or something related? Async await may be involved. Does it needs a try catch for some reason? Or some polyfill that is not behaving correctly with your javascript version and your node version?
    Or it could simply be that you only need a simple if statement to check if some value exist?
    Or some graphql types/fields may have some circular dependency that is not dealt appropriately?
    Debugging is no doubt the worst part of programming. Fortunately at the end of the video, you presented a possible solution. Who knows if it is the right one, but it works and that is what helps preserve the sanity of the normal everyday programmer.

  • @arielsashcov99
    @arielsashcov99 Год назад

    Hey Ben can you try Wundergraph?

  • @vorname1485
    @vorname1485 4 года назад

    when you mentioned md5 and request count, i was sure not this, cause md5 is made to be fast, which is also a reason why its unsafe to hash passwords with it, like many did and do (bruteforce is easier because less time needed to create hash).
    17ms on simple description: string default resolver sounds heavy. I bet the default resolver on the library is poorly optimized (or was).
    Is there any way in the library to set own default resolver?

    • @bawad
      @bawad  4 года назад

      idk if the tracing is getting fooled some how, but the default resolver should do nothing

    • @BIELSIMON
      @BIELSIMON 4 года назад

      I think it is waiting for other promises to resolve, it isn't using 17ms of cpu time probably. It's a recurring issue I find with js devtools. It should indicate which promise (or promises) it is awaiting

  • @romanext921
    @romanext921 2 года назад

    Why not just cache each recipe? It's okay if it takes 500ms, cause most of the time it would be instant

  • @rtorcato
    @rtorcato 4 года назад

    for the foreach callback are you setting it to async?

    • @bawad
      @bawad  4 года назад

      I think the forEach is something the internals of graphql does

    • @rtorcato
      @rtorcato 4 года назад

      @@bawad ok this link explains what could be the problem with the foreach riptutorial.com/javascript/example/7746/looping-with-async-await

    • @bawad
      @bawad  4 года назад +1

      I'm not sure what the code looks like, but you can still use forEach and avoid that
      const promises = [];
      arr.forEach(item => {
      const p = asyncTask(item)
      promises.push(p)
      });
      const results = await Promise.all(promises)

    • @paweld.9542
      @paweld.9542 2 года назад

      @@bawad or you can do like that, more elegant way : const results = await Promise.all(arr.map((item) => asyncTask(item))) 😉

  • @Jossnaz
    @Jossnaz 4 года назад

    actually if type checking is such an issue, why type check? Isn't it commmon nowadays to just strip typescript out and run pure js code?

    • @estranhokonsta
      @estranhokonsta 4 года назад +2

      I think he meant type checking by Graphql, not typescript. Typescript is normally always pre-compiled to pure js. But Graphql is a 'typed API'.

    • @Jossnaz
      @Jossnaz 4 года назад

      @@estranhokonsta cant you strip typescript entirely during the build process? you lose runtime type checking yes, but you get 2 advantages: fast build time, and faster performance. I just assume type graphql makes heavy use of typescript. What checks do have to be done when doing a read? is type graphql double checking the database columns on a read? "is it really an integer?" that'd be stupid

    • @bawad
      @bawad  4 года назад

      ​@@Jossnaz
      > cant you strip typescript entirely during the build process?
      yes
      > is type graphql double checking the database columns on a read? "is it really an integer?"
      It's not type-graphql, but graphql checks each field to make sure it's the expected type

    • @estranhokonsta
      @estranhokonsta 4 года назад

      @@Jossnaz The truth is that modern dev can be so confusing that it let's one doubt many things. All this because modern apps and tech are complex and too many faceted.
      Just in this one project there must be typeOrm, TypeGraphQL (i assume) Typescript, GraphQL, etc And all of them have some relation to types.
      TypeORM and TypesGraphQL are related as they use types, classes and decorators of Typescript and are more for ease of development for the programmer (although they no doubt each introduce overhead in the prod code).
      GraphQL also use its own typing system completely unrelated to Typescript and heavily influence the prodution code.
      And so many other layers of complexity.
      But just thinking about creating a modern and minimally feature rich app with just vanilla javascript... Hell will not be on the creation part, as it is not so impossible as that. The real suffering will appear when one has to maintain the code. It is difficult as it is for the ones who have created the project, never mind the ones who comes afterward.

    • @Jossnaz
      @Jossnaz 4 года назад

      @@estranhokonsta well its like a thing of javascript that everything is so volatile. And if you update one thing, all of the sudden all breaks. It's certainly an anti pattern to use the standard versioning style in the package.json imho. Things break soooo quickly. Upside is that javascript is very innovative it seems... good graphql libraries for php? I've seen one with 3k stars... thats really nothing. The question I was wondering about as well is whether graphql really, really is worth it? do you have soooo many rest endpoints otherwise, really? so many calls? usually a bunch of crud + search thats it. I dont know man. I havent seen the value yet

  • @somedatussr4323
    @somedatussr4323 3 года назад

    I don't mean to be rude but this is why you shouldn't use javascript for a production backend. You should have chosen something like spark-jobserver with python. The performance would be much better and you would have spark's data analytics tools.

  • @thomasczthomash1859
    @thomasczthomash1859 4 года назад +2

    Solve all your GraphQL performance problems by upgrading to REST APIs.

    • @bawad
      @bawad  4 года назад

      big brain plays

  • @OBLIVIOUSKARI
    @OBLIVIOUSKARI 4 года назад

    Can you upload a video to let us know if you find out more or an update happens!?

    • @bawad
      @bawad  4 года назад

      follow me on twitter.com/benawad I'll keep you posted

  • @tibordigana2551
    @tibordigana2551 4 года назад +2

    Young developers repeat 15 years old architectural problems. Server/Client side logic. Instead of building DTO objects on the server side, they cope with bunch of security and performance problems on the client side. Same with the old Asp .Net. Querying 20 objects must be fast like the hell and i did not mention that the database must be very large cca 100 million records.

  • @elgunlee
    @elgunlee 4 года назад +1

    Use Golang's GraphQL libraries for server

  • @OBLIVIOUSKARI
    @OBLIVIOUSKARI 4 года назад

    Thanks I’ll try to update it. I had the same issue and ended up creating a database table that contained preprocessed data. Before that, my resolvers we’re taking 6 seconds to complete.

    • @OBLIVIOUSKARI
      @OBLIVIOUSKARI 4 года назад

      I wonder if it were better sticking with Apollo but typegraphql and TypeORM api is just too good

    • @bawad
      @bawad  4 года назад

      yikes 6 seconds is a looooooooooooooooong time
      yeah I really like the typegraphql/typeorm api, so I'm hoping typegraphql can make some improvements to its performance

    • @OBLIVIOUSKARI
      @OBLIVIOUSKARI 4 года назад

      Ben Awad it was crazy because each step on it’s own we’re near instant. But combined 6 seconds. Hopefully it gets better, it’s my fav library when used with typeorm

    • @bawad
      @bawad  4 года назад

      @@themanlihood how are you annotating fields? Do you use decorators? Can I use 1 class for both my graphql type and typeorm model?

  • @Xhisorz1
    @Xhisorz1 4 года назад

    Thats a nicu, my Dude.

  • @jacobebey7019
    @jacobebey7019 4 года назад

    It's the apollo tracing... It's hefty and should never be used in production. If you disable that and run the profiler, be amazed.

    • @bawad
      @bawad  4 года назад

      I'm not using apollo tracing in production, just tried it to test locally

  • @InfoPaste
    @InfoPaste 4 года назад

    Could you do a video about lunching your platform. I plan to do the same soon and create tips or advice would be great

    • @bawad
      @bawad  4 года назад +1

      haven't done much to launch it yet, only product hunt

    • @31redorange08
      @31redorange08 3 года назад

      @@bawad He said lunch, not launch.

  • @Jossnaz
    @Jossnaz 4 года назад

    a possible solution to avoid such huuuuge queries that arent really needed is to create enriched views. Inserts and deletes will be a bit slower though...

  •  4 года назад

    Hi, would it be worthy to try using server side rendering (in the case you are using SPA).

    • @bawad
      @bawad  4 года назад

      ssr wouldn't change anything in this case

  • @rodmanswanston3320
    @rodmanswanston3320 4 года назад

    Did you try deduplication?

    • @bawad
      @bawad  4 года назад

      nope, have you had success with that? At what level do you dedupe?

    • @BIELSIMON
      @BIELSIMON 4 года назад

      Deduplication in the request level? Data rows? Or like memoizing with data loaders?

  • @Oswee
    @Oswee 4 года назад

    For me watching this conclusion is only one... i should stay away from GraphQL forever as i am working with large tabular data sets mostly.

  • @eyesight2073
    @eyesight2073 4 года назад

    😻😻😻😻

  • @darkpill
    @darkpill 3 года назад +1

    Best way to solve any GraphQL problem. Don't use GraphQL! Problem solved!

  • @RockuHD
    @RockuHD 4 года назад

    That garbage collection is HUGE. Maybe you should go in and edit the field resolver/applymiddlewares. Make it reuse variables rather then creating a new variable each time.

    • @bawad
      @bawad  4 года назад

      I would, but I didn't write that code. It's from type-graphql

  • @Cassp0nk
    @Cassp0nk 4 года назад

    Surprising you are over fetching as that’s basically what graphql is there to avoid. Otherwise you may as well have used rest. In fact with your apparent problem domain it looks like graphql is probably just adding complexity and latency and thus over engineering.

    • @bawad
      @bawad  4 года назад +1

      In this case, I was over fetching on purpose to simplify some logic on the frontend
      > Otherwise you may as well have used rest
      yeah I've been thinking about that lately

  • @AmstradExin
    @AmstradExin 4 года назад

    Performance problems? Assembler. (:

    • @bawad
      @bawad  4 года назад

      😱

  • @socialblade7751
    @socialblade7751 4 года назад +2

    GraphQl for small application, my advice to use Rest API or Grpc (Best solution, very fast) for production ..

    • @paraluchs_
      @paraluchs_ 4 года назад +1

      But why? Huge companies like Facebook, Twitter, Airbnb and Twitch ditched REST for GraphQL.
      As mentioned in the Video the problem was TypeGraphQL and transfer of huge amounts of data (which should always be avoided).

    • @JohnDoe-ji1zv
      @JohnDoe-ji1zv 4 года назад +1

      pharti77 nobody abandoned REST! REST will be still be there for a long time yet.

    • @paraluchs_
      @paraluchs_ 4 года назад

      @@JohnDoe-ji1zv I also agree with that. I use both.

  • @DavidSmith-ef4eh
    @DavidSmith-ef4eh 4 года назад +2

    Another reason not to use graphql

  • @mydisk2859
    @mydisk2859 3 года назад

    Use apollo-server with js simply no n0nsense