- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
(这是通过 Twitter 上的一个问题,经许可在此处重新提问)
我正在尝试快速验证某些对象(以测试空值),我认为 FastMember 可能会有所帮助 - 但是,通过下面显示的测试,我发现性能要差得多。难道我做错了什么?
public class ValidateStuffTests
{
[Test]
public void Benchmark_speed()
{
var player = CreateValidStuffToTest();
_stopwatch.Start();
CharacterActions.IsValid(player);
_stopwatch.Stop();
Console.WriteLine(_stopwatch.Elapsed);
Assert.Less(_stopwatch.ElapsedMilliseconds, 10, string.Format("IsValid took {0} mileseconds", _stopwatch.Elapsed));
}
[Test]
public void When_Benchmark_fastMember()
{
var player = CreateValidStuffToTest();
_stopwatch.Start();
CharacterActions.IsValidFastMember(player);
_stopwatch.Stop();
Assert.Less(_stopwatch.ElapsedMilliseconds, 10, string.Format("IsValid took {0} mileseconds", _stopwatch.Elapsed));
}
}
public static class ValidateStuff
{
public static bool IsValid<T>(T actions)
{
var propertyInfos = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var property in propertyInfos)
{
if (property.GetValue(actions, null) == null)
return false;
}
return true;
}
public static bool IsValidFastMember<T>(T actions)
{
var typeAccessor = TypeAccessor.Create(typeof(T));
foreach (var property in typeAccessor.GetMembers())
{
if (typeAccessor[actions, property.Name] == null)
return false;
}
return true;
}
}
最佳答案
这里的主要问题是您将元编程的 1-off 成本包括在计时内。 FastMember 在处理类型并生成合适的 IL 时会产生一些开销,当然:所有 IL 生成层都需要在此之上进行 JIT。所以是的,使用一次:FastMember 可能看起来更贵。事实上,如果你只打算做一次这项工作,你就不会使用像 FastMember 这样的东西(反射会很好)。诀窍是做所有事情一次(在两个测试中)外 时间,这样第一次运行的表现就不会影响结果。而且,在性能方面,您通常需要多次运行。这是我的装备:
const int CYCLES = 500000;
[Test]
public void Benchmark_speed()
{
var player = CreateValidStuffToTest();
ValidateStuff.IsValid(player); // warm up
var _stopwatch = Stopwatch.StartNew();
for (int i = 0; i < CYCLES; i++)
{
ValidateStuff.IsValid(player);
}
_stopwatch.Stop();
Console.WriteLine(_stopwatch.Elapsed);
Console.WriteLine("Reflection: {0}ms", _stopwatch.ElapsedMilliseconds);
}
[Test]
public void When_Benchmark_fastMember()
{
var player = CreateValidStuffToTest();
ValidateStuff.IsValidFastMember(player); // warm up
var _stopwatch = Stopwatch.StartNew();
for (int i = 0; i < CYCLES; i++)
{
ValidateStuff.IsValidFastMember(player);
}
_stopwatch.Stop();
Console.WriteLine("FastMember: {0}ms", _stopwatch.ElapsedMilliseconds);
}
null
,我实际上会认真考虑直接通过 IL 优化该案例。
[Test]
public void When_Benchmark_Metaprogramming()
{
var player = CreateValidStuffToTest();
Console.WriteLine(ValidateStuff.IsValidMetaprogramming(player)); // warm up
var _stopwatch = Stopwatch.StartNew();
for (int i = 0; i < CYCLES; i++)
{
ValidateStuff.IsValidMetaprogramming(player);
}
_stopwatch.Stop();
Console.WriteLine("Metaprogramming: {0}ms", _stopwatch.ElapsedMilliseconds);
}
public static bool IsValidMetaprogramming<T>(T actions)
{
return !NullTester<T>.HasNulls(actions);
}
T
集中在一处:
static class NullTester<T>
{
public static readonly Func<T, bool> HasNulls;
static NullTester()
{
if (typeof(T).IsValueType)
throw new InvalidOperationException("Exercise for reader: value-type T");
var props = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
var dm = new DynamicMethod("HasNulls", typeof(bool), new[] { typeof(T) });
var il = dm.GetILGenerator();
Label next, foundNull;
foundNull = il.DefineLabel();
Dictionary<Type, LocalBuilder> locals = new Dictionary<Type, LocalBuilder>();
foreach (var prop in props)
{
if (!prop.CanRead) continue;
var getter = prop.GetGetMethod(false);
if (getter == null) continue;
if (prop.PropertyType.IsValueType
&& Nullable.GetUnderlyingType(prop.PropertyType) == null)
{ // non-nullable value-type; can never be null
continue;
}
next = il.DefineLabel();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Callvirt, getter);
if (prop.PropertyType.IsValueType)
{
// have a nullable-value-type on the stack; need
// to call HasValue, which means we need it as a local
LocalBuilder local;
if (!locals.TryGetValue(prop.PropertyType, out local))
{
local = il.DeclareLocal(prop.PropertyType);
locals.Add(prop.PropertyType, local);
}
il.Emit(OpCodes.Stloc, local);
il.Emit(OpCodes.Ldloca, local);
il.Emit(OpCodes.Call,
prop.PropertyType.GetProperty("HasValue").GetGetMethod(false));
il.Emit(OpCodes.Brtrue_S, next);
}
else
{
// is a class; fine if non-zero
il.Emit(OpCodes.Brtrue_S, next);
}
il.Emit(OpCodes.Br, foundNull);
il.MarkLabel(next);
}
il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Ret);
il.MarkLabel(foundNull);
il.Emit(OpCodes.Ldc_I4_1);
il.Emit(OpCodes.Ret);
HasNulls = (Func<T, bool>)dm.CreateDelegate(typeof(Func<T, bool>));
}
}
关于.net - 为什么这里的 fastmember 看起来并不比反射快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19124401/
当使用 TypeAccessor.Create FastMember 时,似乎总是返回按字母排序的列列表。是否可以告诉它保留类中列的顺序? 例如: var testClass = new { B =
我需要提取所有不可枚举的公共(public)读写属性,除非它们是字符串。目前这是通过反射完成的,想知道这是否可以用 FastMember 完成. 我尝试了类似下面的代码,但它没有达到我想要的效果。我可
(这是通过 Twitter 上的一个问题,经许可在此处重新提问) 我正在尝试快速验证某些对象(以测试空值),我认为 FastMember 可能会有所帮助 - 但是,通过下面显示的测试,我发现性能要差得
当我尝试使用 FastMember 设置嵌套成员属性时出现异常。例如当有这些类(class)时 public class A { public B First { get; set; } }
我有以下对象: dynamic person = new {Id = 1, Name = "SpiderMan"}; 我需要能够遍历属性名称,例如“Id”,“Name”。 我还需要能够以最有效的方式实
我想用 FastMember ( https://www.nuget.org/packages/FastMember/ ) 替换我的反射索引访问器,但偶然发现了以下问题。 我有以下设置: class
我从一个我无法控制的库返回一个接口(interface): public interface IA : IB { String A { get;} } public interface IB { St
我不确定它是否受支持,但我试图让 fastmember 为我提供动态 ExpandoObject 的类型信息(使用下面的代码),但我收到错误: System.NotSupportedException
我有一个 C# .NET Core 2.0 Web API 项目(作为微服务实现)。 我在我的存储库层中使用 NuGet 包“Dapper”和“FastMember”(最新版本)来尝试转换 IEnum
我正在使用 FastMember转换 List到 Datatable .一些类包含枚举,这在将数据表作为 TVP 传递给存储过程时会导致问题。 public class MyObject {
我编写了一个方法,使用 FastMember 将通用列表转换为数据表来自 NuGet。 这是我的代码: public DataTable ConvertGenericListToDataTable(
我正在使用 FastMember 库将对象列表转换为数据表,但它返回空对象,所以任何人都可以帮我解决这个问题 List list = new List() { new { Number = 500 }
我已经使用这个函数成功地为属性和嵌套属性赋值 private static void AssignValueToProperty(ObjectAccessor accessor, object val
我从 http://code.google.com/p/fast-member/source/checkout 加载了 .net 3.5 FastMember在 VS 2010 中。 编译器生成此错误
我一直遇到这个错误 指定的参数超出了有效值的范围。参数名称:名称 当我几乎只是在这里复制示例时 https://code.google.com/p/fast-member/ 错误发生在 bcp.Wri
我是一名优秀的程序员,十分优秀!