- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
您好,我正在尝试使用(缓存的)已编译的 lambda 表达式来访问属性,与使用 PropertyInfo.GetValue()/SetValue() 方法调用相比,我确实得到了更好(即更快)的结果。然而,我觉得它离“原生”属性速度还有很远的距离。是基准测试方法使结果与其他方法如此不同吗?
下面是我运行下面的代码后得到的结果:
Native: Elapsed = 00:00:00.0995876 (99.5876 ms); Step = 1.992E-005 ms
Lambda Expression: Elapsed = 00:00:00.5369273 (536.9273 ms); Step = 1.074E-004 ms
Property Info: Elapsed = 00:00:01.9187312 (1918.7312 ms); Step = 3.837E-004 ms
1.000 < 5.392 < 19.267
老实说,我觉得基于其他基准测试,编译后的 lambda 表达式应该比使用常规属性慢两倍,而不是慢 5 到 6 倍。
有什么想法吗?基准测试方法?编译后的 lambda 表达式的计算方式?
public static class Program
{
public static void Main(params string[] args)
{
var stepCount = 5000000UL;
var dummy = new Dummy();
const string propertyName = "Soother";
const bool propertyValue = true;
var propertyInfo = typeof(Dummy).GetProperty(propertyName);
var nativeBenchmark = Benchmark.Run("Native", stepCount, () => dummy.Soother = propertyValue);
var lambdaExpressionBenchmark = Benchmark.Run("Lambda Expression", stepCount, () => dummy.Set(propertyName, propertyValue));
var propertyInfoBenchmark = Benchmark.Run("Property Info", stepCount, () => propertyInfo.SetValue(dummy, propertyValue, null));
var benchmarkReports = new[] { nativeBenchmark, lambdaExpressionBenchmark, propertyInfoBenchmark }.OrderBy(item => item.ElapsedMilliseconds);
benchmarkReports.Join(Environment.NewLine).WriteLineToConsole();
var fastest = benchmarkReports.First().ElapsedMilliseconds;
benchmarkReports.Select(report => (report.ElapsedMilliseconds / fastest).ToString("0.000")).Join(" < ").WriteLineToConsole();
Console.ReadKey();
}
}
public class Dummy
{
public bool? Soother { get; set; } = true;
}
public class BenchMarkReport
{
#region Fields & Properties
public string Name { get; }
public TimeSpan ElapsedTime { get; }
public double ElapsedMilliseconds
{
get
{
return ElapsedTime.TotalMilliseconds;
}
}
public ulong StepCount { get; }
public double StepElapsedMilliseconds
{
get
{
return ElapsedMilliseconds / StepCount;
}
}
#endregion
#region Constructors
internal BenchMarkReport(string name, TimeSpan elapsedTime, ulong stepCount)
{
Name = name;
ElapsedTime = elapsedTime;
StepCount = stepCount;
}
#endregion
#region Methods
public override string ToString()
{
return $"{Name}: Elapsed = {ElapsedTime} ({ElapsedMilliseconds} ms); Step = {StepElapsedMilliseconds:0.###E+000} ms";
}
#endregion
}
public class Benchmark
{
#region Fields & Properties
private readonly Action _stepAction;
public string Name { get; }
public ulong StepCount { get; }
public Benchmark(string name, ulong stepCount, Action stepAction)
{
Name = name;
StepCount = stepCount;
_stepAction = stepAction;
}
#endregion
#region Constructors
#endregion
#region Methods
public static BenchMarkReport Run(string name, ulong stepCount, Action stepAction)
{
var benchmark = new Benchmark(name, stepCount, stepAction);
var benchmarkReport = benchmark.Run();
return benchmarkReport;
}
public BenchMarkReport Run()
{
return Run(StepCount);
}
public BenchMarkReport Run(ulong stepCountOverride)
{
var stopwatch = Stopwatch.StartNew();
for (ulong i = 0; i < StepCount; i++)
{
_stepAction();
}
stopwatch.Stop();
var benchmarkReport = new BenchMarkReport(Name, stopwatch.Elapsed, stepCountOverride);
return benchmarkReport;
}
#endregion
}
public static class ObjectExtensions
{
public static void WriteToConsole<TInstance>(this TInstance instance)
{
Console.Write(instance);
}
public static void WriteLineToConsole<TInstance>(this TInstance instance)
{
Console.WriteLine(instance);
}
// Goodies: add name inference from property lambda expression
// e.g. "instance => instance.PropertyName" redirected using "PropertyName"
public static TProperty Get<TInstance, TProperty>(this TInstance instance, string propertyName)
{
return FastPropertyRepository<TInstance, TProperty>.GetGetter(propertyName)(instance);
}
public static void Set<TInstance, TProperty>(this TInstance instance, string propertyName, TProperty propertyValue)
{
FastPropertyRepository<TInstance, TProperty>.GetSetter(propertyName)(instance, propertyValue);
}
}
public static class EnumerableExtensions
{
public static string Join<TSource>(this IEnumerable<TSource> source, string separator = ", ")
{
return string.Join(separator, source);
}
}
internal static class FastPropertyRepository<TInstance, TProperty>
{
private static readonly IDictionary<string, Action<TInstance, TProperty>> Setters;
private static readonly IDictionary<string, Func<TInstance, TProperty>> Getters;
static FastPropertyRepository()
{
Getters = new ConcurrentDictionary<string, Func<TInstance, TProperty>>();
Setters = new ConcurrentDictionary<string, Action<TInstance, TProperty>>();
}
public static Func<TInstance, TProperty> GetGetter(string propertyName)
{
Func<TInstance, TProperty> getter;
if (!Getters.TryGetValue(propertyName, out getter))
{
getter = FastPropertyFactory.GeneratePropertyGetter<TInstance, TProperty>(propertyName);
Getters[propertyName] = getter;
}
return getter;
}
public static Action<TInstance, TProperty> GetSetter(string propertyName)
{
Action<TInstance, TProperty> setter;
if (!Setters.TryGetValue(propertyName, out setter))
{
setter = FastPropertyFactory.GeneratePropertySetter<TInstance, TProperty>(propertyName);
Setters[propertyName] = setter;
}
return setter;
}
}
internal static class FastPropertyFactory
{
public static Func<TInstance, TProperty> GeneratePropertyGetter<TInstance, TProperty>(string propertyName)
{
var parameterExpression = Expression.Parameter(typeof(TInstance), "value");
var propertyValueExpression = Expression.Property(parameterExpression, propertyName);
var expression = propertyValueExpression.Type == typeof(TProperty) ? propertyValueExpression : (Expression)Expression.Convert(propertyValueExpression, typeof(TProperty));
var propertyGetter = Expression.Lambda<Func<TInstance, TProperty>>(expression, parameterExpression).Compile();
return propertyGetter;
}
public static Action<TInstance, TProperty> GeneratePropertySetter<TInstance, TProperty>(string propertyName)
{
var instanceParameterExpression = Expression.Parameter(typeof(TInstance));
var parameterExpression = Expression.Parameter(typeof(TProperty), propertyName);
var propertyValueExpression = Expression.Property(instanceParameterExpression, propertyName);
var conversionExpression = propertyValueExpression.Type == typeof(TProperty) ? parameterExpression : (Expression)Expression.Convert(parameterExpression, propertyValueExpression.Type);
var propertySetter = Expression.Lambda<Action<TInstance, TProperty>>(Expression.Assign(propertyValueExpression, conversionExpression), instanceParameterExpression, parameterExpression).Compile();
return propertySetter;
}
}
最佳答案
我将您的工作简化为更小的方法。它提高了整体性能,但也扩大了差距。
Native : 00:00:00.0029713 ( 2.9713ms) 5.9426E-07
Lambda Expression : 00:00:00.4356385 ( 435.6385ms) 8.71277E-05
Property Info : 00:00:01.3436626 ( 1343.6626ms) 0.00026873252
这里是使用的方法
public class Dummy
{
public bool? Soother { get; set; } = true;
}
public class Lab
{
Dummy _dummy = new Dummy();
ulong _iterations = 5000000UL;
const bool _propertyValue = true;
const string _propertyName = "Soother";
public BenchmarkReport RunNative()
{
Stopwatch stopwatch = Stopwatch.StartNew();
for (ulong i = 0; i < _iterations; i++)
{
_dummy.Soother = _propertyValue;
}
stopwatch.Stop();
return new BenchmarkReport("Native", stopwatch.Elapsed, _iterations);
}
public BenchmarkReport RunLambdaExpression()
{
Stopwatch stopwatch = Stopwatch.StartNew();
for (ulong i = 0; i < _iterations; i++)
{
_dummy.Set(_propertyName, _propertyValue);
}
stopwatch.Stop();
return new BenchmarkReport("Lambda Expression", stopwatch.Elapsed, _iterations);
}
public BenchmarkReport RunPropertyInfo()
{
PropertyInfo propertyInfo = typeof(Dummy).GetProperty(_propertyName);
Stopwatch stopwatch = Stopwatch.StartNew();
for (ulong i = 0; i < _iterations; i++)
{
propertyInfo.SetValue(_dummy, _propertyValue);
}
stopwatch.Stop();
return new BenchmarkReport("Property Info", stopwatch.Elapsed, _iterations);
}
}
public class BenchmarkReport
{
public string Name { get; set; }
public TimeSpan ElapsedTime { get; set; }
public ulong Iterations { get; set; }
public BenchmarkReport(string name, TimeSpan elapsedTime, ulong iterations)
{
Name = name;
ElapsedTime = elapsedTime;
Iterations = iterations;
}
}
以及运行它的程序
public static class Program
{
public static void Main(params string[] args)
{
Lab lab = new Lab();
List<BenchmarkReport> benchmarkReports = new List<BenchmarkReport>()
{
lab.RunNative(),
lab.RunLambdaExpression(),
lab.RunPropertyInfo()
};
foreach (var report in benchmarkReports)
{
Console.WriteLine("{0}: {1} ({2}ms) {3}",
report.Name.PadRight(20),
report.ElapsedTime,
report.ElapsedTime.TotalMilliseconds.ToString().PadLeft(10),
(double)report.ElapsedTime.TotalMilliseconds / report.Iterations);
}
Console.ReadKey();
}
}
关于c# - 已编译的 lambda 表达式用作属性 getter 和 setter : wrong benchmarking method or wrong lambda expression construction?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42221930/
我一直在阅读 JMH .但是我找不到使用它生成图的方法。 JMH 是否支持绘图?或者是否有用于此目的的第三方库? 最佳答案 JMH 不支持绘图 .您可以 写 出业绩结果存入文件 (例如使用 -rf c
**摘要:**Owasp benchmark 旨在评估安全测试工具的能力(准确率、覆盖度、扫描速度等等),量化安全测试工具的扫描能力,从而更好得比较各个安全工具优缺点。 本文分享自华为云社区《Web漏
我使用此命令在 caffe 中对我的 ConvNet 进行基准测试: ./build/tools/caffe time -model models/own_xx/deploy.prototxt -we
我知道 --benchmark_repetitions标志,这不是我需要的。 我希望能够为一个基准指定迭代次数。我可以使用 --benchmark_iterations设置所有基准的迭代次数的标志。
我有一个发送服务器发送事件的小应用程序。我想对我的应用程序进行负载测试,以便我可以对从推送消息到收到消息的延迟进行基准测试,这样我就可以知道性能何时/何处出现故障。有哪些工具可以做到这一点? 最佳答案
我对STREAM(http://www.cs.virginia.edu/stream/ref.html#runrules)基准测试有一些疑问。 以下是stream.c的评论。关于数组应为缓存大小的4倍
我开始尝试wrk。它非常易于使用,并且在服务器上非常难,但是我不知道如何执行其他类型的请求,例如POST。实际上,我什至不知道该工具是否允许。该文档非常少。 谢谢 最佳答案 现在这是可能的。这是htt
有没有可用的工具可以帮助对Kotlin中的某些代码进行基准测试? 我可以使用类似于此处建议的方法:http://www.ibm.com/developerworks/java/library/j-be
我正在尝试做一个使用 aerospike 的基准测试,例如,假设我想测试在 aerospike 中存储的文档可能是 JSON 并针对 couchbase 进行相同的测试,我可以使用什么样的工具/方法在
我们的团队在 ActiveMQ 或 RabbitMQ 之间进行选择。我们制作了 2 个小的生产者/消费者尖峰,发送带有 16 个字符串、一个时间戳和 2 个整数的数组的对象消息。我们的开发机器上的尖峰
我尝试使用 PHPExcel 手册第 4.2.1 节中的不同缓存方法。 做了一个 10 万行的基准测试,结果如下 gzip = time=50,memoryused=177734904 ser =
我开发了一个框架,供我们组织中的几个团队使用。在这个框架之上开发的那些“模块”可以表现得非常不同,但它们都非常消耗资源,即使有些比其他的更多。他们都在输入中接收数据,分析和/或转换它,然后进一步发送。
我在 Windows Server 2008 Std 上对 IIS 7 的 WCAT 6.4 的初始测试/配置遇到了问题。我们对 WCAT 还很陌生,所以这可能是一个相当幼稚的问题。 我们正在测试一个
我正在尝试在尝试优化函数之前对其执行进行计时。 (代码是 Elixir,但我使用 Erlang 的 :timer.tc。) 我的一般方法是“运行很多次,然后计算平均持续时间。”但是运行次数越多,平均值
是否有比较不同 BLAS(基本线性代数子程序)库的基准?我对单核和多核系统的稀疏矩阵乘法特别感兴趣? 最佳答案 BLAS 性能在很大程度上取决于系统,因此您最好在要使用的机器上自己进行基准测试。由于只
谁能解释为什么以下两个部分之间存在性能差异?第二个定时器调用报告的数字比第一个定时器调用报告的数字小,这在统计上很重要。我唯一的想法是 Netlogo 可以将海龟缓存在内存中。这是预期的行为还是有错误
我试图理解this javascript 代码,扩展了 jquery。我知道打电话extend jquery 对象上将添加一个 tablesorter 对象到 $ 对象。 我想清除表排序器对象上的缓存
Closed. This question does not meet Stack Overflow guidelines。它当前不接受答案。 想改善这个问题吗?更新问题,以便将其作为on-topic
已关注 this post我决定将 Julia 与 GNU Octave 进行基准测试,结果与 julialang.org 中所示的加速不一致。 . 我使用 CXXFLAGS='-std=c++11
想象一下以下案例: 1,000 个客户端连接到 Meteor 页面,显示“Somestuff”集合的内容。 “Somestuff”是一个包含 1,000 件物品的集合。 有人在“Somestuff”集
我是一名优秀的程序员,十分优秀!