Oct 27

How to load parent and child route data at the same time with Angular's router resources

A resolver on a parent route and one on its child run one after the other, so a nested tab waits for both requests in a row. Angular 22.2's router resources start them together. On a 400 ms parent and a 600 ms child, the tab showed up after about 620 ms instead of 1,020 ms. Block only on the data the page can't draw without.

angular · performance · 5 min
→
Oct 21

Keep an Excel export library out of Angular's first download with injectAsync

In a small Angular 22 app, exceljs was 945 kB of a 1,057 kB first download, all for one Export button. Moving that one service behind injectAsync cut the first download to 112 kB. Keep every other import of the library type-only, and check ng build's initial total before and after.

angular · performance · 5 min
→
Oct 12

How EF Core 10 translates Contains over a list of IDs, and when to change it

EF Core 10 sends a Contains over a local list as one SQL parameter per value, padded to fixed sizes, where EF Core 8 and 9 sent one JSON parameter. Short lists get real row estimates. Long lists get slow: 2,000 IDs took about 49 ms against 3 ms in the JSON form on SQL Server. Keep the new default, and move the long-list query back with EF.Parameter.

dotnet · performance · 5 min
→
Oct 01

What decides whether SearchValues<string> beats a Contains loop

A loop of Contains reads the text once per keyword; SearchValues<string> reads it once. At eight keywords that is a fifth of the time. At forty of the same kind of keyword the loop wins, because string.Contains is vectorised and what costs in the single pass is how often its SIMD prefilter stops to verify a candidate.

dotnet · performance · 8 min
→
Sep 24

Server-side paging with Tabulator and ASP.NET Core MVC

In remote mode Tabulator asks an MVC controller for one page, expects data and last_page back, and reads last_row when it is there. Two things bite on the way: the bracketed query string it sends binds to an empty list under MVC's default value providers, and the column name it asks you to sort by is a string the browser chose.

dotnet · performance · 7 min
→
Sep 15

Why your @defer block still shipped in the main bundle

An @defer block only moves a component into a lazy chunk when the deferred dependency is standalone and nothing else in the same file refers to it. When something does, Angular falls back to loading it eagerly with no warning: the placeholder still renders and the content still arrives on the trigger, while the code sits in the initial bundle. Seven builds of the same block, measured, plus the one-line check that tells you which case you are in.

angular · performance · 7 min
→
Aug 27

Stream your export: 6.3 seconds to first byte becomes 29 milliseconds

A buffered export reads every row before it answers. Over the same source, streaming the rows moved time-to-first-byte from 6.3 seconds to 29 milliseconds and peak heap from 39 MB to 17 MB — without finishing much sooner or sending a byte less. The costs are real too, and one of them arrives as a 200.

dotnet · performance · 6 min
→
Aug 25

AsSplitQuery: why a second Include returns 6,000 rows instead of 510

One collection Include is a join. The second one at the same level is a cross product: in the demo, 6,000 rows and 1.6 MB where 510 rows and 78 KB would do. AsSplitQuery fixes it, and in EF 10 the Skip/Take paging behind it also stopped being a correctness risk.

dotnet · performance · 6 min
→
Aug 18

CancellationToken: stop doing work for callers who already left

ASP.NET Core can tell when a caller disconnects. Most handlers never ask. What CancellationToken actually does, where to pass it, and where to be careful.

dotnet · performance · 6 min
→
Aug 04

HybridCache stops the cache stampede that IMemoryCache allows

GetOrCreateAsync on IMemoryCache lets every concurrent request run the factory on a cold key. HybridCache's single-flight fixes the stampede you only meet under load.

dotnet · performance · 5 min
→