- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经编写了一些测试代码来比较使用直接属性访问或反射或使用委托(delegate)进行反射的性能。但我得到的结果令人费解,因为它表明反射并不比直接访问属性慢很多(~4%),我不认为这是真的。如果我在这里做错了什么,有人可以告诉我吗?
对于 5000 个项目,我得到以下结果
代码:
private static Random random = new Random((int)DateTime.Now.Ticks);
Private Dictionary<string, Delegate> delegateList = new Dictionary<string, Delegate>();
private List<ReflectClass1> dataList = new List<ReflectClass1>();
private void TestMethod2<T>()
{
foreach (var propertyInfo in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (propertyInfo.PropertyType.BaseType != typeof(ValueType))
{
Func<T, object> getPropDelegate =
(Func<T, object>) Delegate.CreateDelegate(typeof (Func<T, object>), null, propertyInfo.GetGetMethod());
delegateList.Add(propertyInfo.Name, getPropDelegate);
}
//else
//{
// Type propertyType = propertyInfo.PropertyType.GetType();
// delegateList.Add(propertyInfo.Name,
// Delegate.CreateDelegate(typeof(Func<T, TResult>), null, propertyInfo.GetGetMethod()));
//}
}
}
//http:_//stackoverflow.com/questions/1122483/c-random-string-generator
private string RandomString(int size)
{
StringBuilder builder = new StringBuilder();
char ch;
for (int i = 0; i < size; i++)
{
ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
builder.Append(ch);
}
return builder.ToString();
}
private void SetUpReflectObjList()
{
for (int i = 0; i < 5000 ; i++)
{
ReflectClass1 reflectClass1 = new ReflectClass1();
reflectClass1.Prop1 = RandomString(15);
reflectClass1.Prop2 = RandomString(10);
reflectClass1.Prop3 = RandomString(10);
reflectClass1.Prop4 = RandomString(10);
reflectClass1.Prop5 = RandomString(10);
reflectClass1.Prop6 = RandomString(10);
reflectClass1.Prop7 = RandomString(10);
reflectClass1.Prop8 = RandomString(10);
reflectClass1.Prop9 = RandomString(10);
reflectClass1.Prop10 = RandomString(10);
dataList.Add(reflectClass1);
}
}
private void UseDelegateList()
{
Debug.WriteLine(string.Format(" Begin delegate performance test. item count = {0} start time: {1}",dataList.Count, DateTime.Now.ToLongTimeString()));
for (int i = 0; i < dataList.Count; i++)
{
foreach (PropertyInfo propertyInfo in typeof(ReflectClass1).GetProperties())
{
if (delegateList.ContainsKey(propertyInfo.Name))
{
Func<ReflectClass1, object> getPropDelegate = (Func<ReflectClass1, object>) delegateList[propertyInfo.Name];
Debug.Write(string.Format(" By delegates Object: {0} Property: {1} Value: {2}", i, propertyInfo.Name, getPropDelegate(dataList[i])));
}
}
}
Debug.WriteLine("");
Debug.WriteLine(string.Format(" End delegate performance test. item count = {0} end time: {1}", dataList.Count, DateTime.Now.ToLongTimeString()));
}
private void UseDirectReflection()
{
Debug.WriteLine(string.Format(" Begin direct reflection performance test. item count = {0} start time: {1}", dataList.Count, DateTime.Now.ToLongTimeString()));
for (int i = 0; i < dataList.Count; i++)
{
foreach (PropertyInfo propertyInfo in typeof(ReflectClass1).GetProperties())
{
if (propertyInfo == null) continue;
{
Debug.Write(string.Format(" By reflection Object: {0} Property: {1} Value: {2}", i, propertyInfo.Name, propertyInfo.GetValue(dataList[i], null)));
}
}
}
Debug.WriteLine("");
Debug.WriteLine(string.Format(" End direct reflection performance test. item count = {0} end time: {1}", dataList.Count, DateTime.Now.ToLongTimeString()));
}
private void DirectOutputTest()
{
Debug.WriteLine(string.Format(" Begin direct output benchmark. item count = {0} start time: {1}", dataList.Count, DateTime.Now.ToLongTimeString()));
for (int i = 0; i < dataList.Count; i++)
{
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop1", dataList[i].Prop1));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop2", dataList[i].Prop2));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop3", dataList[i].Prop3));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop4", dataList[i].Prop4));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop5", dataList[i].Prop5));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop6", dataList[i].Prop6));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop7", dataList[i].Prop7));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop8", dataList[i].Prop8));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop9", dataList[i].Prop9));
Debug.Write(string.Format(" direct output benchmark Object: {0} Property: {1} Value: {2}", i, "Prop10", dataList[i].Prop10));
}
Debug.WriteLine("");
Debug.WriteLine(string.Format(" End direct output benchmark. item count = {0} end time: {1}", dataList.Count, DateTime.Now.ToLongTimeString()));
}
最佳答案
2 件事:
反射的性能在较新的运行时中变得更好,因为它是 .NET 语言的主要功能,并且因为人们非常关注静态和动态性能之间的差异。我假设您在 Framework v3.5 或 4.0 中运行它;如果您要在 Framework v2.0 中执行此代码,它的性能可能会更差。
您所做的大部分工作都不是很“大量”地使用反射。动态属性调用有点繁重,但您所做的大部分工作只是获取信息。真正的重头戏是动态方法调用和动态实例创建。
假设您运行了以下测试。非常简单,唯一不同的是静态实例化和调用与反射:
public class ReflectionTest
{
public int Method1(){return 1;}
public int Method2() { return 2; }
public int Method3() { return 3; }
public int Method4() { return 4; }
public int Method5() { return 5; }
public int Method6() { return 6; }
}
[Test]
public void TestStatic()
{
for (var i = 1; i <= 100000; i++)
{
var reflectTest = new ReflectionTest();
reflectTest.Method1();
reflectTest.Method2();
reflectTest.Method3();
reflectTest.Method4();
reflectTest.Method5();
reflectTest.Method6();
}
}
[Test]
public void TestReflection()
{
var fullName = typeof (ReflectionTest).FullName;
for (var i = 1; i <= 100000; i++)
{
var type = Assembly.GetExecutingAssembly().GetType(fullName, true, true);
var reflectTest = Activator.CreateInstance(type);
for (var j = 1; j <= 6; j++)
type.GetMethod("Method" + j.ToString()).Invoke(reflectTest, null);
}
}
如果您想确保测试完全公平,您可以删除内部 for 循环并使用字符串文字“Method1”、“Method2”等调用 GetMethod 6 次。
反射测试不仅动态调用方法,它搜索 list 以找到并实例化一个 Type 对象,然后动态实例化来自 Type 的实际对象,在该对象上动态调用方法。我敢打赌,如果您同时运行这两个测试,那么第二个测试的表现会差得多。此外,探索将参数传递给这些方法;首先,您必须找到正确的重载,然后反射调用采用一个 Object[] 数组,该数组将装箱和拆箱方法的任何值类型参数,进一步减慢反射算法的速度。
简而言之,反射会比静态算法表现更差;然而,在提高其性能方面取得了长足的进步,因此从 .NET 4.0 开始,智能编写的动态算法与对应的静态算法相比并没有那么大的损失,使得反射在需要时更加可行。
编辑:并排运行上述 2 个测试后,相对差异很大:100k 次迭代的静态算法 0.07 秒,反射高达 2.12 秒。反射实例化/调用比静态实例化/调用花费的时间长 30 倍。但是,差异需要 100,000 次迭代才能显着; Debug.WriteLine 语句在我最初的测试中是迄今为止这两个测试中最慢的部分。
关于c# - 反射测试未显示预期数字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5239310/
一、反射 1.定义 Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法(即使是私有的);对于任意一个对象,都能够调用它的任意方法和属性,那么,我
有没有办法从 JavaScript 对象内部获取所有方法(私有(private)、特权或公共(public))?这是示例对象: var Test = function() { // private m
我有一个抽象类“A”,类“B”和“C”扩展了 A。我想在运行时根据某些变量创建这些实例。如下所示: public abstract class A { public abstract int
假设我们在内存中有很多对象。每个都有一个不同的ID。如何迭代内存以找到与某些 id 进行比较的特定对象?为了通过 getattr 获取并使用它? 最佳答案 您应该维护这些对象的集合,因为它们是在类属性
假设我有这个结构和一个方法: package main import ( "fmt" "reflect" ) type MyStruct struct { } func (a *MyS
C#反射简介 反射(Reflection)是C#语言中一种非常有用的机制,它可以在运行时动态获取对象的类型信息并且进行相应的操作。 反射是一种在.NET Framework中广
概述 反射(Reflection)机制是指在运行时动态地获取类的信息以及操作类的成员(字段、方法、构造函数等)的能力。通过反射,我们可以在编译时期未知具体类型的情况下,通过运行时的动态
先来看一段魔法吧 public class Test { private static void changeStrValue(String str, char[] value) {
结构体struct struct 用来自定义复杂数据结构,可以包含多个字段(属性),可以嵌套; go中的struct类型理解为类,可以定义方法,和函数定义有些许区别; struct类型是值类型
反射 1. 反射的定义 Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到那么,我们
反射的定义 java的反射(reflection) 机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性,既然能拿到嘛,那么,我们就可以
我有一个 Java POJO: public class Event { private String id; private String name; private Lon
我编写了以下函数来检查给定的单例类是否实现了特征。 /** Given a singleton class, returns singleton object if cls implements T.
我正在研究 Java 反射的基础知识并观察有关类方法的信息。我需要获得一个符合 getMethod() 函数描述的规范的方法。然而,当我这样做时,我得到了一个 NoSuchMethodExceptio
我正在通过以下代码检索 IEnumerable 属性列表: BindingFlags bindingFlag = BindingFlags.Instance | BindingFlags.Public
我需要检查属性是否在其伙伴类中定义了特定属性: [MetadataType(typeof(Metadata))] public sealed partial class Address { p
我正在尝试使用 Reflections(由 org.reflections 提供)来处理一些繁重的工作,因此我不需要在很长的时间内为每个类手动创建一个实例列表。但是,Reflections 并未按照我
scala 反射 API (2.10) 是否提供更简单的方法来搜索加载的类并将列表过滤到实现定义特征的特定类? IE; trait Widget { def turn(): Int } class
我想在运行时使用反射来查找具有给定注释的所有类,但是我不知道如何在 Scala 中这样做。然后我想获取注释的值并动态实例化每个映射到关联注释值的带注释类的实例。 这是我想要做的: package pr
这超出了我的头脑,有人可以更好地向我解释吗? http://mathworld.wolfram.com/Reflection.html 我正在制作一个 2d 突破格斗游戏,所以我需要球能够在它击中墙壁
我是一名优秀的程序员,十分优秀!