[C#] 문자열에서 첫 번째 문자를 제거하는 가장 빠른 방법

다음 문자열이 있다고 가정 해보십시오.

string data= "/temp string";

첫 번째 문자를 제거하려면 /다음과 같은 많은 방법으로 할 수 있습니다.

data.Remove(0,1);
data.TrimStart('/');
data.Substring(1);

그러나 실제로 어떤 알고리즘이 가장 좋은 알고리즘을 가지고 있고 더 빠르게 수행하는지 알 수 없습니다. 최고 또는 모두 동일한 알고리즘
이 있습니까?



답변

두 번째 옵션은 다른 옵션과 동일하지 않습니다. 문자열이 “/// foo”인 경우 “// foo”대신 “foo”가됩니다.

첫 번째 옵션은 세 번째 옵션보다 이해하는 데 약간의 작업이 필요합니다. Substring옵션을 가장 일반적이고 읽기 쉬운 것으로 간주합니다.

(개별적으로 개별 진술로 그들 각각은 유용한 것을 수행하지 않을 것입니다-결과를 변수 data자체 에 할당해야 합니다.)

실제로 문제가되지 않는 한 여기에서 성능을 고려하지 않을 것입니다.이 경우 알고있는 유일한 방법은 테스트 사례가 있고 각 옵션마다 해당 테스트 사례를 실행하는 것이 쉽습니다. 결과를 비교하십시오. Substring아마도 Substring원래 입력의 단일 청크에서 문자열을 생성하는 반면, Remove적어도 시작 청크와 엔드 청크를 잠재적으로 연결 해야 하기 때문에 아마도 가장 빠를 것으로 예상 됩니다 .


답변

나는 이것이 극도로 최적화 된 땅이라는 것을 알고 있지만의 바퀴를 치는 좋은 변명처럼 보였습니다 BenchmarkDotNet. 이 테스트의 결과 (.NET Core에서도)는 이 샘플 테스트에서 19.37ns 대 22.52ns Substring보다 훨씬 약간 빠릅니다 . 따라서 ~ 16 % 더 빠릅니다.RemoveRemove

using System;
using BenchmarkDotNet.Attributes;

namespace BenchmarkFun
{
    public class StringSubstringVsRemove
    {
        public readonly string SampleString = " My name is Daffy Duck.";

        [Benchmark]
        public string StringSubstring() => SampleString.Substring(1);

        [Benchmark]
        public string StringRemove() => SampleString.Remove(0, 1);

        public void AssertTestIsValid()
        {
            string subsRes = StringSubstring();
            string remvRes = StringRemove();

            if (subsRes == null
                || subsRes.Length != SampleString.Length - 1
                || subsRes != remvRes) {
                throw new Exception("INVALID TEST!");
            }
        }
    }

    class Program
    {
        static void Main()
        {
            // let's make sure test results are really equal / valid
            new StringSubstringVsRemove().AssertTestIsValid();

            var summary = BenchmarkRunner.Run<StringSubstringVsRemove>();
        }
    }
}

결과 :

BenchmarkDotNet=v0.11.4, OS=Windows 10.0.17763.253 (1809/October2018Update/Redstone5)
Intel Core i7-6700HQ CPU 2.60GHz (Skylake), 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100-preview-010184
  [Host]     : .NET Core 3.0.0-preview-27324-5 (CoreCLR 4.6.27322.0, CoreFX 4.7.19.7311), 64bit RyuJIT
  DefaultJob : .NET Core 3.0.0-preview-27324-5 (CoreCLR 4.6.27322.0, CoreFX 4.7.19.7311), 64bit RyuJIT

|          Method |     Mean |     Error |    StdDev |
|---------------- |---------:|----------:|----------:|
| StringSubstring | 19.37 ns | 0.3940 ns | 0.3493 ns |
|    StringRemove | 22.52 ns | 0.4062 ns | 0.3601 ns |


답변

내가 추측 거라고 Remove하고 Substring있는 반면, 그들은 이후, 처음의 문자열의 고정 된 크기의 부분까지 모두 소리내어 먹으을 묶고 TrimStart각 문자에 대한 테스트 왼쪽에서 스캔을 수행하고 다음과 정확히 같은 작업을 수행 할 수있다 다른 두 가지 방법. 그러나 진지하게 머리카락이 갈라지고 있습니다.


답변

당신이 정말로 걱정한다면, 당신은 그것을 프로파일 할 수 있습니다. 많은 반복의 루프를 작성하고 어떻게되는지보십시오. 그러나 이것이 응용 프로그램의 병목 현상이 아니며 TrimStart가 가장 의미 적으로 올바른 것으로 보입니다. 최적화하기 전에 코드를 읽기 쉽게 작성하십시오.


답변