See what a 40% performance boost can mean in your Blazor DataGrid. It should significantly impact your ability to create successful Blazor applications.
The Telerik UI for Blazor R2 2023 release is now comfortably in our rearview mirror, but the impact it introduced still has enduring effects. The enticing performance boost and efficiency gains make it hard to resist diving deeper into its capabilities.
Can you imagine our ever-changing tech world without high-performance and reliable data management tools? What would developers do without them?! Today I have an important task at hand: to showcase the latest improvements in our toolbox. They are truly worth exploring.
I am pretty sure the keen observers among you have already figured out where this conversation is heading—the Blazor DataGrid component. 🎉 It’s known as one of the most robust and flexible tools for handling and displaying data in Blazor applications. Today, we will talk not about its impressive functionality, but also about how much faster and more efficient it has become.
So, let’s get started together, let’s take a deeper dive into these performance gains with the Blazor DataGrid!
Performance plays a crucial role in web applications, going beyond mere speed metrics and directly impacting the overall user experience. It serves as the cornerstone for delivering an exceptional user experience across various scenarios. Every millisecond counts, as even a slight delay in page load time can result in significant losses in conversions and customer satisfaction.
Notably, the importance of performance doesn’t stop at end users—it dramatically impacts the developer experience as well. A highly performant DataGrid component simplifies data management, thereby enhancing developer productivity and efficiency.
Now, let’s delve deeper into the importance of a performant grid, especially when dealing with large datasets. Grids, such as the DataGrid component in Blazor, serve as a conduit for users to comprehend and interact with data. Regardless of how aesthetically pleasing or feature-rich your application may be, if the underlying grid handling the data falls short on performance, it can tarnish the overall user experience.
Take, for example, a financial analyst using an application to parse through vast amounts of continuously updating financial data. A slow-performing grid could hinder their efficiency and even result in missed opportunities or financial losses.
In our data-driven era, a high-performance grid has evolved from a mere luxury to an absolute necessity. It’s the backbone of real-time, seamless data interaction, empowering businesses of all sizes to leverage data-driven insights effectively.
In our R2 2023 release, we worked hard to deliver a significant improvement in the Grid performance, and we managed to take a great step forward in this direction. On average, we improved the grid performance by more than 40% when the grid is prerendered. The upcoming section will provide a detailed walk-through of how we achieved this remarkable performance enhancement.
Blazor is a fantastic framework. It marginally optimizes developer productivity and gives you an effective way to write full-stack web apps using only C#. The tradeoff is that much more communication between the browser and the C# should happen.
Blazor holds a virtual representation of all the UI elements on the page and all its state inside the memory. All the buttons, icons, inputs, sections, cells, rows and so on are represented as a different component instance in your App’s Heap. On top of that, all these component instances are constantly checked for changes and when such changes are found, the components are responsible to build their own render tree, which is the representation of the Browser’s DOM elements.
To achieve a smooth and interactive UI, Blazor often renders the whole page, which renders all other components down the render tree. This could be noticeable, especially for pages with hundreds or thousands of components.
The Grid component is such an example. We have a new component instance for each of the Grid Cells and Grid Rows. This helps us to encapsulate the state of each separate component within it and achieve a feature-rich grid enabling functionalities like Incell editing, Virtual scrolling, Templating, Accessibility, Visibility, Column Reordering, and so on. This means that if we have a grid with 200 rows and 20 columns, we have 4,000 cell components, many of which may contain buttons with icons, inputs, popups and tooltips, which are all separate component instances.
Of course, a potential performance optimization could be not to rely on separate cell components. Although this is a workable solution to the problem, when you have a complex state of your cells, the complexity of handling these states adds up fast, which could lead to bugs and an unmaintainable codebase.
Knowing that, the more rational way to optimize the re-rendering of the components is to reduce the rendering of all of the components, without sacrificing the interactivity of the components.
This process of reducing the rendering of all the components is separated in two parts:
The first step is to ensure the grid is rendered only one time on each action. This is especially valid for complex data operations, that invoke more than one event from the Grid to the outside page.
Such an example for complex data operation is the Row Selection feature. One Selection of the Grid’s row could cause selection of this row, removing selection from another row, triggering the row click event, triggering SelectedItemsChanged event, and triggering OnStateChanged event.
By default, all these events will re-render the Grid at least one time. Additionally, you cannot always rely that all these events will have attached Callbacks, so you may need to re-render the grid at least one time manually to ensure the newly selected items are shown. If you are not cautious, such a simple data operation could need multiple seconds to complete.
The second step is to skip rendering some of the inner components inside the Grid. To do that, you must know which internal components are influenced by the changes that were made and render only them. This is easier said than done.
Going back to the example with the Row Selection feature, in the typical case, you want to re-render only the changed rows, those that receive a new selection state and those that are deselected. However, we also need to consider if the developer implements a callback for SelectedItemsChanged, that alters some of the item’s values, so we need to track for any change in the state of the Cells, that are related to the re-rendering.
Leveraging these two approaches may be hard, but it is particularly useful, especially for components that can have hundreds of component instances.
Enough technical stuff. Now let me show you the result.
I will highlight three relatable use cases where the optimizations we made can be measured.
Old Incell editing
New Incell editing
This example measures the time between OnUpdate and OnEdit method, which is a good way to measure the time the Grid needs to update one time and start editing new one. The grid has 200 rows and 8 columns.
This example measures the time for render of a basic grid with 500 rows and 11 columns:
The example measures the time for rendering the grid with virtualization. The grid has 7 columns and 40 rows page size and 100,000 rows in total.
* The metrics are extracted by running 10 times each of the examples on different versions of the Telerik UI for Blazor and getting the average time. Keep in mind that Blazor WASM performance depends on the client machine performance, so the numbers could be different if run the snippets on your machine, but the relative difference should stay almost constant.
** The formula we used to calculate the performance optimization is:
((OldValue/NewValue) - 1) / 100.
And there you have it. Performance plays a crucial role in shaping the user experience, impacting not only the end users but the developers as well. Improving performance is akin to providing a smoother, more enjoyable ride for both users navigating your application and developers building it. Specifically, the performance of a grid component is of paramount importance in data-driven applications. A performant grid, capable of handling large data sets efficiently, enables seamless, real-time interaction with data. It facilitates better decision-making, more efficient workflows and successful outcomes.
With our latest R2 2023 release, we have taken our commitment to performance a step further. We are proud to announce a significant 40%+ performance boost in our Blazor DataGrid component, marking a considerable stride toward enhancing the overall user experience.
We are excited about the improved performance of our Blazor DataGrid component and look forward to hearing your feedback. We believe these improvements will significantly impact your ability to create compelling, efficient and highly responsive Blazor applications.
As we continue to refine and optimize our tools, we remain committed to supporting developers in crafting superior digital experiences. Your success is our success, and every performance gained is a step toward making your development journey smoother and more enjoyable.
Stay tuned for more updates, and here’s to building faster, more powerful applications together!
Develop new Blazor apps and modernize legacy web projects in half the time with a high-performing Grid and 100+ truly native, easy-to-customize Blazor components to cover any requirement. Try Progress Telerik UI for Blazor for free with our 30-day trial and enjoy our industry-leading support.
Kristian is a Principal Software Engineer in Progress’ Blazor team and Product Owner of Telerik REPL for Blazor. He is excited about new technologies and hard technical problems. Kristian has almost 10 years of experience in various fields of software development, including backend, frontend, cloud, scalable applications and more. You can follow him on Twitter.
Subscribe to be the first to get our expert-written articles and tutorials for developers!
All fields are required