たこぜりー研究室

大腸菌DNAは4.64Mbp。酵母は13Mbpで、ヒトは3Gbp

スポンサーサイト

#
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Windows Update エージェントが更新された

#523
[Vista] Windows Update エージェント 7.4.7600.226

Windows Update エージェント 7.4.7600.226

Windows 7 化が始まったw
スポンサーサイト

string の foreach

#522
[C#]
(string value)
{
  foreach (char c in value)
  {
    if (c != ' ' && c != '\n' && c != '\t')
      return false;
  }
  return true;
}

[コンパイル後 IL -> C# 的表現]
(string value)
{
  string CS$6$0001 = value;
  int CS$7$0002 = 0;
  for (int CS$7$0002 = 0; CS$7$0002 < CS$6$0001.Length; CS$7$0002++)
  {
    char c = CS$6$0001[CS$7$0002];
    if (c != ' ' && c != '\n' && c != '\t')
      return false;
  }
  return true;
}

foreach (char in string) が展開されておる!

string ループ

#520
2 記事連続で C# パフォーマンスネタ。
string str = ....;
for (int i = 0; i < str.Length; i++)
{
  if (!char.IsControl(str[i])) ...
}

が、unsafe でいうところの
string str = ....;
fixed (char* cp = str)
{
  for (char* p = cp; p != '\0'; p++)
  {
    if (!char.IsControl(*p)) ...
  }
}

となってくれるだろうか。

そうすれば str.Length をループの外に出さなくて済むのだが。

EqualityComparer.Default でリニアサーチ

#519
長さ 10 万の整数列を 1000 回リニアサーチ。
static void Main(string[] args)
{
  Stopwatch sw = new Stopwatch();
  int[] array = Enumerable.Range(1, 100000).ToArray();

  sw.Start();
  for (int i = 0; i < 1000; i++)
    One(array, 90000);
  sw.Stop();
  Console.WriteLine(sw.Elapsed);
  sw.Reset();

  sw.Start();
  for (int i = 0; i < 1000; i++)
    Two(array, 90000);
  sw.Stop();
  Console.WriteLine(sw.Elapsed);
  sw.Reset();

  sw.Start();
  for (int i = 0; i < 1000; i++)
    One(array, 90000);
  sw.Stop();
  Console.WriteLine(sw.Elapsed);
  sw.Reset();
}

static int One(int[] array, int value)
{
  for (int i = 0; i < array.Length; i++)
  {
    if (EqualityComparer<int>.Default.Equals(array[i], value))
      return i;
  }
  return -1;
}

static int Two(int[] array, int value)
{
  var comparer = EqualityComparer<int>.Default;

  for (int i = 0; i < array.Length; i++)
  {
    if (comparer.Equals(array[i], value))
      return i;
  }
  return -1;
}

もちろん実際には Array.IndexOf を使えばいいわけだが。

EqualityComparer.Default をループ中に呼び出すのか、呼び出さないのか、の違いをみたいなぁ、という話。

結果 (Release ビルドでデバッグなし実行、.NET 3.5 / Core2 Duo 2.00GHz) :
00:00:01.3417418
00:00:00.5312608
00:00:01.3143324

ループ内呼び出しオワタ

犯人↓
call class [mscorlib]System.Collections.Generic.EqualityComparer`1<!0> [mscorlib]System.Collections.Generic.EqualityComparer`1<int32>::get_Default()

が ldloc.0 になるだけでこの速度差 orz
ここは逆に考えるんだ。1 億回 の呼び出しでようやく 0.8 秒の差なんだと。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。