How slow is MediatR really?

Поделиться
HTML-код
  • Опубликовано: 8 фев 2025
  • Check out my courses: dometrain.com
    Become a Patreon and get source code access: / nickchapsas
    Hello everybody I'm Nick and in this video I will investigate a claim around the library MediatR and how it can affect your application's performance. This video will also introduce you to performance measuring and memory profiling techniques.
    Don't forget to comment, like and subscribe :)
    Social Media:
    Follow me on GitHub: bit.ly/ChapsasG...
    Follow me on Twitter: bit.ly/ChapsasT...
    Connect on LinkedIn: bit.ly/ChapsasL...
    Keep coding merch: keepcoding.shop
    #csharp #dotnet #mediatr

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

  • @nickchapsas
    @nickchapsas  3 года назад +109

    Something that I forgot to mention in the video is that, when you add some IO into the mix (database call, api call etc) the difference will get even smaller because the IO will loadbalance it out of the equation.

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

      Yeah is was wanting to make this comment as well. As realistic as you tried to make it, it is still not really reflecting real-world scenarios. Would love to see an addition to this where some real work is being done, eg calling a DB or external service

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

      And this is not even the beginning of looking for performance - first you need to figure out exactly what part of pipeline slows you down. You can make an educated guess that more often than not it will be the IO. But you may have a really non-performing middleware/container and so on. Unless you find the real culprit it's pointless to sacrifice the architectural cleanliness vs. performance.
      Thanks for the video.

    • @Petoj87
      @Petoj87 3 года назад +2

      This is something you should say in all your performance related videos. But great video always something new to learn :)

    • @GhostTyper
      @GhostTyper 2 года назад +1

      However, the gap also may get bigger, if you don't have the SSL overhead.

  • @JesseTemple
    @JesseTemple 3 года назад +24

    We use MediatR in a production environment with good results, but I never got this far down into the weeds about it. This was a very interesting video, thanks!

  • @jradplowman
    @jradplowman 2 года назад +8

    Nick your videos are pure gold. Your presentation and pacing are perfect. Also your approach is so easy to follow! Thanks again for the great content.

  • @ThiagoFer93
    @ThiagoFer93 3 года назад +38

    I feel like most developers are always seeking the best practices overall and forget to ask what is the best for their situation, which can lead to hard to handle cannon that is used to kill an ant.
    It all comes to the problem you need to solve. In my company, we have some smaller applications that use MediatR. We never faced performance issues and my team just like to work with this library, because how the code feels cleaner and outweighs the performance "cost". It works for us in that situation and we are happy with maintening it.

    • @davidmartensson273
      @davidmartensson273 3 года назад +6

      I agree, cleaner better code is almost always beneficial, and my experience is that cleaner code can lead you to find better optimizations that saves even more or code that scales better.
      Getting 5 % more speed with more complex code, or double the performance by adding another instance due to easier to scale code :)

    • @gettoecoding1058
      @gettoecoding1058 3 года назад +2

      100% agree with you !

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

      And happy developers that can easily change code saves money as well. Good for you!

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

      100% agree. 80% of the time, we use only 20% of application. Martin fowler refactoring books also suggested the same.. we should focus on writing clean code and fix performance issue when needed.

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

      it is my experience that there are other ways to keep your code "clean" and remain testable without the complexity, and clutter, that this pattern inherently introduces.

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

    Super interesting how it affects in terms of memory allocation, thanks again Nick!

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

    Hey Nick, awesome to see a video on this content! As always really well done :). I agree that the benefits of MediatR generally speaking outweigh the performance cost. That said, the memory allocation issue related to the service can almost be completely removed by making the service a singleton, if your use case permits. It would be interesting if MediatR also allowed you to register handlers as singletons.

    • @nickchapsas
      @nickchapsas  3 года назад +5

      Singleton is almost never a viable option bacause it heavily depends on whether you want to support scoped services in the handlers, which is almost always the case, since the API request itself is scoped.

    • @tiebird
      @tiebird 3 года назад +2

      Registring as Singleton will create a memory leak in most cases. Variables injected with a shorter lifetime will never be collected because the root will still exist. While it is possible, I think you will get into all sorts of trouble 🙂

    • @RENAUDADAM
      @RENAUDADAM 3 года назад +2

      @@tiebird That is interesting! I never thought that a singleton would create a memory leak. How would this happen?

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

      @@nickchapsas That is completely fair. Good point 😊

    • @tiebird
      @tiebird 3 года назад +2

      @@RENAUDADAM like earlier mentioned, you register a service/class as a Singleton. Every service/class that is injected in to the constructor of this Singleton will never be disposed in the lifetime of the application. As long as the root object exists, this means the Singleton object in this case, underlying objects will not be disposed by the automatic garbage collection. Therefore, you will see your .NET Core ServiceCollction grow larger and larger. It can be pretty hard to find these kind of memory leaks if you don't know what you're looking for. Memory consumption can rise fast if you call some kind of repository frequently.

  • @diadetediotedio6918
    @diadetediotedio6918 2 года назад +3

    I think many people have a hard time understanding that not everything is about raw performance, if that were the case we would only write with low-level languages like ASM, C or Rust. We use high-level languages because we want to increase the readability of our code as much as possible and reduce human error at the maximum possible rate, the objective with this is to make the product something agile to develop and with a low error rate. If you worry too much about performance trying to cut costs, you will end up impacting your bottom line and making those lower costs less valuable in and of themselves.

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

    very good evidences bro, thanks for best clarifications

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

    Great thorough tests, explanations, and video! Thank you!

  • @thomas5540
    @thomas5540 3 года назад +2

    Thank you for putting so much effort into it. I learned a lot from this video.
    I'm gonna stick with Mediatr :-)

  • @josepvg
    @josepvg 3 года назад +2

    Thanks for a great video. I think when you add some IO bound code to the sample this overhead becomes minimum and I also think in 99% of cases doing such low level optimization as using services instead of the Mediatr makes the code more complex. It is then much more difficult to maintain, bugfix and refactor for high level optimization

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

    Very informative video. Learned about the profiling tool too. :)

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

    Thank you for this extraordinary example!

  • @Sebazzz1991
    @Sebazzz1991 3 года назад +28

    Do one SQL query or lazy load too many, then optimize that away, and you've gained much more than replacing MediatR.

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

    It was quite obvious that with all the additional plumbing that Mediatr and CQRS in general require there was going to be some performance impact. I think 8% is not terribly significant. However, we have to remember why CQRS is really in place. The theory is that it improves readability, testing paradigms, and keeps a cleaner more manageable architecture. You can make a case for that I think. In my situation, our company builds enterprise applications for large companies and government with 10's of thousands of potential concurrent users possible. In that scenario, we have been hard-pressed to think that all of the extra plumbing (dozens and dozens of extra nearly empty classes and interface points), that this requires gives a tangible benefit. It does keep code out of the WebAPI controllers which is great. But there are a number of other scenarios including just a straight N layer interface that do the same thing and do not degrade performance. This pattern and some of the others like it then are relegated to really specific situations that most projects do not need. I very much appreciate the quantifiable info that Nick has provided, it further confirms for me in my mind, that Mediatr outside of some very specific situations, is purely an academic exercise.

  • @Dustyy01
    @Dustyy01 3 года назад +2

    Really nice and deep insights. Sadly most people just believe what others say without trying it out first.

  • @nothingisreal6345
    @nothingisreal6345 3 года назад +15

    I think from a performance perspective this doesn't matter that much. After all realistically processing a request will do MUCH more memory allocation (DB query, Read/Write XML, create in memory data structures). But I do think that there is a tendency to add more and more indirections into C# projects. And every level of indirection adds more complexity. While the original author of a code might be familiar with all these advance concepts and remember about all the introduced indirections and abstractions someone who needs to maintain the code later will have a very hard time to figure out how things in a code base depend on each other, especially if introducing such an indirection happens in a code file that isn't obviously linked to the code file that depends on it. You must know that e.g. the Mediator package has been added. You must know that this one line of code in the Program.cs is responsible for the coupling. You must know that the service runs transient. All this adds complexity without delivering any direct business value. It is all pluming. This is the wrong direction IMHO.

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

      Do you think these issues could be solved by writing documentation?

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

      ​@@roko567 so we use MediatR which causes increase of indirections into our project. these indirections create us a problem to solve by documentation... which is also a problem because documentation is something that we have to keep updated and if you have outdated documentation it can be even worse than total absence of documentation
      Also MediatR makes a great job of hiding code smells. e.g. if you have a controller with 10+ services you can see that something somewhere went wrong and you should do refactoring. While with MediatR you have only instance of IMediatr and miss that your code is not as great as it seems
      I see these pros and cons about using MediatR
      + less dependencies in costructors
      + nice and easy in-process pub-sub implementation
      + way to decorate your calls with logging and etc
      - indirect usage of methods/services
      - slower navigation across code base
      - hiding code smells
      I agree that there are cases when usage of MediatR is great. But I doubt that it should be used in every single API project.

  • @denys-p
    @denys-p 3 года назад

    Honestly, I like this video much more than many others. Mostly because of conclusion “always measure and then make decisions”.
    It would be nice to see even more realistic example - some json (de)serialization, maybe call to DB, some calculations and data transformations, logging, DI. Where are bottlenecks etc?

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

    You are awesome Nick 👍🏼

  • @metlic5209
    @metlic5209 3 года назад +8

    But the problem with MediatR is when you have a large amount of request handlers, notification handlers and behaviors, of course calling a single request handler is closely comparable to direct method call.

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

      The same applies to normal DI though.

    • @hyts2k
      @hyts2k 11 месяцев назад

      @@peteruelimaa4973 I think that the performance of MediatR relay on performance of DI container, the much request and handdler you are using the much slow will be.

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

    Perfect demo 👌

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

    Very very cool video ! Super interesting.

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

    Nick great presentation !!! But it is also great the comments that this video triggered, if someone read them can gain some more knowledge

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

    I'm always weirded out by people micro-benchmarking in C#. "Oh... you'll get 3.8% better performance if you don't use mediatr"... Sure, and i'll get an order of magnitude improvement if I use Go or Rust. I'm using C# in the first place because, to a certain degree, I'm prioritizing development time performance over runtime performance. And yeah i'd echo the point you made in the pin that i'd like to see this test re-run with EF... i'm definitely expecting that the differences would shrink to basically nothing as soon as you hit a database (particularly if you're performing the correct async rituals).
    For me... bottom line is that, at worst, Mediatr is taking away 4% of performance, probably less in a real example, and the very fact that i'm using C# means that 4% in return for objectively cleaner architecture is a good deal.

  • @MetalKid007
    @MetalKid007 2 года назад +1

    I didn't think the slowness complaint was the basic Mediatr setup. I think it was more when you start adding things to its pipeline/middleware (decorators) that it started to become a problem.

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

    MassTransit also has an implementation of the Mediator Pattern, I have a feeling that there will be a huge difference in terms of performance, but I'm too lazy to benchmark it to see the difference. Is there a chance you can make a video for that?

    • @kblyr
      @kblyr 3 года назад +2

      By the way, I'm currently experimenting with MassTransit's Mediator

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

      @@kblyr I asked the Author of Masstransit about that and he says he hasnt used it himself LOL

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

    Great content!

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

    your content is good. thanks

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

    It will be interesting to run this test with the MediatR request being of type record or struct or maybe record struct to see how that impacts allocation.

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

      It can't be a struct because it needs to inherit from the IRequest interface

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

    Hi Nick! Thanks for the nice videos & material you make & provide to the public :)
    I have never used MediatR library before, however I believe there is another, that might be negative, impact in using this pattern in such a generic way as the library provide. How can you control the lifetime of the handler's instance? Does every time you send a message through the mediator instantiate a new instance of the handler? What happens if you send the message from a loop?

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

    I'm a fan of MediatR and agree that it's all relative to what you gain plus, as others have commented, one bad SQL query makes all of this irrelevant.
    However, just in terms of MediatR overhead, a more likely scenario is probably a controller calling a method in a service class and that method calling multiple other methods in that same class - compared to the controller calling a MediatR class and that class calling multiple other MediatR classes.
    I haven't done the test, but I suspect the difference will be far greater in a case like that.
    Otherwise you have to duplicate common code in each MediatR class and that's not good.

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

    Hi Nick,
    Thank you for your free content really appreciate it.
    I am wondering how will the Fastenpoints perform against mediator, I guess that the Fastenpoints also allocate ram in order to map the objects.
    Thank you.

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

    Having looked at the mediatr codebase, I believe the performance issue can be alleviated by Introducing object pooling for the request handler and the notification handler. This will reduce the overall memory used and thus reduce GC time.

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

      MediatR is as efficient as it can go with the handlers while respecting .NET's DI scopes. Both scoped and transient use the service provider to retrieve the service, which is exactly the same as injecting them and singletons are cached. All of them come from a dictionary. There isn't much to optimize past that, since a lot depends on how elaborate your pipeline is (pre/post processors etc)

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

    Hi Nick, I'm a bit confused here and I was wondering if you could help me. Both methods use the MediatR framework. Calling it directly just means that you're NOT using MediatR injecting dependency, you're just creating an instance of the object and then calling the Method directly?

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

    At the beginning you think about a performance.
    In the middle you think about an architecture.
    In the end you try to think about the performance keeping in mind the architecture.
    After the end - you want to use the ECS.
    But if you are a senior - you have to know and have love to use the MediatR, the benefits in Enterprise is huges.

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

    Better than unit of work + service + repository?

  • @ДимаАфонченко
    @ДимаАфонченко 3 года назад

    Hello Nick! Cool demo! What program you use to create your videos? I mean this great feature when you can stop demo at any time and draw lines to highlight useful moments on screen.

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

    Is the Activator call can cause this little overhead in mediatr?

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

    And try and throw some middleware (native) / mediatr pipeline behaviours that do logging and some other useful stuff and it gets really crazy :)

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

    What do you recommend instead of using MediatR write own solution ?

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

    is MassTransit MediatR ok? because using the cqrs pattern without MediatR is not that simple for me and everyone is using MediatR

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

    I think for most corporative applications, that performance difference would not be a big deal.

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

    Nice

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

    If we add a least some noticeable business logic to the test apps then the overhead of creating little mediator messages will disappear and will be minor comparing to other allocations related to DB, MessageBus, what ever could be in the logic. So for me such testing has very little value or I would say it actually hurts because ppl with insufficient qualification will make decisions based on this or at least will be biased doing own selection of the approach.

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

    I think the first benchmark was not fair. You are using a single instance of the service/handler, effectively a singleton for the non-mediator test. But for the mediator test, you are using DI to allocate the handler on each iteration. Was it medator or DI allocating the order of magnitude more memory? Each benchmark should be required to resolve the handler 'service'.

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

      The comparison is being fair to how you would use MediatR in your app. You wouldn't resolve the handler. You would resolve IMediatr. On that front they are both singletons. They handler is out of bounds since mediatr is doing the instantiation internally. It can be overriden, but that was never what we're testing.

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

      @@nickchapsas Guess it is fair, I rewrote it as I suggested but the relative performance and memory allocations were inline with what you showed. I should have validated my assumption before my original comment. Thanks for all the great videos.

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

    Interesting, as usual, but I've never used MediatR as "dry" as that. For instance, the pipeline model is so much worthy, and appart from the obvious "cleaner code" standpoint, I'd bet the impact wouldn't be as important if you'd have to put your behavior logic in all your services...

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

    Can you make a vid about Dataflow (Task Parallel Library) ?

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

    How's your command line called ??? It looks so utterly insane

    • @nickchapsas
      @nickchapsas  3 года назад +2

      I’m using Microsoft Terminal and oh-my-posh

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

    Can you try and do this with Blazor and Fluxor compared to a home made Blazor with Invoke? Right now Fluxor is making it so much easier to work with UI state.

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

    record please video about your pc setup

  • @koktbarilla2568
    @koktbarilla2568 3 года назад +7

    I was blinded around 7:30 min in, could not watch the rest of the video, RIP

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

      Hahahahahaha :)

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

    applications should almost always prioritize speed before other. So the question should be is this safe enough. If true then go speed

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

    Greate content!

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

    How do you comment that fast

    • @myuuiii
      @myuuiii 3 года назад +2

      Notification squad

  • @giovani5586
    @giovani5586 3 года назад +2

    Even slower due to slow code navigation 😴😴😴

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

    pre 301 squad :D

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

    Hi Nick
    Have you considered opening a discord community?
    Would also be an opportunity for your potential patreon subscribers

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

      Hey Jacob. I have but I don't want the Discord server to end up being total chaos since I don't have time to moderate it so for now, I'm just part of the official C# Discord server

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

    Slower than me posting a comment

  • @insert-name1500
    @insert-name1500 3 года назад +2

    OMG. I can't believe Nick is using 69 and 420 as test values 🤣🤣🤣.

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

    👍👍👍👍👍!! You really need Promo>SM!!!

  • @brandonpearman9218
    @brandonpearman9218 3 года назад +10

    Poorer performance is an objective number but besides that MediatR is an extra dependency to maintain and align with the team, its an added layer of complexity which you dont NEED. I dont feel like it makes code "clean", Its just a popular style at the moment off the back of the popularity of events. Basically teams which dont have event queues can play play events with MediatR lol jk

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

      In reality that’s not the case.
      Look at it this way.
      The complexity of your unit testing is dramatically reduced. You only need to test your handlers instead of mocking and testing controllers and contexts etc. In that example case, why would you go out of your way to indirectly test parts of .net outside the domain of your project?
      We don’t want to mock controllers, we don’t
      Want to create a dummy context. Why should we? We only want to test our code. Hence, the handlers
      And this example works all over.
      Not only this but it allows associates all the way through senior to work on core parts of the system in isolation because you’re only working on a single request contract / response object implementation.
      If anything I think it makes it easier to maintain your code base while also keeping it simpler
      Now the question is, is mediatr the best. I dunno. If it’s the only thing you have in a service maybe but if you’re also using something like masstransit then you can use Chris Patterson’s in memory mediatr which does the same thing
      Mediatr is my go to unless I’m using MAssTransit then I use a combination of the MAssTransit bus with in memory bus similar to SendLocal in Nservicebus.

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

      MediatR behaviors are the secret sause, which used effectively, does contribute to clean extensible architecture. I would not agree that this is not NEEDED.

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

      @@prom3theu581 yeah i agree with you regarding the tests but you dont need mediatr for any of that. Ie thats not a legit reason to use mediatr, hence why i say its just the popular thing nowadays days.

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

      @@krajekdev yes id agree behaviors is a good reason for mediatr. But in my experience most companies that use mediatr dont use behaviors and have no need for it(that could be argued but the fact that they never used them shows it was not needed). But yes if you have a strong need for behaviors, i would endorse mediatr for that case. But thats why i say it just a popularity contest, everyone uses something because its shiney and not because they actually need it or even know what it does. Some things have become "always use it because it fits every project".

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

      @@brandonpearman9218 agreed 100%, cheers

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

    Lol! MediatR … like to “mediate”; sounds like politics… We usually save that for our meetings not our code. ;)

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

    Irrelevant