Stopwatch stopwatch1 = new Stopwatch();
Stopwatch stopwatch2 = new Stopwatch();
string l = "my test";
string u = "MY TEST";
for (int i = 0; i < 25; i++)
{
l += l;
u += u;
}
stopwatch1.Start();
l=l.ToUpper();
stopwatch1.Stop();
stopwatch2.Start();
u=u.ToLower();
stopwatch2.Stop();
// Write result.
Console.WriteLine("Time elapsed: nUPPER : {0}n LOWER : {1}",
stopwatch1.Elapsed, stopwatch2.Elapsed);
我跑了很多次:
UPPER : 00:00:01.3386287
LOWER : 00:00:01.4546552
UPPER : 00:00:01.1614189
LOWER : 00:00:01.1970368
UPPER : 00:00:01.2697430
LOWER : 00:00:01.3460950
UPPER : 00:00:01.2256813
LOWER : 00:00:01.3075738
让我们尝试 reproducing 结果
// Please, notice: the same string for both ToUpper/ToLower
string GiniPig = string.Concat(Enumerable
.Range(1, 1000000) // a million chunks "my test/MyTest" combined (long string)
.Select(item => "my test/MY TEST"));
Stopwatch sw = new Stopwatch();
// Let's try n (100) times - not just once
int n = 100;
var sampling = Enumerable
.Range(1, n)
.Select(x => {
sw.Reset();
sw.Start();
GiniPig.ToLower(); // change this into .ToUpper();
sw.Stop();
return sw.ElapsedMilliseconds; })
.ToSampling(x => x); // Side library; by you may save the data and analyze it with R
Console.Write(
$"N = {n}; mean = {sampling.Mean:F0}; std err = {sampling.StandardDeviation:F0}");
跑步几次(变暖)我已经得到了结果(核心i7 3.6 GHz,.net 4.6 IA-64):
ToLower: N = 100; mean = 38; std err = 8
ToUpper: N = 100; mean = 37; std err = 9
因此,您不能拒绝 ToLower
的零假设与 ToUpper
一样快,因此您的实验有错误::
- 您有不同的字符串来处理
- 处理简短(仅
175
字符)字符串仅一次(不在循环中)即时,因此错误可以enrous enourmous - 您必须热身例行程序(为了编译要编译的方法,加载的组件,填充的caches等) )
看来(经过的时间超过1秒,非常简单的操作)是规则#3(热身)破坏了实验
您对ToUpper
的Intial假设比ToLower
快具有逻辑谬误。
您的转化为文化敏感。您没有执行顺序操作,而是执行取决于当前文化的操作(如CultureInfo.CurrentCulture
返回)。在您使用的文化中,从下部情况到上案的转换可能会更快,并且它可能会在另一个文化中慢。一种文化中的转化也可能比另一种文化中的转换更快。
因此,您最初的假设是 ToUpper
和ToLower
的一个性能。