質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

Q&A

解決済

1回答

242閲覧

動的なインスタンス生成処理のベンチマーク結果について

hossy

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

2グッド

1クリップ

投稿2017/10/02 10:18

確認したいこと

オブジェクトの動的生成について、DynamicMethodを使った方法とExpressionを使った方法を比較してみたところ、Expressionを使った方法の方が性能が良い結果になりました。
この差異が何によって発生しているのかについて、理由または調査方法が知りたいです。

試したこと

BenchmarkDotNetを使用して、以下の様なコードで実験を行いました。

csharp

1class Program 2{ 3 static void Main(string[] args) 4 { 5 BenchmarkRunner.Run<CreateBenchmark>(); 6 } 7} 8 9public class Hoge 10{ 11} 12 13public class CreateBenchmark 14{ 15 private Func<object[], object> _dynamicMethodCtor; 16 17 private Func<object[], object> _expressionCtor; 18 19 [GlobalSetup] 20 public void GlobalSetup() 21 { 22 _dynamicMethodCtor = CreateByDynamicMethod(typeof(Hoge).GetConstructors()[0]); 23 _expressionCtor = CreateByExpression(typeof(Hoge).GetConstructors()[0]); 24 } 25 26 public static Func<object[], object> CreateByDynamicMethod(ConstructorInfo ctor) 27 { 28 var dynamic = new DynamicMethod("", typeof(object), new[] { typeof(object[]) }, true); 29 var il = dynamic.GetILGenerator(); 30 31 // デフォルトコンストラクタしかテストしないので引数の処理部分は省略 32 33 il.Emit(OpCodes.Newobj, ctor); 34 il.Emit(OpCodes.Ret); 35 36 return (Func<object[], object>)dynamic.CreateDelegate(typeof(Func<object[], object>)); 37 } 38 public static Func<object[], object> CreateByExpression(ConstructorInfo ctor) 39 { 40 var parameters = ctor.GetParameters(); 41 var parametersExpr = Expression.Parameter(typeof(object[]), "parameters"); 42 var argumentsExprs = new Expression[parameters.Length]; 43 44 // デフォルトコンストラクタしかテストしないので引数の処理部分は省略 45 46 return Expression.Lambda<Func<object[], object>>(Expression.New(ctor, argumentsExprs), parametersExpr).Compile(); 47 } 48 49 [Benchmark] 50 public object DynamicMethodCtor() 51 { 52 return _dynamicMethodCtor(null); 53 } 54 55 [Benchmark] 56 public object ExpressionCtor() 57 { 58 return _expressionCtor(null); 59 } 60}

実行結果

何回か繰り返しても、以下の様にExpressionCtorの方が若干性能の良い結果となりました。

MethodMeanErrorStdDevGen 0Allocated
DynamicMethodCtor3.379 ns0.5940 ns0.0336 ns0.005724 B
ExpressionCtor2.950 ns0.2595 ns0.0147 ns0.005724 B

その他

LambdaExpressionの内容をファイルに保存してIldasmで確認してみましたが、やっていることは以下の様にnewobjとretだけでした。

.method public static object Create(object[] args) cil managed { // コード サイズ 6 (0x6) .maxstack 1 IL_0000: newobj instance void [IlTest]IlTest.Class0::.ctor() IL_0005: ret } // end of method test_type::create

ILだけ見ると性能に差異が出なくてよいような気がしますが、なぜこの差異が発生しているのかについてなにかわかる方がいらっしゃったらヒントをお願いします。

Tak1wa, ebiryo👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんにちは。
ただいま検証環境が作成できず、完全な勘での回答になります……的外れでしたら申し訳ないです。

質問のコードでは、DynamicMethod版のデリゲートは静的メソッドとして生成するコードとなっていますが、
確か、ExpressionTreeのLambdaCompilerによるデリゲート作成はインスタンスメソッドの形で生成されていたと記憶しています。
試しに、DynamicMethod版を任意のオブジェクトに紐つけたインスタンスメソッドとして定義した場合、計測結果に影響するかもしれません。

csharp

1public static Func<object[], object> CreateByDynamicMethod(ConstructorInfo ctor) 2{ 3 var dynamic = new DynamicMethod("", typeof(object), new[] { typeof(object), typeof(object[]) }, true); // targetの型を追加 4 var il = dynamic.GetILGenerator(); 5 6 il.Emit(OpCodes.Newobj, ctor); 7 il.Emit(OpCodes.Ret); 8 9 var dummy = new object(); // 10 return (Func<object[], object>)dynamic.CreateDelegate(typeof(Func<object[], object>), dummy); // インスタンスメソッド 11}

投稿2017/10/04 05:02

tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hossy

2017/10/04 06:26

提示頂いた方法を試してみたところ、Expressionを使った方法との差異がなくなった気がします。 もう少し検証はしたいと思いますが、一端解決済みにしたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問