Open gao-artur opened 5 months ago
Note that the StringBuilder.GetChunks
can be added to older frameworks with Polyfill if you are open to adopting this library. It can bring the newest and fastest API to older TFMs, and improve code maintainability (by removing all the #if NET6_0_OR_GREATER
etc). The only drawback is increased assembly size because Polyfill adds all these APIs as source code into your code base.
@ThomasHoevel any feedback on this? I just wait for a green light from you to create PRs.
Since you asked me...
Where to start?
GitHub is not our development repository and we never accept PRs here. But creating PRs here is one way to propose code changes.
I tagged you because I saw you are actively answering issues. Sorry if I tagged the wrong person. The proposed changes concern memory allocation, not execution time. But of course, reducing the amount of garbage produced will also improve time. I just don't want to invest time in changes that won't be accepted for any reason. Once I get a sign of interest in this optimization I'll be happy to create a PR.
Hi. We are using this library to create Pdf reports with large tables. I did some benchmarks, and the memory allocations didn't look good, so I did some profiling to find where it could be improved. My benchmark includes creating a table with 15 columns and 2500 rows. Here are the initial results:
And here are the dotMemory allocation analysis results:
Then, I did a few simple optimizations and was able to reduce the allocations from 589.81 MB to 528.62 MB. Not huge, but it was just a POC to see how difficult it is to handle different cases.
The changes I applied here:
StringBuilder
pool in a few places (PdfFlattenVisitor.VisitDocumentObjectCollection
,XGraphicsPdfRenderer._content
,PdfEncoders.FormatStringLiteral
)Used StringBuilder.GetChunks in a few places to avoid intermediate string allocation.
Many other places can be optimized with different levels of effort. For example, you can reduce 3 more MB by passing
StringComparer.InvariantCultureIgnoreCase
intoFontDescriptorCache
constructor and removingname = name.ToLowerInvariant();
from theFontDescriptor.ComputeFdKey
method. And even more by creating astruct
key that will includeisBold
andisItalic
booleans and avoid creating a new string at all.Also, from what I have seen, most of the renderers are one-time use, so making them reusable will eliminate a lot of short-living object creation:
Let me know if you are interested in accepting PR's with these and other changes around memory allocations.