速度を向上させるパッチがきてたー
というわけで、さっそくベンチ
| パッチ前 | パッチ後 |
| CPU | メモリ | CPU | メモリ |
| 8.6sec | 20KB | 4.09sec | 327KB |
テストコードはこんな感じ
using System;
using System.Globalization;
class Test {
static void Main ()
{
DateTime dt = DateTime.Now;
NumberFormatInfo nfi = NumberFormatInfo.GetInstance (null);
long before = GC.GetTotalMemory (true);
for (int i = 0; i < 10000000; i ++)
i.ToString ("g", nfi);
TimeSpan time = DateTime.Now.Subtract (dt);
long after = GC.GetTotalMemory (true);
Console.WriteLine ("Time:{0}, Memory:{1}KB", time, (after - before) / 1000);
}
}
なんでプロファイラを使わないで、GC.GetTotalMemoryを使っているかというと、
プロファイラの実行に時間がかかるから(ぇ
それに、単純に静的に確保されるメモリ領域を知りたいだけだから。
次は、上記のコードのdouble型版。静的領域のメモリ確保量は変わらないと思ったけど少し変化が。
| パッチ前 | パッチ後 |
| CPU | メモリ | CPU | メモリ |
| 31.5sec | 32KB | 9.3sec | 389KB |
わお。劇的に早くなってる。しかもユニットテストは全部パスしているっぽい
だけど気になるのは
// _decHexDigits s a translation table from a decimal number to its
// digits hexadecimal representation (e.g. _decHexDigits [234] = 0x234).
static readonly int[] _decHexDigits = new int [10000];
// _decHexLen caches the number of digits in a hexadecimal number.
// For instance _decHexLen [0x234] = 3.
static readonly int[] _decHexLen = new int [0x10000];
この部分。さすがに静的メモリ確保しすぎな気がする。なので、以下のパッチをさらに適用して再測定。
--- NumberFormatter.cs 2007-12-30 13:39:42.397014155 +0900
+++ NumberFormatter.reduce.cs 2007-12-30 14:23:13.781828495 +0900
@@ -76,30 +76,14 @@
// digits hexadecimal representation (e.g. _decHexDigits [234] = 0x234).
static readonly int[] _decHexDigits = new int [10000];
- // _decHexLen caches the number of digits in a hexadecimal number.
- // For instance _decHexLen [0x234] = 3.
- static readonly int[] _decHexLen = new int [0x10000];
-
static NumberFormatter ()
{
- // Compute _decHexDigits and _decHexLen.
+ // Compute _decHexDigits.
uint res = 0;
for (int i = 0; i < _decHexDigits.Length; i++) {
_decHexDigits [i] = (int)res;
res = AddOneToDecHex (res);
}
- int len = 0;
- for (int i = 0; i < _decHexLen.Length; i++) {
- if (i == 0x1)
- len = 1;
- if (i == 0x10)
- len = 2;
- else if (i == 0x100)
- len = 3;
- else if (i == 0x1000)
- len = 4;
- _decHexLen [i] = len;
- }
}
#endregion Static Fields
@@ -219,14 +203,29 @@
}
// Helper to count number of hexadecimal digits in a number.
- private static int DecHexLen (uint val)
+ private static int DecHexLen (uint v)
{
- int v = (int)val;
- if (v < 0)
- return 8;
- if (v < 0x10000)
- return _decHexLen [v];
- return 4 + _decHexLen [v >> 16];
+ if (v < 0x10000) {
+ if (v < 0x100) {
+ if (v < 0x10)
+ return v == 0 ? 0 : 1;
+ return 2;
+ } else {
+ if (v < 0x1000)
+ return 3;
+ return 4;
+ }
+ } else {
+ if (v < 0x1000000) {
+ if (v < 0x100000)
+ return 5;
+ return 6;
+ } else {
+ if (v < 0x10000000)
+ return 7;
+ return 8;
+ }
+ }
}
// Count number of hexadecimal digits stored in _val1 .. _val4.
| パッチ後 | パッチ後+メモリ削減パッチ |
| CPU | メモリ | CPU | メモリ |
| 4.09sec | 327KB | 4.31sec | 57KB |
うむ。だいぶ減った。
後は、_decHexDigits = new int [10000] の部分も new int[100] ぐらいにすればいい気がするけど
速度を考慮すると、これぐらいでもちょうどいいのかな? ここら辺のトレードオフって難しいなぁ