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
@porgeet4 жыл бұрын
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.
@TheNewton4 жыл бұрын
tl;dw 10:40 overfetching fields & 11:12 type-graphql performance, optimized by lowering results fetched and using beta branch of type-graphql
@31redorange084 жыл бұрын
TL;DW GraphQL
@Frogquest4 жыл бұрын
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.
@bawad4 жыл бұрын
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
@pkop44 жыл бұрын
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.
@uziboozy45404 жыл бұрын
Didn't even know they did that under the hood. Maybe it's time to reconsider using Hasura instead of Prisma.
@cobalt24893 жыл бұрын
Or use diesel & actix with rust. To make your API goo BRRRRRRRR
4 жыл бұрын
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 :)
@bawad4 жыл бұрын
yeah that was certainly part of the problem
@cklee_4 жыл бұрын
@@bawad any way to lazy load the query for the recipe detail after the initial fetch for the search component?
@bawad4 жыл бұрын
@@cklee_ yeah that's what I'm planning on doing
@herohamp24 жыл бұрын
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
@metropolis104 жыл бұрын
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!
@scottamolinari4 жыл бұрын
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)? :)
@bawad4 жыл бұрын
will do
@Butcheren010 ай бұрын
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.
@alkismavridis14 жыл бұрын
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!
@bawad4 жыл бұрын
agreed
@driziiD4 жыл бұрын
really impressive performance-tuning i learned a lot high-quality content as always
@MrEmanuelherrera4 жыл бұрын
Thanks Ben for explaining and sharing the problem.
@hdauven84344 жыл бұрын
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.
@bawad4 жыл бұрын
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
@xmorse4 жыл бұрын
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
@bawad4 жыл бұрын
yep I think it is related to that
@BIELSIMON4 жыл бұрын
Okay but what is the solution then, in nodejs since it is single threaded everything has to be async
@bawad4 жыл бұрын
one solution is to remove promises where stuff should just be sync
@BIELSIMON4 жыл бұрын
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...
@BIELSIMON4 жыл бұрын
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.
@ngneerin2 жыл бұрын
This is the type of content missing from the web. Continue with such videos
@unlimitself4 жыл бұрын
This is why I started using GoLang. The performance is mind blowing. Other static typed close to C languages are also good.
@andresmontoya78524 жыл бұрын
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.
@uziboozy45404 жыл бұрын
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.
@unlimitself4 жыл бұрын
@@uziboozy4540 Sure. Rust is great as well. That is why, I mentioned any "Other static typed close to C" language.
@vsalbuq4 жыл бұрын
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.
@bawad4 жыл бұрын
if you're new to GraphQL, I recommend starting with graphql.org/learn/ and kzbin.info/aero/PLN3n1USn4xln0j_NN9k4j5hS1thsGibKi
@LucasBatistussi3 жыл бұрын
BFF (Back End For Frontend) pattern says hi 🙋
@boopfer3874 жыл бұрын
curious on if you messed with a Graph database like Neo4j?
@justfly19844 жыл бұрын
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.
@petecapecod4 жыл бұрын
Great video thanks for showing us how to debug GraphQL requests
@eduriseworld4 жыл бұрын
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 👍
@bawad4 жыл бұрын
Any particular kind of project you had in mind?
@eduriseworld4 жыл бұрын
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.
@bawad4 жыл бұрын
oh lmao this is an advertisement, I thought you were wanting to see me make more project based react tutorials
@DrPanesar4 жыл бұрын
Hi Ben. What version of type-graphql did you need to upgrade too?
@bawad4 жыл бұрын
0.18.0-beta.8 edit: 0.18.0-beta.9 just came out with even more improvements
@ProjektArcadia4 жыл бұрын
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.
@estranhokonsta4 жыл бұрын
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.
@yah31364 жыл бұрын
Don't overfetch, save the planet
@C493d2 жыл бұрын
Was this really the solution or did you take any further steps after?
@sinefinehabitarevolo4 жыл бұрын
This is a great breakdown video. How were you able to get the query field breakdown to DataDog?
@bawad4 жыл бұрын
check out datadog APM they have a node.js lib
@dealloc4 жыл бұрын
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!
@bawad4 жыл бұрын
Wouldn't I still go through GraphQL to query Elasticsearch or do you recommend directly talking to elastic?
@dealloc4 жыл бұрын
@@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).
@elgunlee4 жыл бұрын
Use Golang's GraphQL libraries for server
@romanext9212 жыл бұрын
Why not just cache each recipe? It's okay if it takes 500ms, cause most of the time it would be instant
@Kanexxable4 жыл бұрын
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
@somedatussr43233 жыл бұрын
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.
@arielsashcov99 Жыл бұрын
Hey Ben can you try Wundergraph?
@OBLIVIOUSKARI4 жыл бұрын
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.
@OBLIVIOUSKARI4 жыл бұрын
I wonder if it were better sticking with Apollo but typegraphql and TypeORM api is just too good
@bawad4 жыл бұрын
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
@OBLIVIOUSKARI4 жыл бұрын
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
@bawad4 жыл бұрын
@@themanlihood how are you annotating fields? Do you use decorators? Can I use 1 class for both my graphql type and typeorm model?
@tibordigana25514 жыл бұрын
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.
@aleksd2864 жыл бұрын
how did you test how fast you could md5 hash something?
Can someone recommend a project based course to learn javascript (+ ecosystem) ? Took one udemy course but abandoned it as it dragged too much
@jamesherrero73344 жыл бұрын
3:51 you mention that you're using apollo tracing, how did you make it give you that diagram?
@bawad4 жыл бұрын
That's Apollo platform
@jacobebey70194 жыл бұрын
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.
@bawad4 жыл бұрын
I'm not using apollo tracing in production, just tried it to test locally
@vorname14854 жыл бұрын
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?
@bawad4 жыл бұрын
idk if the tracing is getting fooled some how, but the default resolver should do nothing
@BIELSIMON4 жыл бұрын
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
@OBLIVIOUSKARI4 жыл бұрын
Can you upload a video to let us know if you find out more or an update happens!?
@bawad4 жыл бұрын
follow me on twitter.com/benawad I'll keep you posted
@InfoPaste4 жыл бұрын
Could you do a video about lunching your platform. I plan to do the same soon and create tips or advice would be great
@bawad4 жыл бұрын
haven't done much to launch it yet, only product hunt
@31redorange084 жыл бұрын
@@bawad He said lunch, not launch.
@Jossnaz4 жыл бұрын
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...
@thomasczthomash18594 жыл бұрын
Solve all your GraphQL performance problems by upgrading to REST APIs.
@bawad4 жыл бұрын
big brain plays
@Xhisorz14 жыл бұрын
Thats a nicu, my Dude.
@Oswee4 жыл бұрын
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.
@vinayakshahdeo75784 жыл бұрын
Ben can you help how to take a screenshot in react and append it as a file input automatically?
@bawad4 жыл бұрын
sorry, not sure how to do that
@darkpill3 жыл бұрын
Best way to solve any GraphQL problem. Don't use GraphQL! Problem solved!
@Jossnaz4 жыл бұрын
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?
@estranhokonsta4 жыл бұрын
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'.
@Jossnaz4 жыл бұрын
@@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
@bawad4 жыл бұрын
@@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
@estranhokonsta4 жыл бұрын
@@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.
@Jossnaz4 жыл бұрын
@@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
@rtorcato4 жыл бұрын
for the foreach callback are you setting it to async?
@bawad4 жыл бұрын
I think the forEach is something the internals of graphql does
@rtorcato4 жыл бұрын
@@bawad ok this link explains what could be the problem with the foreach riptutorial.com/javascript/example/7746/looping-with-async-await
@bawad4 жыл бұрын
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.95422 жыл бұрын
@@bawad or you can do like that, more elegant way : const results = await Promise.all(arr.map((item) => asyncTask(item))) 😉
@eyesight20734 жыл бұрын
😻😻😻😻
@Cassp0nk4 жыл бұрын
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.
@bawad4 жыл бұрын
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
@RockuHD4 жыл бұрын
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.
@bawad4 жыл бұрын
I would, but I didn't write that code. It's from type-graphql
@rodmanswanston33204 жыл бұрын
Did you try deduplication?
@bawad4 жыл бұрын
nope, have you had success with that? At what level do you dedupe?
@BIELSIMON4 жыл бұрын
Deduplication in the request level? Data rows? Or like memoizing with data loaders?
@socialblade77514 жыл бұрын
GraphQl for small application, my advice to use Rest API or Grpc (Best solution, very fast) for production ..
@paraluchs_4 жыл бұрын
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-ji1zv4 жыл бұрын
pharti77 nobody abandoned REST! REST will be still be there for a long time yet.
@paraluchs_4 жыл бұрын
@@JohnDoe-ji1zv I also agree with that. I use both.
@AmstradExin4 жыл бұрын
Performance problems? Assembler. (:
@bawad4 жыл бұрын
😱
4 жыл бұрын
Hi, would it be worthy to try using server side rendering (in the case you are using SPA).