先の記事で FastEnum という超高速な Enum Utility ライブラリを作ってリリースしてから 3 日。v1.1.0 をリリースしました。パフォーマンスはさらに磨きがかかっていて、他の追随を許さないレベルに昇華されました。最早グラフにしても棒が表示されてない...(
今回は主に以下のような変更を行っています。早速思いっきり Breaking Chages!!
- API Surface が大きく変更に
- 更なるパフォーマンスの改善
- API の追加
- etc...
API Surface の変更
のいえ先生 (@neuecc) から「Generics Class な API は使い心地が悪いからヤだ」と指摘を受け、全くそのとーりだったので改善しました。思いっきり Breaking Changes!! なんですが、リリース数日なので許してください!(泣
これFastEnum.TryParse<T>的なAPIに寄せれるのってできないんです?(キャッシュするのを内側にすればいいだけとは思いますんが)。安全性的にはT[]の露出はReadOnly...にしたいところですが、まぁそこは割り切ってもおk?
— neuecc (@neuecc) 2019年9月7日
APIの触り心地的に、クラスでジェネリクスからのメソッドってかなり感触の悪いAPIの一つとは思ってますねえ。.Defaultとか以外ではあんまりやりたくなくはなく。
— neuecc (@neuecc) 2019年9月7日
概ね以下のように変更されています。Generics クラスだったものを Generics メソッドに変更した感じです。大変自然というか、System.Enum
にかなり近づいた API になったと思います。
//--- Before var values = FastEnum<Fruits>.Values; var names = FastEnum<Fruits>.Names; var defined = FastEnum<Fruits>.IsDefined(123); var parse = FastEnum<Fruits>.Parse("Apple"); var tryParse = FastEnum<Fruits>.TryParse("Apple", out var value); //--- After var values = FastEnum.GetValues<Fruits>(); var names = FastEnum.GetNames<Fruits>(); var defined = FastEnum.IsDefined<Fruits>(123); var parse = FastEnum.Parse<Fruits>("Apple"); var tryParse = FastEnum.TryParse<Fruits>("Apple", out var value);
更なるパフォーマンスの改善
.NET Core に勝っただけで世界最速!などと大きなことを言ってしまったことを反省しています。世の中には Enums.NET というライブラリがあって、同様に high-performance を謳っていました。それとの比較なしに最速を勝手に語るのは思い上がりなので、ちゃんと比較しました。
結果として IsDefined
メソッドで Enums.NET より 4 倍ほど遅い結果が出てしまって大変がっかり...。
うぎゃー!IsDefined で負けたーwwwww
— じんぐる (@xin9le) 2019年9月6日
これは何とかして追いつかなければ...(ぐぬぬ pic.twitter.com/PCdFWykVxs
ということで必死に改善しました。改善した結果は記事冒頭のグラフの通りで、Enums.NET
と比べて 6 倍 (v1.0 の実装と比べると 25 倍) 程速くなっています。どのメソッドにおいても Enums.NET
よりも System.Enum
よりも速い!今度こそ最速!(たぶん
まとめ
1 [ns] レベルの改善するために数日かけるという非効率の極み...。このチューニングによる時間は回収できるものなのか分かりませんが、大変勉強にはなりました。もうこれ以上の速度は出せない気がする (気がするだけかも) ので、ぜひ速いものに巻かれる (?) つもりで利用してみてください。バグ報告や PR などもお待ちしております :)