- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我正在编写一些调用 Field.set
的代码和 Field.get
成千上万次。显然这很慢,因为 reflection .
我想看看我是否可以使用 MethodHandle
来提高性能在 Java 7 中。到目前为止,这就是我所拥有的:
我正在做的不是 field.set(pojo, value)
:
private static final Map<Field, MethodHandle> setHandles = new HashMap<>();
MethodHandle mh = setHandles.get(field);
if (mh == null) {
mh = lookup.unreflectSetter(field);
setHandles.put(field, mh);
}
mh.invoke(pojo, value);
但是,这似乎并不比使用反射的 Field.set 调用更好。我在这里做错了吗?
我是用 invokeExact
读到的可能会更快,但是当我尝试使用它时,我得到了 java.lang.invoke.WrongMethodTypeException
.
是否有人成功地优化了对 Field.set 或 Field.get 的重复调用?
最佳答案
2015-06-01:更新以反射(reflect) @JoeC 对句柄为静态时的另一种情况的评论。还更新到最新的 JMH 并在现代硬件上重新运行。结论几乎保持不变。
请进行适当的基准测试,JMH 可以说没有那么难.一旦你这样做了,答案就显而易见了。它还可以展示invokeExact
的正确使用。 (需要目标/源 1.7 才能编译和运行):
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(3)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
public class MHOpto {
private int value = 42;
private static final Field static_reflective;
private static final MethodHandle static_unreflect;
private static final MethodHandle static_mh;
private static Field reflective;
private static MethodHandle unreflect;
private static MethodHandle mh;
// We would normally use @Setup, but we need to initialize "static final" fields here...
static {
try {
reflective = MHOpto.class.getDeclaredField("value");
unreflect = MethodHandles.lookup().unreflectGetter(reflective);
mh = MethodHandles.lookup().findGetter(MHOpto.class, "value", int.class);
static_reflective = reflective;
static_unreflect = unreflect;
static_mh = mh;
} catch (IllegalAccessException | NoSuchFieldException e) {
throw new IllegalStateException(e);
}
}
@Benchmark
public int plain() {
return value;
}
@Benchmark
public int dynamic_reflect() throws InvocationTargetException, IllegalAccessException {
return (int) reflective.get(this);
}
@Benchmark
public int dynamic_unreflect_invoke() throws Throwable {
return (int) unreflect.invoke(this);
}
@Benchmark
public int dynamic_unreflect_invokeExact() throws Throwable {
return (int) unreflect.invokeExact(this);
}
@Benchmark
public int dynamic_mh_invoke() throws Throwable {
return (int) mh.invoke(this);
}
@Benchmark
public int dynamic_mh_invokeExact() throws Throwable {
return (int) mh.invokeExact(this);
}
@Benchmark
public int static_reflect() throws InvocationTargetException, IllegalAccessException {
return (int) static_reflective.get(this);
}
@Benchmark
public int static_unreflect_invoke() throws Throwable {
return (int) static_unreflect.invoke(this);
}
@Benchmark
public int static_unreflect_invokeExact() throws Throwable {
return (int) static_unreflect.invokeExact(this);
}
@Benchmark
public int static_mh_invoke() throws Throwable {
return (int) static_mh.invoke(this);
}
@Benchmark
public int static_mh_invokeExact() throws Throwable {
return (int) static_mh.invokeExact(this);
}
}
在 1x4x2 i7-4790K、JDK 8u40、Linux x86_64 上,它产生:
Benchmark Mode Cnt Score Error Units
MHOpto.dynamic_mh_invoke avgt 25 4.393 ± 0.003 ns/op
MHOpto.dynamic_mh_invokeExact avgt 25 4.394 ± 0.007 ns/op
MHOpto.dynamic_reflect avgt 25 5.230 ± 0.020 ns/op
MHOpto.dynamic_unreflect_invoke avgt 25 4.404 ± 0.023 ns/op
MHOpto.dynamic_unreflect_invokeExact avgt 25 4.397 ± 0.014 ns/op
MHOpto.plain avgt 25 1.858 ± 0.002 ns/op
MHOpto.static_mh_invoke avgt 25 1.862 ± 0.015 ns/op
MHOpto.static_mh_invokeExact avgt 25 1.859 ± 0.002 ns/op
MHOpto.static_reflect avgt 25 4.274 ± 0.011 ns/op
MHOpto.static_unreflect_invoke avgt 25 1.859 ± 0.002 ns/op
MHOpto.static_unreflect_invokeExact avgt 25 1.858 ± 0.002 ns/op
...这表明在这种特殊情况下 MH 确实比反射快得多(这是因为对私有(private)字段的访问检查是在查找时完成的,而不是在调用时完成的)。 dynamic_*
案例模拟 MethodHandles
时的情况和/或 Fields
不是静态已知的,例如来自 Map<String, MethodHandle>
或类似的东西。相反,static_*
情况是调用者是静态已知的。
请注意,反射性能与 dynamic_*
中的 MethodHandles 相当在这种情况下,这是因为反射在 JDK 8 中得到了进一步优化(因为实际上,您不需要访问检查来读取自己的字段),所以答案可能是“只是”切换到 JDK 8 ;)
static_*
案例甚至更快,因为 MethoHandles.invoke
调用是积极内联的。这消除了 MH 案例中的部分类型检查。但是,在反射情况下,仍然存在快速检查,因此它落后了。
关于java - 如何提高 Field.set 的性能(可能使用 MethodHandles)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22244402/
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 5 年前。 Improve
我有一个 mysql 表,其中包含一个名为“id”、“name”和“number”的字段。 每一行的字段'number',都有一个数字。 id name number 1 test 30
我需要获得两个字段之间的最大和最小值。我将 JPA 2.1 与 EclipsLink 结合使用。 这是我的简化查询: SELECT GREATEST(c.min, mc.max), LEAST(c.m
我想知道是否可以询问具有相同字段名称的多个表,并且只写入一次询问的值。可能是为了避免裁员。 例如: SELECT * FROM table WHERE Table1.Status AND Ta
我想知道如何以负增量更新字段,但如果新值小于 1,则删除该行? 是否可以在 case 或 if/else block 中放置和更新语句? 目前我正在执行一个 select 语句来获取当前值,然后使用
嗨,我一直在寻找 secnhatouch 字段的 readOnly 属性,但没有找到它......有人可以帮助我解决这个问题吗 { xtype: 'textfield
SQL Server 2005 报告服务。 我想在报告文本框中使用以下内容: =IIF(IsNothing(Fields!Certification.Value), "", "Certs: "
考虑下表: un_id avl_id avl_date avl_status 1738 6377398 2011-03-10 unavailable 1738 6377399
鉴于集合将包含 50 多万份文档,每个文档都有最大数量的字段(如选项 a 所示)处理可能为空/稀疏的字段的最佳实践是什么? a)将每个具有相同字段和空字段的文档保存为 null 是否更好? { "
尝试开始使用 apioto http://apiato.io/A.getting-started/installation/ 如果我尝试测试 http://api.apiato.dev/registe
我在教程中找不到这两个指令之间的区别。 th:field="${something}"和 th:field="*{something}" 谁能告诉我一些例子? 最佳答案 Reference site
在 MongoDb 中 - 如果我的字段并不总是包含值 - 更好的做法是:在所有记录中保留相同的字段,即使有时这些字段为空或根本不创建这些字段? 10 倍! 最佳答案 字段会占用键的磁盘空间,即使没有
如何使用 factory-boy 定义依赖于其他字段的字段? 例如,我想定义一个 email这取决于 first name和 last name的 User . 我尝试使用 post_generati
嘿嘿, 我遇到了以下问题:我尝试阻止用户为“用户名”和“电子邮件”字段选择相同的值。我正在使用 jquery 表单验证插件 (http://bassistance.de/jquery-plugins/
在性能方面,哪个更适合使用? ...关于可读性/可理解性? ...关于公认的标准? SELECT * FROM Wherever WHERE Greeting IN ('hello', 'hi', '
我想知道使用 this 和 super 访问父类字段的区别。 我们有以下名为 ListItem 的抽象类,它扩展了 Node 类。 public abstract class ListItem {
假设 this 是一个指针,(2) 和 (3) 行如何在下面的 C++ 类中编译,所以应该需要 -> 符号来访问字段(如 (1) 行所示)? ( Source ) #include #include
我想更好地理解通过单独使用 this.field 和 field 来引用类字段有什么区别 this.integerField = 5; 和 integerField = 5; 最佳答案 this 关键
问题:我有一张库存表,还有一张列出正在拍卖的元素的表格。我想要一个别名字段(“isAuction”)来表示具有库存库存编号的项目是否存在于拍卖项目表中。 我写了以下查询: SELECT FROM in
如果我将包含多个字段的文档添加到 Elasticsearch 索引,当我在 Kibana 中查看它时,我每次都会得到相同的字段两次。其中之一将被称为 some_field 另一个将被调用 some_f
我是一名优秀的程序员,十分优秀!