How to optimize high memory allocation for String types
Hi Team,
I am trying to optimize the memory allocation of string types. In back traces the methods are listed as we can see in below screenshot.
I m able to understand what to fix about the Concat related methods(like use StringBuilder instead of + operator)
but I do not understand and not able to find out that how to optimize or fix the high memory allocation for other methods listed in back traces like.
1. CreateStringFromEncoding (How to fix ?)
2. ToString (How to fix ?)
3. CtorCharCount (How to fix ?)
4.ToUpper (How to fix ?)
5. InternalSubString (How to fix ?)
These above methods have above 1GB of memory allocation.
How can I find out the exact classes ,methods and objects which causes the high memory allocation for above method list.
Could you please help me with some examples how can I optimize or fix the above methods?
Also attaching the workspace , and will be very grateful if you please look into it and suggest as per your opinion what are the major issues in it.
Is managed heap allocation is fine in this workspace?
Thanks
PFA :
Upload id: 2022_02_10_4KexF2uoSUYPTKrg
Please sign in to leave a comment.
You should expand back traces tree to find methods from your code where these objects are created, e.g. the first Concat method which allocates ~77GB is called from code relates to logging:
This memory amount can be decreased by introducing log level system in your application and write only "info" logs without additional data by default.
CreateStringFromEncoding and some other nodes comes from MongoDB.Bson. Most likely it allocates a lot of data when the database contains huge number of strings. You can reduce this traffic by optimizing the database but this can be over-optimized if the database query rate is high enough.
Thanks Anna Guseva,
Yes When I expand back traces tree I am able to find the methods related with my application. But I m not sure about the solutions for this , like I found one article about string concatenation at jetbrains blog, so able to understand how we can find out and fix the issues (https://blog.jetbrains.com/dotnet/2014/07/17/unusual-ways-of-boosting-up-app-performance-strings/).
But for the below category/methods not able to understand how can we identify the main culprit in our methods and how to fix it.
2. ToString (How to find and fix the issue ?)
3. CtorCharCount (How to find and fix the issue ?)
4.ToUpper (How to find and fix the issue ?)
5. InternalSubString (How to find and fix the issue ?)
If I expand the ToString I can easily find out the methods of my application but not understand how to fix ToString related high memory consumption similarly for other categories/methods. Please help with some examples to fix above.
Also in dotMemory toll I m not found any tips and suggestions to fix high memory allocation for all listed methods . Generaly if the problem is identified then for its solutions some tips and suggestions are given.
Could you please suggest, maximum how much memory allocation for a single method is considerable.
And also want your valuable comment on the captured sanpshot, if you see the Sanpshot#4, its total memory allocation is
2.16GB --total
1.70GB --.Net total
263.73MB -- .Net used.
Is this OK or it is very high?, my RAM is 16 GB ?
And also not able to understand the Generations diagram . Is there any thing in this generation's diagram for which we would to worry about or anything that needs to be fix ?
Upload id: 2022_02_10_4KexF2uoSUYPTKrg
Thanks
Why do you decide there are any issues related to this allocations? The article you mentioned above explains the certain case with boxing and gives an example of how to fix it via StringBuilder class. If you have any boxing in your code on this stack trace (you can check it e.g. via ReSharper) and it causes a lot of allocations, you can fix it this way. In other case, there is no universal instructions how to fix allocations in the applications. Besides, it is not very clear why they need to be fixed because the code allocates objects and this is normal as long as it does not cause any performance issues.
dotMemory presents all objects allocated by your application on selected time interval. It does not mean that you need to do something about it. Allocations view should help you to find out what objects were allocated on this interval and what functions allocated these objects.
If you really have performance issues on this time interval, first of all, you should fix the most obvious parts (excessive logging in your case) and then continue to investigate if problem still persists. There is no universal way how to reduce strings count in your application, it’s unique for the certain code. As I wrote in previous message, you can reduce some traffic e.g. by optimizing the database. In other cases, you should analyse your code and search the way how to reduce strings count.
There is no such value. The value which would be very good e.g. for an IDE, will be catastrophically large for some other applications. Besides, the amount of allowed memory depends on the system requirements of your application.
Snapshot contains information about Total, .NET Total and .NET Used memory values.
Total memory consists of "unmanaged" memory and ".NET, total" memory. Usually, this size is similar to Windows Task Manager's Commit size: the amount of memory requested by a process.
Unmanaged memory is memory allocated outside of the managed heap and not managed by Garbage Collector. Generally, this is the memory required by .NET CLR, dynamic libraries, graphics buffer, and so on. This part of memory cannot be analysed in dotMemory.
.NET, total is the amount of memory in the managed heap used by the app including free space between allocated objects. .NET, total = ".NET, used" + free memory. Free memory may be reserved by CLR to perform future allocations faster. You can't affect this CLR behaviour. Anyway, free memory should be released in case of lack of resources.
".NET, used" is the amount of memory in the managed heap used by the app excluding free space. This is the only part of memory .NET allows you to work with. You can get all these objects in dotMemory snapshot.
Actually, 263.73MB survived objects after GC for an application which allocates gigabytes of objects looks really good.
Your application allocates a lot of objects and CLR keeps free space to perform future allocations faster in LOH and in Gen0. That’s why you see a lot of free space here. You don’t need to worry about this because you can’t affect this behaviour.