Dynamic Program Analysis (DPA)
It's a good idea to regularly do exploratory profiling of your applications. That takes time, and as a result, profiling is often only done after an application starts misbehaving, in production.
Dynamic Program Analysis (or DPA) performs automatic analysis of memory and allocations, and runs in the background of Rider. It checks your application for various memory allocation issues, such as closures and allocations to large and small object heaps (LOH and SOH).
Allocation data is collected automatically, with almost zero overhead, making DPA a useful tool to catch memory issues before pushing an application to production.
Optimize Memory Pressure based on DPA
In the previous step, we concluded that the constructor of
Cell is on the hot path, and we are causing too much
memory traffic overall. If you run the Sudoku solver, Dynamic Program Analysis will detect several issues. The top issue
is excessive allocation of the
Cell type indeed!
Optimizing the issue with
Cell can be done by making it a
struct instead of a
class, as described here.
This will move
Cell from the heap to the stack, and reduce the need for garbage collection. Since all
Cell are short-lived
and don't take up much memory per instance, it's safe to move these to the stack.
Optimize Closures using DPA
When you use Language Integrated Query (LINQ), or a lot of
async/await, the compiler may have to generate hidden classes
that "capture" the current value of a variable. These allocations are not always obvious, and it may not be required to
optimize them at all.
However, when they happen on a hot path, they may matter after all. If a hidden allocation is done often, again, your application may experience high memory traffic.
When you work with DPA, it's a good idea to use its companion: the Heap Allocations Viewer plugin. Using the Heap Allocations Viewer plugin may help clarify where memory is allocated, so you can optimize code.
In the Sudoku solver, you can optimize a call to
.FirstOrDefault() by converting the LINQ statement into a
loop instead, so you don't require capturing an existing variable.
There are various other memory issues that you can discover when using Dynamic Program Analysis. Check our list of fixes for issues found by DPA to learn more.