This article is completely separate from the previous two articles. If you like them, I hope you’ll like this one, too. In the last article, I showed which approach is faster and compared the execution speed of the code. In this article, I’ll show memory consumption for different snippets of code. To display the memory mapping and allocation graph, I used the 32-bit version of the CLR Profiler and, as usual, 4GB of RAM and a Core I3 CPU on the Windows platform. The memory consumption or allocation graph can vary depending on the process the system is running. So if you get a different output or behavior from the code, then please share your experience with us.
Let’s begin our journey through “5 tips for improving c# code: part 3”.
StringBuilder consumes less memory than String
In my last article, I showed how slow strings can be in the long-connect scenario. Here we see a memory allocation diagram for strings and StringBuilder. Let me show you. Here’s my code for doing the same with strings and StringBuilder.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Net; using System.Net.NetworkInformation; using System.Threading; using System.Globalization; using System.Data.SqlClient; namespace Test1 { public class Test1 { string Name ; public void Process() { Name = Name + "A"; } } public class Test2 { StringBuilder sb = new StringBuilder(); public void Process() { sb.Append("A"); } } class Program { static void Main(string[] args) { Test1 t = new Test1(); t.Process(); Test2 t1 = new Test2(); t1.Process(); }}}Copy the code
This is the memory allocation diagram for code execution.
Here we call two functions Process() from main; Although they both have the same name, they belong to different classes and test1.process handles string data, while test2.process () handles StringBuilder data. In the allocation diagram, we can see that the string handler consumes 94% of the resources of Main(), while the StringBuilder Process() of the Test2 class consumes only 0.21% of the resources of Main().
Thus, the conclusion is “Always use StringBuilder when you want to concatenate strings more than once.”
If possible, use static functions
Yes, try to implement a static function if possible, because static objects (functions and data) do not belong to any object of a particular class. That’s what we all have. Therefore, if you do not create objects, there is no memory consumption problem. Below I’ll show an example of a static function and a static class. Take a look at the IL code.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Net; using System.Net.NetworkInformation; using System.Threading; using System.Globalization; using System.Data.SqlClient; namespace Test1 { public static class mySclass { public static void Print() { Console.Write("Hello"); } } public class myNclass { public static void Print() { Console.Write("Hello"); } } class Program { static void Main(string[] args) { for (int i = 0; i < 1000; i++) { mySclass.Print(); myNclass.Print(); }}}}Copy the code
The IL code is on the left hand side, and on the right hand side are the memory consuming classes retrieved by the CLR parser. Due to space consumption, I can’t show a full screenshot of the CLR profiler. But trust me, static classes or functions have no memory allocation.
Therefore, the conclusion is “if possible, try to create a static function and call it using the class name instead of calling a generic function by the object name”.
String formatting VS string concatenation
In the first point, I showed how strings consume more resources than StringBuilder. At this point, I’ll compare formatted output with string concatenation. In the first function, I used a format specification to print the formatted output (basically concatenating a string). In another function, I use the (+) operator to concatenate a string, as follows:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Net; using System.Net.NetworkInformation; using System.Threading; using System.Globalization; using System.Data.SqlClient; namespace Test1 { class Test { public void Format() { int a = 100; Console.WriteLine("{0}AND{1}", a, a); } public void Concatination() { int a = 100; Console.WriteLine(a + "AND" +a ); } } class Program { static void Main(string[] args) { Test t = new Test(); t.Format(); t.Concatination(); Console.ReadLine(); }}}Copy the code
In memory allocation we see:
A function that prints strings in format consumes 57% of the resources, while a function that simply concatenates two strings consumes 30% of the resources of the main function. Therefore, it is clear that system resources can be saved if string concatenation is used instead of output formatting.
Which class in an empty program consumes the most resources?
First, this point does not recommend any best practice techniques. I’m just saying, if we run an empty program with only one Main() function, how much memory is allocated? Here is a very simple program of mine.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test1
{
class Program
{
static void Main(string[] args)
{
}
}
}
Copy the code
A function that prints strings in format consumes 57% of the resources, while a function that simply concatenates two strings consumes 30% of the resources of the main function. Therefore, it is clear that system resources can be saved if string concatenation is used instead of output formatting.
Which class in an empty program consumes the most resources?
First, this point does not recommend any best practice techniques. I’m just saying, if we run an empty program with only one Main() function, how much memory is allocated? Here is a very simple program of mine.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test1
{
class Program
{
static void Main(string[] args)
{
}
}
}
Copy the code
Yeah, I didn’t write anything in this program. Let’s look at memory mapping.
Here, I show the six most expensive classes associated with running an empty program scenario. You can clearly see that the String class takes up the most resources (25% of the total). Now, questions. In a program where we never use strings, why does the string class consume the most resources? If we look at the call diagram of this program, we’ll see that there are many internal functions called in the main function, most of which take strings as arguments. To generate these arguments, the CLR usually uses the String class. If you have a different opinion, please use the comment box below.
Implement a using block to manage memory
It is a best practice to always implement a using block to manage resources. In fact, we can prove that using block statements consumes less memory than not using block statements. We know that the block code size may be larger if we implement a using block because internally the using block creates a try catch in the IL code, but once it is implemented in the IL code at run time, it effectively handles system memory. To demonstrate this, I wrote a simple program that looks like this:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.IO; using System.Net; using System.Net.NetworkInformation; using System.Threading; using System.Globalization; using System.Data.SqlClient; namespace Test1 { class Test { public void Test1() { StreamWriter wr = new StreamWriter(@"D:\text.txt"); } public void Test2() { using (StreamWriter wr = new StreamWriter(@"D:\abc.txt")) { } } } class Program { static void Main(string[] args) { Test t = new Test(); t.Test1(); t.Test2(); }}}Copy the code
In the output section, I combined three output screens.
In the allocation diagram, we see that using blocks consume fewer resources than without them, because if we implement using blocks, the program can manage memory efficiently.
Welcome to pay attention to my public number – code non translation station, if you have a favorite foreign language technical articles, you can recommend to me through the public number message.