スポンサーサイト

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

C# Math.Powのパフォーマンスについて

  • 2016/03/02 14:33
  • Category: C#
.NETのMath.Powを使う場合、指数部に整数を指定するのであれば、Math.Powよりもx * xのように演算子を使う方が高速です。


//最適化でコードが削除されないように一部対処してます。

Math.Pow5937ms
x * x * x115ms


50倍も差が出ました。Math.Powではdoubleを指定できるので、汎用的に使える分、処理は遅くなるということでしょうか…
MSDNに書いてある通り、引数がNANやInfであったときに特定の値を返すので、引数の判断にも時間がかかっていそうです。


Reference Sourceでメソッドの実装を見ようとしたところ、
http://referencesource.microsoft.com/#mscorlib/system/math.cs,95354113fadc3083,references
public static extern double Pow(double x, double y);
externが付いていました。もっと低レイヤーで実装されているようです。


さらに調べてみると、Stack Overflowから
http://stackoverflow.com/questions/9652549/self-made-pow-c
http://opensource.apple.com/source/Libm/Libm-315/Source/ARM/powf.c
http://opensource.apple.com/source/Libm/Libm-2026/Source/Intel/expf_logf_powf.c
Cでの実装が見つかりました。(といってもAppleのものですが)
軽く読むだけでも、単なる掛け算とは比較にならないほどの処理をしてるのが分かりますね…

スポンサーサイト

C#でオブジェクトを再帰的にダンプする

  • 2016/02/24 02:11
  • Category: C#
個人的に使っていたダンプクラスを手直ししたので、ついでにGitHubに挙げておきました。
https://github.com/KkGh/DebugLib/blob/master/Dumper.cs
DebugLib.Dumperがそのクラスです。
リポジトリには他にもいくつかクラスが入ってますが、特に参照はしていないのでDumper.csだけで利用できます。

ダンプ用メソッドはDump()とDumpToString()の2つです。2つともobjectの拡張メソッドにしているので、instance.Dump()でコンソールへ出力、instance.DumpToString()でstringを返します。
クラスならプロパティを、コレクションなら各要素をリフレクションで再帰的に列挙します。
基本的なフォーマットは「プロパティ名 = 値 (値の型)」ですが、コレクションの要素を列挙する場合には「[インデックス] 値 (値の型)」となります。

サンプル


staticプロパティでインデントサイズや型の表示・非表示などを設定できます。
DateTimeのように、そのままダンプするとやたら長い結果を吐くクラスもあるので、TypesAsStringに型を追加すれば再帰せずToString()の結果だけを出力できるようにしました。


モノによってはかなり冗長な出力になりますが、デバッグ用に作ったものということで…
それと今の処理ではコレクションが持つプロパティ(List<T>.Countなど)を表示できないので、今後色々と変更するかもしれません。

C#で配列をダンプする

  • 2015/01/27 16:15
  • Category: C#
C#でジャグ配列や多次元配列をダンプしてみました。



両方とも再帰で要素を列挙してます。
インデックスは再帰の途中でindexesに入れておいて、要素をConsole.WriteLine()するときに
一緒に表示するようにしています。

使い方↓



3次元以上の配列でも使えますが、多次元配列とジャグ配列をミックスしたものでは
後に出てきた方がToStringされるので [0,1][0] のようには出力されません。



インデックスの保持を工夫すれば対応できるような気はするものの、
実際にこの配列が使われているのを見たことがないような…?

byte配列を16進数文字列に変換する際のパフォーマンス

  • 2014/02/19 15:14
  • Category: C#
C#でバイト配列を16進数文字列に変換する方法は色々ありますが、パフォーマンス的にはどの方法がいいのか少し検証してみました。
(あまり厳密にやった訳ではないので参考程度に)

検証対象
StringBuilder.AppendFormat
byte.ToString
Convert.ToString
BitConverter.ToString

約2MBのファイルを読み込んで、それぞれの処理時間を計測してみます。
BitConverter.ToString以外は文字列の連結にStringBuilderを使用しました。



結果
StringBuilder.AppendFormat1073ms
byte.ToString481ms
Convert.ToString379ms
BitConverter.ToString82ms

BitConverterが最も速いように見えますが、実際は文字列がハイフン区切りで返ってくるので
削除するにはReplace("-", "")する必要があります。
実際に行ったら183msかかりました。2倍越えてますね…
http://msdn.microsoft.com/ja-jp/library/3a733s97%28v=vs.110%29.aspx

またConvert.ToStringは他のメソッドと異なりA-Fは小文字に、0x00-0x0Fは先頭の0が削られ1桁になるようです。
http://msdn.microsoft.com/ja-jp/library/8s62fh68%28v=vs.110%29.aspx

基本的にはBitConverter.ToStringで十分でしょう。
しかし巨大なバイナリを扱うことを考えると、できるだけ高速化は行いたいものです。



というわけでLookupテーブルとポインタで4種類作りました。



4つ目のstringをint*で操作する方法はCodeProjectを参考にしてます。
http://www.codeproject.com/Tips/447938/High-performance-Csharp-byte-array-to-hex-string-t

結果
stringテーブル + StringBuilder71ms
charテーブル + char[]43ms
charテーブル + char[] + unsafe22ms
charテーブル + string + unsafe18ms

やはりポインタを使うと速いですね。
ちなみにリンク先のToHexStringで測ったら14msでした。


VS2012単体テストで例外の検証

  • 2014/01/10 00:09
  • Category: C#
VS2012単体テストでは、テストメソッドが例外を投げるか検証するために
ExpectedException属性を使用します。
しかし、1つの例外に対し1つのテストメソッドを用意しなければいけないので
割と面倒だったりします。


ということで作りました。
引数のactionにメソッドなりラムダなり指定して例外を投げるかテストするメソッドです。



これを使えば、1つのテストメソッド内で複数の例外を検証できるようになります。




allowDerivedTypesがtrueの場合、TにArgumentExceptionを指定すれば、
その派生であるArgumentOutOfRangeExceptionやArgumentNullExceptionを
actionがスローした時にもテストをパスします。


actionがnullの時はパスしてもいいかなとか
catch内からスローした時は例外メッセージも返した方がいいかなとか
色々改良するところがあると思います…


後で気付いたのですが、NUnitにはAssert.Throwsメソッドとして用意されているようです。
http://www.nunit.org/index.php?p=exceptionAsserts&r=2.6.3



Pagination

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