String.Replace () 대 StringBuilder.Replace ()
마커를 사전의 값으로 대체해야하는 문자열이 있습니다. 가능한 한 효율적이어야합니다. string.replace를 사용하여 루프를 수행하면 메모리가 소모됩니다 (문자열은 변경 불가능합니다. 기억하세요). StringBuilder.Replace ()가 문자열 조작과 함께 작동하도록 설계되었으므로 더 좋을까요?
나는 RegEx의 비용을 피하고 싶었지만 그것이 더 효율적이라면 그렇게 될 것입니다.
참고 : 코드의 복잡성은 신경 쓰지 않고 실행 속도와 소비하는 메모리 만 중요합니다.
평균 통계 : 길이는 255-1024 자, 사전에는 15-30 개의 키가 있습니다.
다음 코드를 사용하여 RedGate 프로파일 러 사용
class Program
{
static string data = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
static Dictionary<string, string> values;
static void Main(string[] args)
{
Console.WriteLine("Data length: " + data.Length);
values = new Dictionary<string, string>()
{
{ "ab", "aa" },
{ "jk", "jj" },
{ "lm", "ll" },
{ "yz", "zz" },
{ "ef", "ff" },
{ "st", "uu" },
{ "op", "pp" },
{ "x", "y" }
};
StringReplace(data);
StringBuilderReplace1(data);
StringBuilderReplace2(new StringBuilder(data, data.Length * 2));
Console.ReadKey();
}
private static void StringReplace(string data)
{
foreach(string k in values.Keys)
{
data = data.Replace(k, values[k]);
}
}
private static void StringBuilderReplace1(string data)
{
StringBuilder sb = new StringBuilder(data, data.Length * 2);
foreach (string k in values.Keys)
{
sb.Replace(k, values[k]);
}
}
private static void StringBuilderReplace2(StringBuilder data)
{
foreach (string k in values.Keys)
{
data.Replace(k, values[k]);
}
}
}
- String.Replace = 5.843ms
- StringBuilder.Replace # 1 = 4.059ms
- Stringbuilder.Replace # 2 = 0.461ms
문자열 길이 = 1456
stringbuilder # 1은 메서드에서 stringbuilder를 생성하지만 # 2는 그렇지 않으므로 해당 작업을 메서드 밖으로 이동하기 때문에 성능 차이가 거의 동일하게됩니다. 문자열 대신 stringbuilder로 시작하면 # 2가 대신 사용할 수 있습니다.
메모리에 관한 한 RedGateMemory 프로파일 러를 사용하면 stringbuilder가 전반적으로 승리 할 많은 교체 작업에 들어갈 때까지 걱정할 필요가 없습니다.
도움이 될 수 있습니다.
짧은 대답은 String.Replace가 더 빠르지 만 메모리 공간 / 가비지 수집 오버 헤드에 더 큰 영향을 미칠 수 있다는 것입니다.
예, StringBuilder속도와 메모리의 이득을 모두 제공합니다 (기본적으로 조작 할 때마다 문자열의 인스턴스를 생성하지 않기 때문에 StringBuilder항상 동일한 객체로 작동합니다). 다음은 몇 가지 세부 사항 이있는 MSDN 링크 입니다.
stringbuilder.replace가 [String.Replace보다] 더 좋을까요?
예, 훨씬 좋습니다. 그리고 새 문자열의 상한을 추정 할 수 있다면 (할 수있는 것처럼 보임) 아마도 충분히 빠를 것입니다.
다음과 같이 만들면 :
var sb = new StringBuilder(inputString, pessimisticEstimate);
그러면 StringBuilder가 버퍼를 다시 할당 할 필요가 없습니다.
Converting data from a String to a StringBuilder and back will take some time. If one is only performing a single replace operation, this time may not be recouped by the efficiency improvements inherent in StringBuilder. On the other hand, if one converts a string to a StringBuilder, then performs many Replace operations on it, and converts it back at the end, the StringBuilder approach is apt to be faster.
Rather than running 15-30 replace operations on the entire string, it might be more efficient to use something like a trie data structure to hold your dictionary. Then you can loop through your input string once to do all your searching/replacing.
It will depend a lot on how many of the markers are present in a given string on average.
Performance of searching for a key is likely to be similar between StringBuilder and String, but StringBuilder will win if you have to replace many markers in a single string.
If you only expect one or two markers per string on average, and your dictionary is small, I would just go for the String.Replace.
If there are many markers, you might want to define a custom syntax to identify markers - e.g. enclosing in braces with a suitable escaping rule for a literal brace. You can then implement a parsing algorithm that iterates through the characters of the string once, recognizing and replacing each marker that it finds. Or use a regex.
My two cents here, I just wrote couple of lines of code to test how each method performs and, as expected, result is "it depends".
For longer strings Regex seems to be performing better, for shorter strings, String.Replace it is. I can see that usage of StringBuilder.Replace is not very useful, and if wrongly used, it could be lethal in GC perspective (I tried to share one instance of StringBuilder).
Check my StringReplaceTests GitHub repo.
The problem with @DustinDavis' answer is that it recursively operates on the same string. Unless you're planning on doing a back-and-forth type of manipulation, you really should have separate objects for each manipulation case in this kind of test.
I decided to create my own test because I found some conflicting answers all over the Web, and I wanted to be completely sure. The program I am working on deals with a lot of text (files with tens of thousands of lines in some cases).
So here's a quick method you can copy and paste and see for yourself which is faster. You may have to create your own text file to test, but you can easily copy and paste text from anywhere and make a large enough file for yourself:
using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Windows;
void StringReplace_vs_StringBuilderReplace( string file, string word1, string word2 )
{
using( FileStream fileStream = new FileStream( file, FileMode.Open, FileAccess.Read ) )
using( StreamReader streamReader = new StreamReader( fileStream, Encoding.UTF8 ) )
{
string text = streamReader.ReadToEnd(),
@string = text;
StringBuilder @StringBuilder = new StringBuilder( text );
int iterations = 10000;
Stopwatch watch1 = new Stopwatch.StartNew();
for( int i = 0; i < iterations; i++ )
if( i % 2 == 0 ) @string = @string.Replace( word1, word2 );
else @string = @string.Replace( word2, word1 );
watch1.Stop();
double stringMilliseconds = watch1.ElapsedMilliseconds;
Stopwatch watch2 = new Stopwatch.StartNew();
for( int i = 0; i < iterations; i++ )
if( i % 2 == 0 ) @StringBuilder = @StringBuilder .Replace( word1, word2 );
else @StringBuilder = @StringBuilder .Replace( word2, word1 );
watch2.Stop();
double StringBuilderMilliseconds = watch1.ElapsedMilliseconds;
MessageBox.Show( string.Format( "string.Replace: {0}\nStringBuilder.Replace: {1}",
stringMilliseconds, StringBuilderMilliseconds ) );
}
}
I got that string.Replace() was faster by about 20% every time swapping out 8-10 letter words. Try it for yourself if you want your own empirical evidence.
참고URL : https://stackoverflow.com/questions/6524528/string-replace-vs-stringbuilder-replace
'Program Club' 카테고리의 다른 글
| Android 잠금 화면 위젯 (0) | 2020.10.24 |
|---|---|
| jQuery .val ()과 .attr ( 'value')의 차이점은 무엇입니까? (0) | 2020.10.24 |
| jQuery가 requestAnimationFrame을 사용하지 않는 이유는 무엇입니까? (0) | 2020.10.24 |
| CMake를 사용하여 CFLAGS 및 CXXFLAGS 옵션 설정 (0) | 2020.10.24 |
| 하나의 도메인 이름에 여러 개의 해당 IP 주소가있을 수 있습니까? (0) | 2020.10.24 |