How can I get the name / details of an Action delegate invocation? - c#

I'm testing the performance of some similar method calls that I'm wrapping in some timing and logging statements. I'm passing these methods in via an Action delegate parameter.
Is there any way to print details about the call?
For example:
var httpResult = TestService(() => serviceHttp.Search(criteria));
var tcpResult = TestService(() => serviceTcp.Search(criteria));
var localResult = TestService(() => servicelocal.Search(criteria));
...
private static double TestService(Action serviceOperation)
{
const int iterations = 15;
...
for (var i = 0; i < iterations; i++)
{
var watch = Stopwatch.StartNew();
...
Console.WriteLine(string.Format("{0} ElapsedMilliseconds={1}", ????, watch.ElapsedMilliseconds));
// Ideally this would print something like "serviceTcp.DoStuff(...) ElapsedMilliseconds=313"
}
...
}

Change your testing method declaration to
private static double TestService(Expression<Action> expression)
Call Compile method of expression object to get a method for testing:
var serviceOperation = expression.Compile();
Expression object can provide a lot of information about method call, you can start with something like this:
private static string GetMethodCallDescription(Expression<Action> expression)
{
var mce = (MethodCallExpression)expression.Body;
var method = mce.Method;
var sb = new StringBuilder();
sb.Append(method.DeclaringType.Name);
sb.Append(".");
sb.Append(method.Name);
sb.Append("(");
bool firstarg = true;
foreach(var arg in mce.Arguments)
{
if(!firstarg)
{
sb.Append(", ");
}
else
{
firstarg = false;
}
sb.Append(arg.ToString());
}
sb.Append(")");
return sb.ToString();
}

You could do it without using expression trees; just change the signature of TestService to take the action and the parameter separately, and use the Delegate.Target and Delegate.Method properties to get the type and method:
var httpResult = TestService(serviceHttp.Search, criteria);
var tcpResult = TestService(serviceTcp.Search, criteria);
var localResult = TestService(servicelocal.Search, criteria);
...
private static double TestService<T>(Action<T> serviceOperation, T parameter)
{
const int iterations = 15;
...
for (var i = 0; i < iterations; i++)
{
var watch = Stopwatch.StartNew();
...
string typeName = serviceOperation.Method.IsStatic
? serviceOperation.Method.DeclaringType.Name
: serviceOperation.Target.GetType().Name;
string methodName = serviceOperation.Method.Name;
Console.WriteLine(string.Format("{0}.{1} ElapsedMilliseconds={2}", typeName, methodName, watch.ElapsedMilliseconds));
// Ideally this would print something like "serviceTcp.DoStuff(...) ElapsedMilliseconds=313"
}
...
}

Related

Inject stopwatch using c# into all dll methods using Mono.Cecil, including methods with multiple Return statements

Case 1 Case 2 Case 3 Case 4
Objective:
Using the Injector code i'm trying to inject the stopwatch methods (which are in stopwatch dll) in the desired code location of target dll, inorder to calculate the time taken by each method in the target dll which may or may not be a void method and it may have multiple return statements.
Target dll
public class targetDll
{
void func1(){
//Inject Stopwatch_start(); method here
int a = 3;
int b = 4;
int temp;
temp = a;
a = b;
b =temp;
if (a + b > 2)
{
Console.WriteLine("function____1");
}
#Stopwatch_stop() //Inject stop time here
}
String func2(){
//Inject Stopwatch_start(); method here
int a = 3;
int b = 4;
int c = 5;
int temp;
temp = a;
a = b;
b = c;
c = temp;
if (a + b > 5)
{
Console.WriteLine("function____2");
//inject Stopwatch_stop() method here
return ;
}
a = temp;
//inject Stopwatch_stop(); method here
return;
}
}
Source dll(stopwatch dll)
public static class stopwatch_class
{
static System.Diagnostics.Stopwatch stopwatch_obj = new System.Diagnostics.Stopwatch();
public static void stopwatch_start()
{
stopwatch_obj.Start();
}
public static void stopwatch_stop()
{
stopwatch_obj.Stop();
Console.WriteLine(stopwatch_obj.ElapsedMilliseconds);
}
}
}
Injector code
class Trial_injector
{
static void Main(string[] args)
{
var start_method = (dynamic)null;
var stop_method = (dynamic)null;
AssemblyDefinition target_assembly = AssemblyDefinition.ReadAssembly("targetDll.dll",
new ReaderParameters { ReadWrite = true });
var target_modules = target_assembly.MainModule;
TypeDefinition[] target_module = target_modules.Types.ToArray();
AssemblyDefinition source_assembly = AssemblyDefinition.ReadAssembly("stopwatch.dll", new
ReaderParameters { ReadWrite = true });
var source_modules = source_assembly.MainModule;
TypeDefinition[] source_module = source_modules.Types.ToArray();
foreach (var type in source_module)
{
foreach (var method in type.Methods)
{
if (method.Name == "stopwatch_start")
{
start_method = method;
}
if (method.Name == "stopwatch_stop")
{
stop_method = method;
}
}
}
foreach(var module_ in target_module)
{
foreach(var method_ in module_.Methods)
{
String stg="hello_world";
var processor2 = method_.Body.GetILProcessor();
var first_instruction = method_.Body.Instructions.First();
var last_instruction = method_.Body.Instructions.Last();
var ldstr = processor2.Create(OpCodes.Ldstr, stg);
var call = processor2.Create(OpCodes.Call, method_.Module.Import(start_method));
var call2 = processor2.Create(OpCodes.Call, method_.Module.Import(stop_method));
processor2.InsertBefore(first_instruction, ldstr);
processor2.InsertAfter(first_instruction, call);
processor2.InsertBefore(last_instruction, ldstr);
processor2.InsertBefore(last_instruction, call2);
}
}
target_assembly.Write();
}
You were almost correct with your code. There were few modifications that needed to be done.
Not sure why you need the ldstr opcode as it's not needed anywhere. For the call you want to have that inserted before the first opcode not after. As for the last instruction you could go with InsertBefore. So the final code could be like this:
foreach (var module_ in target_module)
{
foreach (var method_ in module_.Methods)
{
var processor2 = method_.Body.GetILProcessor();
var first_instruction = method_.Body.Instructions.First();
var last_instruction = method_.Body.Instructions.Last();
var call = processor2.Create(OpCodes.Call, method_.Module.Import(start_method));
var call2 = processor2.Create(OpCodes.Call, method_.Module.Import(stop_method));
processor2.InsertBefore(first_instruction, call);
processor2.InsertBefore(last_instruction, call2);
}
}
but that wouldn't work with some early returns. Why? Early returns are coded as a br or br_s opcode to the ret at the end of procedure and if we inject our call before the ret those early returns will skip that. In your example it's not needed as this code is converted to if-else and we have branch in both cases correctly matched. But image we have code like this:
int a = 3;
if (a == 3)
{
return; // very early return here
}
// the rest as in original one
we wont see elapsed time printed for this method as return will direct the execution after our injected call. What we need to do here is to update all branch instructions that are responsible for early returns (so they jump to ret opcode) and point them to our call. We can do this in the following way:
foreach (var bodyInstruction in method_.Body.Instructions)
{
if (bodyInstruction.OpCode != OpCodes.Br && bodyInstruction.OpCode != OpCodes.Br_S) continue;
if (((Instruction)bodyInstruction.Operand).OpCode != OpCodes.Ret) continue;
bodyInstruction.Operand = call2;
}
So what we do here is that we scan through all opcodes and see if we have a br or br_s that jumps to return we update it to jump to our call instead. ViolĂ .
Note: used Elapsed instead of ElapsedMilliseconds as the former was giving all zeros.
Full code:
var start_method = (dynamic) null;
var stop_method = (dynamic) null;
AssemblyDefinition target_assembly = AssemblyDefinition.ReadAssembly("target.exe", new ReaderParameters {ReadWrite = true});
var target_modules = target_assembly.MainModule;
TypeDefinition[] target_module = target_modules.Types.ToArray();
AssemblyDefinition source_assembly = AssemblyDefinition.ReadAssembly("stopwatch.dll", new ReaderParameters {ReadWrite = true});
var source_modules = source_assembly.MainModule;
TypeDefinition[] source_module = source_modules.Types.ToArray();
foreach (var type in source_module)
{
foreach (var method in type.Methods)
{
if (method.Name == "stopwatch_start")
{
start_method = method;
}
if (method.Name == "stopwatch_stop")
{
stop_method = method;
}
}
}
foreach (var module_ in target_module)
{
foreach (var method_ in module_.Methods)
{
var processor2 = method_.Body.GetILProcessor();
var first_instruction = method_.Body.Instructions.First();
var last_instruction = method_.Body.Instructions.Last();
var call = processor2.Create(OpCodes.Call, method_.Module.Import(start_method));
var call2 = processor2.Create(OpCodes.Call, method_.Module.Import(stop_method));
processor2.InsertBefore(first_instruction, call);
processor2.InsertBefore(last_instruction, call2);
foreach (var bodyInstruction in method_.Body.Instructions)
{
if (bodyInstruction.OpCode != OpCodes.Br && bodyInstruction.OpCode != OpCodes.Br_S) continue;
if (((Instruction)bodyInstruction.Operand).OpCode != OpCodes.Ret) continue;
bodyInstruction.Operand = call2;
}
}
}
target_assembly.Write();
self-promotion on
I happen to recorded two videos about doing this (in a bit different way) with Mono.Cecil. You can find it Writing simple .NET execution tracer with Mono.Cecil and Instrumenting .NET assemblies to measure method's execution time in with Mono.Cecil.
self-promotion off

How to have dynamic Nunit TestCaseSource in C#?

What I'd like to do is exactly the first example from this page but...
http://nunit.org/index.php?p=testCaseSource&r=2.5
with value that I can change
static object[] DivideCases =
{
for (int i = 0; i < qtyCmd(); i++)
{
new object[] { getCmd[i] },
}
};
qtyCmd is just a static method which return a number
getCmd read a line (index sent as parameter) in a text file
where the arrays command. I know about Data-Driven Unit Test, but I was asked to do not use it. To be more specific, I am asked to do so with [TestCase]
You can turn DivideCases into a method:
private object[] DivideCases() {
var amountOfSamples = qtyCmd();
var result = new object[amountOfSamples];
for (var i = 0; i < amountOfSamples; i++) {
result[i] = new object[] {getCmd[i]};
}
return result;
}
And then use it with TestCaseSource:
[Test, TestCaseSource("DivideCases")]
public void TestMethod(object[] samples) {
// Your test here.
}

Type casting object[] to generic type K which is also an array

I try to write a generic type casting method which will work for both complex objects and arrays of objects. Below is my code:
public void Test()
{
MyClass2[] t2 = m.MapItem<MyClass1[], MyClass2[]>(t1);
return;
}
public K MapItem<T, K>(T source)
{
if (typeof(T).IsArray && typeof(K).IsArray)
{
Type ek = typeof(K).GetElementType();
IList sourceList = (IList)source;
List<object> tmp = new List<object>();
for (int i = 0; i < sourceList.Count; i++)
{
var k = Activator.CreateInstance(ek);
tmp.Add(k);
}
var resultObj = tmp.ToArray();
MapItem(source, resultObj);
//Here i have resultObj is an object[] of the results,
//which is to be casted result type K
//BUT DOES NOT WORK!!!
return (K)Convert.ChangeType(resultObj, typeof(K));
}
else
{
MethodInfo myMapperMethod = GetMyMapperMethodForThisType(typeof(T), typeof(K));
return (K)myMapperMethod.Invoke(null, new object[] { source });
}
}
public K MapItem<T, K>(T source, K dest)
{
if (typeof(T).IsArray && typeof(K).IsArray)
{
IList sourceList = (IList)source;
IList destList = (IList)dest;
for (int i = 0; i < sourceList.Count; i++)
{
MapItem(sourceList[i], destList[i]);
}
return dest;
}
else
{
MethodInfo myMapperMethod = GetMyMapperMethodForThisType(typeof(T),typeof(K));
return (K) myMapperMethod.Invoke(null, new object[] { source, dest });
}
}
private MethodInfo GetMyMapperMethodForThisType(Type type1, Type type2)
{
//some code to find appropriate function...
}
But, return (K) Convert.ChangeType(y, typeof(K)); cannot cast from object[] to K. How can I do this casting to return K from object[]?
Note: json serialization works but I don't want to use reflection or serialization.
string jsonStr = JsonConvert.SerializeObject(resultObj);
return JsonConvert.DeserializeObject<K>(jsonStr);
Fundamentally I think you want to avoid using List<object> at all. You should just create the array of the right size:
IList dest = Array.CreateInstance(ek, sourceList.Count);
for (int i = 0; i < sourceList.Count; i++)
{
dest[i] = Activator.CreateInstance(ek);
}
K result = (K) dest;
// Note that this is calling MapItem<T, K>, not MapItem<T, object[]>
MapItem(source, result);
return result;

c# and LINQ where property-name of collection member is passed via function

As always, help/comments thoughts are always appreciated, and appologies for the naivety of my programming.
I am trying to create a broadly applicable function which can be used in future research which involves block randomization. Each member of patientDataCollection will have a boolean property named something like interventionArm, givenDrugX or something similar. The function aims to (pseudo-)randomly assign to an arm of a study, depending on block size - that is to say if block size is 8, 4 will be assigned to treatment and 4 to control (no treatment).
The code so far:
public static bool nextAllocation<T>(int blockSize, IEnumerable<T> patientDataCollection, string allocationPropertyName)
{
int remainingAllocations = blockSize - patientDataCollection.Count();
if (remainingAllocations <= 0) throw new Exception("All alocations within block accounted for");
var p = typeof(T).GetProperty(allocationPropertyName);
int remainingInterventions = blockSize/2 - patientDataCollection.Count(c => c.p);
double Pintervention = (double)remainingInterventions / (double)remainingAllocations;
double rdm = new Random().NextDouble();
return (rdm <= Pintervention);
}
this is of course flawed logic because the variable p does not relate to c.p referenced in the linq statement patientDataCollection.Count(c => c.p). obviously this statement is simply to count all elements which have a true value.
ASP is 4.0. Can anyone see how to achieve this
You can pass to your method a Func<T, bool> which will be used for counting.
public static bool nextAllocation<T>(int blockSize, IEnumerable<T> patientDataCollection, Func<T,bool> predicate)
{
int remainingAllocations = blockSize - patientDataCollection.Count();
if (remainingAllocations == 0) throw new Exception("All alocations within block accounted for");
int remainingInterventions = blockSize/2 - patientDataCollection.Count(predicate);
double Pintervention = remainingInterventions / remainingAllocations;
double rdm = new Random().NextDouble();
return (rdm <= Pintervention);
}
An example of usage would be something like this:
var result = nextAllocation(10, collection, c=>c.interventionArm);
You can use reflection to get the value of the property:
int remainingInterventions = blockSize/2 -
patientDataCollection.Count(c => (bool)p.GetValue(c,null));
Add error checking as well.
Try using Expressions
public static class ExpressionCreator
{
public static Func<T, TProperty> CreatePropertyAccessExpression<T, TProperty>(string propertyName)
{
var tType = typeof (T);
var property = tType.GetProperty(propertyName);
var parameterExpression = Expression.Parameter(tType);
var memberAccessExpression = Expression.MakeMemberAccess(parameterExpression, property);
var lambda = Expression.Lambda<Func<T, TProperty>>(memberAccessExpression, parameterExpression);
return lambda.Compile();
}
}
Example usage:
public class A
{
public bool Thing1 { get; set; }
public bool Thing2 { get; set; }
}
static void Main(string[] args)
{
var #as = new A[10];
for(var i = 0; i < #as.Length; i+=2)
{
#as[i] = new A {Thing1 = true};
#as[i + 1] = new A {Thing2 = i%4 == 0};
}
var thing1Expression = ExpressionCreator.CreatePropertyAccessExpression<A, bool>("Thing1");
var thing2Expression = ExpressionCreator.CreatePropertyAccessExpression<A, bool>("Thing2");
Console.WriteLine(#as.Count(thing1Expression));
Console.WriteLine(#as.Count(thing2Expression));
Console.ReadLine();
}

Run dynamically compiled C# code at native speed... how?

I have read several posts on SO about writing and compiling dynamic C# code. For example, this post. I understand it can be done several ways.
However, calling the code invoker is slow. I did a simple benchmark, and it's some 500 X slower than calling a native method.
What I want to be able to do is the equivalent of loading a DLL and calling one of its methods directly ("natively"), which will give the speed benefits I want.
What is the easiest way to go about this? Compile the dynamic code to a dll and then load it? Can it be done in memory?
EDIT
I don't care about compilation time. Only execution.
EDIT 2, 3
Here is the benchmark code I wrote:
public static int Execute(int i) { return i * 2; }
private void button30_Click(object sender, EventArgs e)
{
CSharpCodeProvider foo = new CSharpCodeProvider();
var res = foo.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = true,
CompilerOptions = #"/optimize",
},
#"public class FooClass { public static int Execute(int i) { return i * 2; }}"
);
var type = res.CompiledAssembly.GetType("FooClass");
var obj = Activator.CreateInstance(type);
var method = type.GetMethod("Execute");
int i = 0, t1 = Environment.TickCount, t2;
//var input = new object[] { 2 };
//for (int j = 0; j < 10000000; j++)
//{
// input[0] = j;
// var output = method.Invoke(obj, input);
// i = (int)output;
//}
//t2 = Environment.TickCount;
//MessageBox.Show((t2 - t1).ToString() + Environment.NewLine + i.ToString());
t1 = Environment.TickCount;
for (int j = 0; j < 100000000; j++)
{
i = Execute(j);
}
t2 = Environment.TickCount;
MessageBox.Show("Native: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString());
var func = (Func<int, int>) Delegate.CreateDelegate(typeof (Func<int, int>), method);
t1 = Environment.TickCount;
for (int j = 0; j < 100000000; j++)
{
i = func(j);
}
t2 = Environment.TickCount;
MessageBox.Show("Dynamic delegate: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString());
Func<int, int> funcL = Execute;
t1 = Environment.TickCount;
for (int j = 0; j < 100000000; j++)
{
i = funcL(j);
}
t2 = Environment.TickCount;
MessageBox.Show("Delegate: " + (t2 - t1).ToString() + Environment.NewLine + i.ToString());
}
Yes, if you invoke via a MethodInfo or a non-specific Delegate, then it will indeed be slow. The trick is: don't do that. Various approaches:
for individual methods, go via a basic but typed delegate, such as Action, or as a generic catch-all, Func<object[], object> - and use Delegate.CreateDelegate to create a typed delegate:
Action doSomething = (Action)Delegate.CreateDelegate(typeof(Action), method);
another variant of this is to use the Expression API (which has a .Compile() method), or DynamicMethod (which has CreateDelegate()). The key thing: you must get a typed delegate and invoke using typed invoke (not .DynamicInvoke).
for more complex cases where you are generating whole types, consider implementing an interface you know about, i.e.
IFoo foo = (IFoo)Activator.CreateInstance(...);
again; after the initial cast (which is very cheap) you can just use static code:
foo.Bar();
Do not use someDelegate.DynamicInvoke(...) or someMethod.Invoke(...) if you are after any kind of performance.
Besides Marc's advice you could improve speed by specifying the "optimize" compiler option:
var res = foo.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = true,
CompilerOptions = "/optimize"
},
Thought it was worth showing how all potential options looked and their performance characteristics. Given the following helper classes and functions:
public void Test(Func<int> func)
{
var watch = new Stopwatch();
watch.Start();
for (var i = 0; i <= 1000000; i++)
{
var test = func();
}
Console.WriteLine(watch.ElapsedMilliseconds);
}
public class FooClass { public int Execute() { return 1;}}
Set up and execution:
using (Microsoft.CSharp.CSharpCodeProvider foo =
new Microsoft.CSharp.CSharpCodeProvider())
{
var res = foo.CompileAssemblyFromSource(
new System.CodeDom.Compiler.CompilerParameters()
{
GenerateInMemory = true
},
"public class FooClass { public int Execute() { return 1;}}"
);
var real = new FooClass();
Test(() => real.Execute()); // benchmark, direct call
var type = res.CompiledAssembly.GetType("FooClass");
var obj = Activator.CreateInstance(type);
var method = type.GetMethod("Execute");
var input = new object[] { };
Test(() => (int)method.Invoke(obj, input)); // reflection invoke
dynamic dyn = Activator.CreateInstance(type);
Test(() => dyn.Execute()); // dynamic object invoke
var action = (Func<int>)Delegate.CreateDelegate(typeof(Func<int>), null, method);
Test(() => action()); // delegate
}
The results are:
8 // direct
771 // reflection invoke
41 // dynamic object invoke
7 // delegate
So in those cases where you can't use delegates (if you don't know enough?), you can try dynamic.

Categories

Resources