use*_*191 3 c# string performance
struct mydata
{
public int id;
public string data;
}
class Program
{
static void Main(string[] args)
{
List<mydata> myc = new List<mydata>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
mydata d = new mydata();
d.id = i;
d.data = string.Format("DataValue {0}",i);
myc.Add(d);
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
}
Run Code Online (Sandbox Code Playgroud)
这个代码上面的代码是如此慢......?
在较旧的笔记本电脑上,时间是:C#代码高于:1500ms类似的代码在Delphi:450ms ....
然后我将代码更改为KeyValue/Pair(见下文):
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var list = new List<KeyValuePair<int , string>>();
for (int i = 0; i < 1000000; i++)
{
list.Add(new KeyValuePair<int,string>(i, "DataValue" + i));
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
这改善了1150ms的时间..
如果我删除'+ i',则时间<300ms
如果我尝试用StringBuilder替换它,时间是类似的.
StringBuilder sb = new StringBuilder();
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
var list = new List<KeyValuePair<int, string>>();
for (int i = 0; i < 1000000; i++)
{
sb.Append("DataValue");
sb.Append(i);
list.Add(new KeyValuePair<int, string>(i, sb.ToString()));
sb.Clear();
}
stopWatch.Stop();
Console.WriteLine("End: {0}", stopWatch.ElapsedMilliseconds);
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
稍微好一点..如果你删除sb.Append(i)它非常快..
看来,任何时候你必须将一个Int添加到一个字符串/ stringbuilder它非常慢.
我能以任何方式加快速度吗?
编辑**
以下代码是我提出建议后最快的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication1
{
struct mydata
{
public int id;
public string data;
}
class Program
{
static void Main(string[] args)
{
List<mydata> myc = new List<mydata>();
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
{
mydata d = new mydata();
d.id = i;
d.data = "DataValue " + i.ToString();
myc.Add(d);
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
}
Run Code Online (Sandbox Code Playgroud)
}
如果我更换线路:
d.data = "DataValue " + i.ToString();
有:
d.data = "DataValue ";
在我的家用机器上,这是从660ms - > 31ms ..
是的..用'+ i.ToString()'慢了630ms
但仍然比拳击/ string.format等快2倍..
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
var list = new List<KeyValuePair<int, string>>();
for (int i = 0; i < 1000000; i++)
{
list.Add(new KeyValuePair<int, string>(i, "DataValue" +i.ToString()));
}
stopwatch.Stop();
Console.WriteLine("End: {0}", stopwatch.ElapsedMilliseconds);
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
是612ms ..(如果列表>(1000000),则没有速度差异;是预先初始化的).
Mar*_*ers 10
前两个示例的问题是必须首先将整数装箱,然后转换为字符串.拳击会导致代码变慢.
例如,在这一行:
d.data = string.Format("DataValue {0}", i);
Run Code Online (Sandbox Code Playgroud)
第二个参数string.Format是object,导致拳击i.请参阅中间语言代码以确认:
... box int32 call string [mscorlib]System.String::Format(string, object) ...
同样这段代码:
d.data = "DataValue " + i;
Run Code Online (Sandbox Code Playgroud)
相当于:
d.data = String.Concat("DataValue ", i);
Run Code Online (Sandbox Code Playgroud)
这使用了String.Concat带有类型参数的重载,object所以这又涉及一个装箱操作.这可以在生成的中间语言代码中看到:
... box int32 call string [mscorlib]System.String::Concat(object, object) ...
为了更好的性能,这种方法避免了拳击:
d.data = "DataValue " + i.ToString();
Run Code Online (Sandbox Code Playgroud)
现在中间语言代码不包含box指令,它使用String.Concat带有两个字符串的重载:
... call instance string [mscorlib]System.Int32::ToString() call string [mscorlib]System.String::Concat(string, string) ...
| 归档时间: |
|
| 查看次数: |
820 次 |
| 最近记录: |