Optimize memory footprint with the string intern pool

Origin:http://www.dotnet2themax.com/blogs/fbalena/PermaLink,guid,cecc8b4b-f362-4c59-95a1-fba055b50ec1.aspx

VB.NET and C# compilers manage string constants in a rather smart way: all strings with same value are stored in a common area known as string intern pool. The following code snippet shows this compiler feature in action:

' VB.NET
Dim s1 As String = "ABCDE"
Dim s2 As String = "ABC" & "DE"
' Prove that s1 and s2 point to the same element in the intern pool
Console.WriteLine(s1 Is s2) ' => True
// C#
string s1 = "ABCDE";
string s2 = "ABC" + "DE";
// Prove that s1 and s2 point to the same element in the intern pool
Console.WriteLine(String.ReferenceEquals(s1, s2)); // => True

 

 

This optimization technique doesn't really have any impact on the amount of memory used by most client applications, but it makes a difference if used inside types that are instantiated thousand times, as it often happens in server applications. The problem is, this optimization is applied only to string constants, not to strings built at runtime:

' VB.NET ...continuing previous example...
Dim s3 As String = "ABC"
s3 &= "DE"
' s1 and s3 contain the same value but point to a different string
Console.WriteLine(s1 = s3) ' => True
Console.WriteLine(s1 Is s3) ' => False

// C# ... continuing previous example...
string s3 "ABC";
s3 += "DE";
Console.WriteLine(s1 == s3) // => True
Console.WriteLine(String.ReferenceEquals(s1, s3) // => False

 

Now, let's suppose you have a component in the data tier and this component contains the the connection string for the database. This connection string is read from somewhere - typically the configuration file - when it's time to open the connection, therefore the compiler can't store the string in the intern pool. If this component is instantiated N times, there will be N copies of the same string in memory, which clearly is a waste if the string is long and N is high. There are two ways to avoid this waste, depending on how the connection string can vary.

If the connection string is guaranteed to be the same for all the instances, then you can store it in a static variable (a Shared variable in VB), so that the string is shared among all the instances of the component. This is the simplest case and I assume you know how to implement it, so let's move to the more interesting situation.

If the connection string can vary - for example, if the data component can connect to two or more different databases or if the connection string can use different login information - you can't store it in a static field. In this case you can resort to a technique based on the String.Intern method. This method receives a string argument and searches the argument in the intern pool: if the search is successful, the method returns a pointer to the existing string in the pool; if the search fails, the method inserts the string in the pool and returns a pointer to the element just added. Here's how you might implement the ConnectionString property in the hypothetical data component to better leverage the intern pool:

 

' VB.NET
Dim m_ConnectionString As String

Property ConnectionString() As String
   Get
      Return m_ConnectionString
   End Get
   Set(ByVal Value As String)
      m_ConnectionString = String.Intern(Value)
   End Set
End Property
 

 

// C#
private string m_ConnectionString;

public string ConnectionString
{
  get { return m_ConnectionString; }
  set { m_ConnectionString = String.Intern(value);}
}

 

The first time a given value is assigned to the ConnectionString property, the search in the pool fails, the String.Intern method adds the string in the pool and returns a pointer to the new pool element. If the same connection string is eventualy assigned to a different instance of the data component, the String.Intern pool returns a pointer to the element already in the pool and doesn't create any duplicate. The total amount of memory that the application uses is reduced and so is the number of garbage collections that occur during the application's lifetime.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值