문자열 보간 대 문자열.서식
문자열 보간을 사용하는 것 사이에 현저한 성능 차이가 있습니까?
myString += $"{x:x2}";
vs 문자열.형식()?
myString += String.Format("{0:x2}", x);
ReSharper가 수정을 요청하고 있고, 전에 속아본 적이 있기 때문에 묻는 것입니다.
주목할 만한 것은 상대적인 것입니다.나:.string.Format()
컴파일 타임에 그들은 결국 같은 결과로 끝나야 합니다.
하지만 미묘한 차이가 있습니다. 이 질문에서 알 수 있듯이 형식 지정자의 문자열 연결은 추가적인 결과를 가져옵니다.string.Concat()
러.
대답은 '그렇다'와 '아니오' 둘 다 입니다.ReSharper
가장 성능이 뛰어난 세 번째 변형을 보여주지 않음으로써 여러분을 속이는 것입니다.나열된 두 가지 변형은 동일한 IL 코드를 생성하지만, 다음과 같은 것이 실제로 강화됩니다.
myString += $"{x.ToString("x2")}";
전체테스트코드
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Running;
namespace StringFormatPerformanceTest
{
[Config(typeof(Config))]
public class StringTests
{
private class Config : ManualConfig
{
public Config() => AddDiagnoser(MemoryDiagnoser.Default, new EtwProfiler());
}
[Params(42, 1337)]
public int Data;
[Benchmark] public string Format() => string.Format("{0:x2}", Data);
[Benchmark] public string Interpolate() => $"{Data:x2}";
[Benchmark] public string InterpolateExplicit() => $"{Data.ToString("x2")}";
}
class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<StringTests>();
}
}
}
시험결과
| Method | Data | Mean | Gen 0 | Allocated |
|-------------------- |----- |----------:|-------:|----------:|
| Format | 42 | 118.03 ns | 0.0178 | 56 B |
| Interpolate | 42 | 118.36 ns | 0.0178 | 56 B |
| InterpolateExplicit | 42 | 37.01 ns | 0.0102 | 32 B |
| Format | 1337 | 117.46 ns | 0.0176 | 56 B |
| Interpolate | 1337 | 113.86 ns | 0.0178 | 56 B |
| InterpolateExplicit | 1337 | 38.73 ns | 0.0102 | 32 B |
신규시험결과(.)NET 6)
테스트를 다시 실행합니다..NET 6.0.9.41905, X64 RyuJIT AVX2
.
| Method | Data | Mean | Gen0 | Allocated |
|-------------------- |----- |----------:|-------:|----------:|
| Format | 42 | 37.47 ns | 0.0089 | 56 B |
| Interpolate | 42 | 57.61 ns | 0.0050 | 32 B |
| InterpolateExplicit | 42 | 11.46 ns | 0.0051 | 32 B |
| Format | 1337 | 39.49 ns | 0.0089 | 56 B |
| Interpolate | 1337 | 59.98 ns | 0.0050 | 32 B |
| InterpolateExplicit | 1337 | 12.85 ns | 0.0051 | 32 B |
InterpolateExplicit()
다가 더 빠릅니다.string
. 포맷할 개체를 박스에 넣을 필요가 없습니다.복싱은 정말 돈이 많이 듭니다.참고할 점은NET 6
모든 방법에 대해 CPU 및 메모리 할당을 모두 줄였습니다.
신규시험결과(.)NET 7)
테스트를 다시 실행합니다..NET 7.0.122.56804, X64 RyuJIT AVX2
.
| Method | Data | Mean | Gen0 | Allocated |
|-------------------- |----- |----------:|-------:|----------:|
| Format | 42 | 41.04 ns | 0.0089 | 56 B |
| Interpolate | 42 | 65.82 ns | 0.0050 | 32 B |
| InterpolateExplicit | 42 | 12.19 ns | 0.0051 | 32 B |
| Format | 1337 | 41.02 ns | 0.0089 | 56 B |
| Interpolate | 1337 | 59.61 ns | 0.0050 | 32 B |
| InterpolateExplicit | 1337 | 13.28 ns | 0.0051 | 32 B |
이후 큰 ..NET 6
.
C#10 및 에서 문자열 보간에 대한 상당한 최적화가 있었음을 유의해야 합니다.NET 6 - C# 10 및 .의 문자열 보간.NET 6.
저는 문자열 형식뿐만 아니라 문자열 연결의 모든 용도를 문자열 보간을 사용하기 위해 마이그레이션해 왔습니다.
저는 다른 방법들 간의 메모리 할당 차이에 대해 더 관심을 가질 것입니다.문자열 인터폴레이션은 적은 수의 문자열로 작업할 때 속도와 메모리 할당 모두에서 거의 항상 유리하다는 것을 발견했습니다.지정되지 시 알 수 경우 은는)다를 System.Text.StringBuilder.Append(xxx)
아니면System.Text.StringBuilder.AppendFormat(xxx)
당신의 .+=
문자열 연결에 사용할 수 있습니다.매우 조심하고 적은 수의 줄에 대해서만 주의해야 합니다.
그 문제는 성능에 관한 것이었는데 제목에 "vs"라고만 쓰여 있어서 몇 점을 더 추가해야 할 것 같아요, 그 중 일부는 의견이 있습니다.
현지화
- 문자열 보간은 인라인 코드 특성 때문에 지역화할 수 없습니다.에다로 .
string.Format
(:ReSharper
).
- 문자열 보간은 인라인 코드 특성 때문에 지역화할 수 없습니다.에다로 .
유지가능성(나의 의견)
string.Format
문장에 초점을 맞추기 때문에 훨씬 더 가독성이 높습니다. 예를 들어, 멋지고 의미 있는 오류 메시지를 작성할 때 말입니다.사용.{N}
자리 표시자는 제게 더 많은 유연성을 주고 나중에 수정하는 것이 더 쉽습니다.- 또한 보간에서 인라인 형식 지정자는 잘못 읽히기 쉽고, 변경 시 식과 함께 삭제하기 쉽습니다.
- 복잡하고 긴 표현을 사용하는 경우 보간은 읽기와 유지가 더 어려워지기 때문에 코드가 진화하고 복잡해질 때 확장이 잘 되지 않습니다.
string.Format
이런 일이 일어나기 쉬운 건 아닙니다 - 결국, 모든 것은 우려의 분리에 관한 것입니다.저는 그것이 제시해야 할 내용과 제시해야 할 내용을 혼합하는 것을 좋아하지 않습니다.
그래서 이것들을 바탕으로, 저는 계속하기로 결정했습니다.string.Format
대부분의 내 암호대로라면하지만 제가 훨씬 더 좋아하는 코딩을 좀 더 유창하게 하기 위해 확장 방법을 준비했습니다.확장의 구현은 원-라이너이며, 단순히 사용 중인 것처럼 보입니다.
var myErrorMessage = "Value must be less than {0:0.00} for field {1}".FormatWith(maximum, fieldName);
인터폴레이션은 훌륭한 기능입니다. 오해하지 마세요.다 IMO라는 빛납니다.string.Format
예를 들어 자바스크립트와 같은 기능입니다.
이 .string.Format()
컴파일 타임에
string.Format()
에 대해 할 수 있고, 출력 형식을 할 수 있습니다 .
하지만 문자열 보간이 더 읽기 쉬운 것 같습니다.그러니까, 당신한테 달렸어요.
a = string.Format("Due date is {0:M/d/yy} at {0:h:mm}", someComplexObject.someObject.someProperty);
b = $"Due date is {someComplexObject.someObject.someProperty:M/d/yy} at {someComplexObject.someObject.someProperty:h:mm}";
사용 가능한 성능 테스트 결과는 다음과 같습니다.
늦었을 도 있지만 한 것을하지 못했습니다. 가 것을 . 나는 그것을 알아차렸습니다.+=
당신의 질문에 연산자가 있습니다.이 작업을 주기적으로 실행하는 것의 16진수 출력을 생성하는 것 같습니다.
)+=
할 수 ), .OutOfMemoryException
쓰레기장을 분석하는 동안 안에 수많은 여유 메모리가 있을 것입니다!
어떻게 되는 거지?
- 메모리 관리자는 결과 문자열을 저장할 수 있는 충분한 연속 공간을 찾습니다.
- 연결된 문자열이 적혀 있습니다.
- 원래 왼쪽 변수의 값을 저장하는 데 사용되는 공간입니다.
1단계에서 할당된 공간은 3단계에서 해방된 공간보다 확실히 더 큽니다.
다음 사이클에서도 동일한 현상이 발생합니다.각 주기마다 10바이트 길이의 문자열이 원래 20바이트 길이의 문자열에 3번 추가되었다고 가정하면 우리의 메모리는 어떻게 보일까요?
[20바이트 사용 가능]X1[30바이트 사용 가능]X2[40바이트 사용 가능]X2[50바이트 할당됨]
(왜냐하면 사이클 중에 메모리를 사용하는 다른 명령어들이 있을 것이 거의 확실하기 때문입니다. 저는 메모리 할당을 설명하기 위해 Xn-s를 배치했습니다.이것들은 자유로워질 수도 있고 여전히 할당될 수도 있습니다. 저를 따라오세요.)
다음 할당 시 MM에서 충분한 크기의 연속 메모리(60바이트)가 발견되지 않으면 OS에서 가져오거나 콘센트의 여유 공간을 재구성하여 가져오려고 합니다.X1과 X2는 (가능한 경우) 어딘가로 이동될 것이고 20+30+40 연속 블록이 사용 가능하게 될 것입니다.시간이 걸리지만 사용 가능합니다.
그러나 블록 크기가 88kb(google for it why 88kb)에 도달하면 Large Object Heap에 할당됩니다.이곳의 무료 블록은 더 이상 압축되지 않습니다.
따라서 문자열 += 연산 결과가 이 크기를 초과하는 경우(예: CSV 파일을 구축하거나 메모리에 무엇인가를 이런 식으로 렌더링하는 경우), 위 사이클을 통해 계속해서 크기가 증가하는 빈 메모리 덩어리가 생성되고, 그 합계는 기가바이트가 될 수 있습니다.하지만 앱이 1Mb 정도의 작은 블록을 할당할 수 없기 때문에 앱이 OOM으로 종료됩니다. 왜냐하면 어떤 청크도 충분히 크지 않기 때문입니다.
긴 설명 죄송합니다만, 몇 년 전에 일어난 일이라 힘든 교훈이었습니다.저는 그 이후로 스트링 콘캣의 부적절한 사용에 맞서 싸우고 있습니다.
에 대한 .String.Format()
마이크로소프트 사이트에서 다음을 확인할 수 있습니다.
https://learn.microsoft.com/en-us/dotnet/api/system.string.format?view=net-6.0#remarks
String을 부르는 대신에.형식 방법 또는 복합 형식 문자열을 사용하여 언어가 지원하는 경우 보간 문자열을 사용할 수 있습니다.보간 문자열은 보간된 식을 포함하는 문자열입니다.보간된 각 식은 식의 값으로 해결되며 문자열이 할당되면 결과 문자열에 포함됩니다.
언급URL : https://stackoverflow.com/questions/32342392/string-interpolation-vs-string-format
'programing' 카테고리의 다른 글
R의 MySQL에서 UTF-8 텍스트를 가져오면 "???"가 반환됩니다. (0) | 2023.09.28 |
---|---|
404를 유사한 URL로 리디렉션 (0) | 2023.09.28 |
동일한 테이블에 여러 인덱스를 동시에 만들 수 있는 데이터베이스가 있습니까? (0) | 2023.09.28 |
Piwik 사용자 정의 변수별 필터 그래프 (0) | 2023.09.28 |
SQL "LIKE" 문과 동등한 SQL Lchemy (0) | 2023.09.28 |