일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 히오스
- game
- 자바
- 게임
- 에셋
- 변경된 정보
- 스랄 특성
- 나지보
- tcp
- 벨팡
- unity
- 명령어
- 안드로이드 Application Lifecycle
- End of Darkness
- 소캣(Socket)
- 나지보 특성
- 컬렉션 프레임
- 아이패드
- 리눅스
- php 홈디렉토리 변경방법
- tcp네트워크
- 기업의 행포
- 포트(Port)
- TCP 네트워크 방식의 연결
- 집 정리
- 아이폰
- 어플
- Collection Framework
- 안드로이드
- 비행기 모드
- Today
- Total
Do Something IT
String.Format() and StringBuilder 본문
참조 : 바로가기
Recently, I saw some code that looked something like this:
builder.Append(String.Format("{0} {1}", firstName, lastName));
// Do more with builder...
Now, I don't won't get into arguments about how String.Concat() is more performant here. String.Format() allows code to be more easily localized and it is being used for that purpose here. The real problem is that StringBuilder.AppendFormat() should be used instead:
builder.AppendFormat("{0} {1}", firstName, lastName);
// Do more with builder...
The reason that this is important is because, internally, String.Format() actually creates a StringBuilder and calls StringBuilder.AppendFormat()! String.Format() is implemented like this:
{
if (format == null || args == null)
throw new ArgumentNullException((format == null ? "format" : "args"));
StringBuilder builder = new StringBuilder(format.Length + (args.Length * 8));
builder.AppendFormat(provider, format, args);
return builder.ToString();
}
It turns out that the formatting logic is actually implemented in StringBuilder.AppendFormat(). So, the original code actually caused a second StringBuilder to be created when it wasn't needed.
This is also important to know if you are trying to avoid creating a StringBuilder by concatentating strings with String.Format(). For example:
+ "<td>" + String.Format("{0}, {1}", id, department) + "</td>";
That code will actually create two StringBuilders. So, creating one StringBuilder and using AppendFormat() will be more performent:
nameBuilder.Append("<td>");
nameBuilder.AppendFormat("{0} {1}", firstName, lastName);
nameBuilder.Append("</td>");
nameBuilder.Append("<td>");
nameBuilder.AppendFormat("{0}, {1}", id, department);
nameBuilder.Append("</td>");
string nameString = nameBuilder.ToString();
I decided to run some performance tests to verify my claims. First, I timed code that demonstrates the very reason that StringBuilder exists:
const string firstName = "Dustin";
const string lastName = "Campbell";
const int id = 1;
const string department = "IDE Tools Team";
static void PerformanceTest1()
{
string nameString = String.Empty;
for (int i = 0; i < LOOP_SIZE; i++)
nameString += String.Format("{0} {1}", firstName, lastName);
}
The above code creates a new string and then concatenates to it inside of a for-loop. This causes two new strings to be created on each pass--one from String.Format() and one from the concatenation. This is woefully inefficient.
Next, I tested the same code modified to use a StringBuilder with String.Format():
{
StringBuilder builder = new StringBuilder((firstName.Length + lastName.Length + 1) * LOOP_SIZE);
for (int i = 0; i < LOOP_SIZE; i++)
builder.Append(String.Format("{0} {1}", firstName, lastName));
string nameString = builder.ToString();
}
Finally, I tested code that uses StringBuilder.AppendFormat() instead of String.Format():
{
StringBuilder builder = new StringBuilder((firstName.Length + lastName.Length + 1) * LOOP_SIZE);
for (int i = 0; i < LOOP_SIZE; i++)
builder.AppendFormat("{0} {1}", firstName, lastName);
string nameString = builder.ToString();
}
These three methods ran with the following timings:
- PerformanceTest1: 1.277935 seconds
- PerformanceTest2: 0.005254 seconds
- PerformanceTest3: 0.004017 seconds
Obviously, concatenating a string in a loop without using a StringBuilder is amazing inefficient. And, removing the call to String.Format also yields a performance boost.
Next, I tested the following two methods:
{
string htmlString;
for (int i = 0; i < LOOP_SIZE; i++)
htmlString = "<td>" + String.Format("{0} {1}", firstName, lastName) + "</td><td>"
+ String.Format("{0}, {1}", id, department) + "</td>";
}
{
StringBuilder builder = new StringBuilder(256);
string htmlString;
for (int i = 0; i < LOOP_SIZE; i++)
{
builder.Append("<td>");
builder.AppendFormat("{0} {1}", firstName, lastName);
builder.Append("</td><td>");
builder.AppendFormat("{0}, {1}", id, department);
builder.Append("</td>");
htmlString = builder.ToString();
builder.Length = 0;
}
}
These two methods ran with the following timings:
- PerformanceTest4: 0.016213 seconds
- PerformanceTest5: 0.011320 seconds
As you can see, it is important to know when to use String.Format and when to use StringBuilder.AppendFormat(). While the performance boosts that can be achieved are fairly small, they are too easy to code.
You can download the performance tests here: StringFormatPerfTest.zip (4.12 KB).
'Unity3D > Optimization' 카테고리의 다른 글
유니티3D 게임 리소스 최적화? 3가지만 기억해라 (0) | 2014.12.11 |
---|---|
Memory profiling in Unity (0) | 2014.07.22 |
효과적인 C# 메모리 관리 기법 (0) | 2014.05.07 |
[Unity] 유니티의 메모리 관리 (0) | 2014.03.26 |
Unity 최적화 (0) | 2014.03.10 |