zoukankan      html  css  js  c++  java
  • span<T>之高性能字符串操作实测

       .net中的字符串操作性能问题由来已久,幸运的是微软推出了span<T>高性能指针操作封装工具类。这个类到底有多高的性能呢?网上传言反正很高,但是实际上在网上很难找到合适的测试实例,这让本人实在无力吐槽。经不住高性能这三个字的诱惑,本人还是了解了一番后做了几个简单样例来测试一番,下面列出几种字符串常见操作的测试代码及其运行结果。

    一、String.Index 测试

    1             var t1 = StopWacherHelper.DoTimer(() =>
    2             {
    3                 for (int i = 0; i < count; i++)
    4                 {
    5                     str.IndexOf(subStr);
    6                 }
    7             });
    8 
    9             Console.WriteLine($"string.IndexOf {count} 次用时:{t1} 毫秒");
     1             var t2 = StopWacherHelper.DoTimer(() =>
     2             {
     3                 var strSpan = str.AsSpan();
     4 
     5                 var subStrSpan = subStr.AsSpan();
     6 
     7                 for (int i = 0; i < count; i++)
     8                 {
     9                     strSpan.IndexOf(subStrSpan);
    10                 }
    11             });
    12 
    13             Console.WriteLine($"Span<T>.IndexOf {count} 次用时:{t2} 毫秒");

     

    二、String.Substring 测试

    1             var t1 = StopWacherHelper.DoTimer(() =>
    2             {
    3                 for (int i = 0; i < count; i++)
    4                 {
    5                     str.Substring(0, str.IndexOf(subStr));
    6                 }
    7             });
    8 
    9             Console.WriteLine($"String.Substring {count} 次用时:{t1} 毫秒");
     1             var t2 = StopWacherHelper.DoTimer(() =>
     2             {
     3                 var strSpan = str.AsSpan();
     4 
     5                 var subStrSpan = subStr.AsSpan();
     6 
     7                 var index = strSpan.IndexOf(subStrSpan);
     8 
     9                 for (int i = 0; i < count; i++)
    10                 {
    11                     strSpan.Slice(0, strSpan.IndexOf(subStrSpan));
    12                 }
    13             });

    三、String.Split 测试

    1             var t1 = StopWacherHelper.DoTimer(() =>
    2             {
    3                 for (int i = 0; i < count; i++)
    4                 {
    5                     var arr = str.Split(new string[] { splitStr }, StringSplitOptions.None);
    6                 }
    7             });
    8 
    9             Console.WriteLine($"String.Split {count} 次用时:{t1} 毫秒");
     1             var t2 = StopWacherHelper.DoTimer(() =>
     2             {
     3                 var strSpan = str.AsSpan();
     4 
     5                 var splitSapn = splitStr.AsSpan();
     6 
     7                 int m = 0, n = 0;
     8 
     9                 for (int i = 0; i < count; i++)
    10                 {
    11                     List<string> arr = new List<string>();
    12 
    13                     while (true)
    14                     {
    15                         m = n;
    16                         n = strSpan.IndexOf(splitSapn);
    17                         if (n > -1)
    18                         {
    19                             arr.Add(strSpan.Slice(0, n).ToString());
    20                             strSpan = strSpan.Slice(n + splitSapn.Length);
    21                         }
    22                         else
    23                         {
    24                             break;
    25                         }
    26                     }
    27 
    28                 }
    29             });
    30 
    31             Console.WriteLine($"Span<T>.Split {count} 次用时:{t2} 毫秒");

    四、String.Replace 测试

    1             var t1 = StopWacherHelper.DoTimer(() =>
    2             {
    3                 for (int i = 0; i < count; i++)
    4                 {
    5                     str.Replace(splitStr, replaceStr);
    6                 }
    7             });
    8 
    9             Console.WriteLine($"String.Replace {count} 次用时:{t1} 毫秒");
     1             var t2 = StopWacherHelper.DoTimer(() =>
     2             {
     3                 var strSpan = str.AsSpan();
     4 
     5                 var splitSapn = splitStr.AsSpan();
     6 
     7                 int m = 0, n = 0;
     8 
     9                 for (int i = 0; i < count; i++)
    10                 {
    11                     List<string> arr = new List<string>();
    12 
    13                     while (true)
    14                     {
    15                         m = n;
    16                         n = strSpan.IndexOf(splitSapn);
    17                         if (n > -1)
    18                         {
    19                             arr.Add(strSpan.Slice(0, n).ToString());
    20                             strSpan = strSpan.Slice(n + splitSapn.Length);
    21                         }
    22                         else
    23                         {
    24                             break;
    25                         }
    26                     }
    27                     string.Join(replaceStr, arr);
    28                 }
    29             });
    30 
    31             Console.WriteLine($"Span<T>.Replace {count} 次用时:{t2} 毫秒");

      怎么样,经过上面的测试,是不是觉的Span<T>确实是名不虚传?的确,在上面几个常见场景中,Span<T>的高性能确实不同凡响,差不多是10倍的性能优势!看到这里,小伙伴们是不是觉的字符串操作全改成Span<T>就行了?那下面的两个测试会让大家看清现实,在String.Contains中表现还不如原生的。

    一、String.Contains 测试

    1             var t1 = StopWacherHelper.DoTimer(() =>
    2             {
    3                 for (int i = 0; i < count; i++)
    4                 {
    5                     str.Contains(subStr);
    6                 }
    7             });
    8 
    9             Console.WriteLine($"string.Contains {count} 次用时:{t1} 毫秒");
     1             var t2 = StopWacherHelper.DoTimer(() =>
     2             {
     3                 var strSpan = str.AsSpan();
     4 
     5                 var subStrSpan = subStr.AsSpan();
     6 
     7                 for (int i = 0; i < count; i++)
     8                 {
     9                     strSpan.Contains(subStrSpan, StringComparison.CurrentCulture);
    10                 }
    11             });
    12 
    13             Console.WriteLine($"Span<T>.Contains {count} 次用时:{t2} 毫秒");

      仔细一看,不对啊,Span<T>的Contains里面有其它的大小写和语言相关的判断啊。好,那再换一个原生方法对比测试一下。

    二、String.Compare 测试

    1             var t1 = StopWacherHelper.DoTimer(() =>
    2             {
    3                 for (int i = 0; i < count; i++)
    4                 {
    5                     string.Compare(str, subStr, true);
    6                 }
    7             });
    8 
    9             Console.WriteLine($"string.Compare {count} 次用时:{t1} 毫秒");
     1             var t2 = StopWacherHelper.DoTimer(() =>
     2             {
     3                 var strSpan = str.AsSpan();
     4 
     5                 var subStrSpan = subStr.AsSpan();
     6 
     7                 for (int i = 0; i < count; i++)
     8                 {
     9                     strSpan.Contains(subStrSpan, StringComparison.CurrentCultureIgnoreCase);
    10                 }
    11             });
    12 
    13             Console.WriteLine($"Span<T>.Contains {count} 次用时:{t2} 毫秒");

      还是被反杀了,这说明Span<T>的这个Contains方法可能真的只能在某些地方才能用,不然性能反而会有所下降。

           如果对上述感兴趣,可以点击这里下载测试源码,更多请点击左下角的推荐,谢谢~

  • 相关阅读:
    PAT (Advanced Level) Practice 1100 Mars Numbers (20分)
    PAT (Advanced Level) Practice 1107 Social Clusters (30分) (并查集)
    PAT (Advanced Level) Practice 1105 Spiral Matrix (25分)
    PAT (Advanced Level) Practice 1104 Sum of Number Segments (20分)
    PAT (Advanced Level) Practice 1111 Online Map (30分) (两次迪杰斯特拉混合)
    PAT (Advanced Level) Practice 1110 Complete Binary Tree (25分) (完全二叉树的判断+分享致命婴幼儿错误)
    PAT (Advanced Level) Practice 1109 Group Photo (25分)
    PAT (Advanced Level) Practice 1108 Finding Average (20分)
    P6225 [eJOI2019]异或橙子 树状数组 异或 位运算
    P4124 [CQOI2016]手机号码 数位DP
  • 原文地址:https://www.cnblogs.com/yswenli/p/9987762.html
Copyright © 2011-2022 走看看