反射性能差这么多,有办法提高吗? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
hackingwu
V2EX    程序员

反射性能差这么多,有办法提高吗?

  •  1
     
  •   hackingwu
    hackingwu 2019-06-26 15:02:05 +08:00 3962 次点击
    这是一个创建于 2301 天前的主题,其中的信息可能已经有所发展或是发生改变。

    代码:

     public static void test() { int i = 0; } public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { int times = Integer.MAX_VALUE; Method method = ReflectTest.class.getMethod("test", null); long start = System.currentTimeMillis(); while (times-->0) { method.invoke(ReflectTest.class); } long end1 = System.currentTimeMillis(); while (++times<Integer.MAX_VALUE) { test(); } long end2 = System.currentTimeMillis(); System.out.println("end1 - start: " + (end1-start)+", end2 - end1: "+(end2-end1)); } 

    结果:end1 - start: 9137, end2 - end1: 1 查了千倍,Method 方法已经算是缓存,而且不在计时之内。计时只是 invoke 方法,差异这么大,有办法改善吗?

    16 条回复    2021-05-13 22:04:13 +08:00
    leavic
        1
    leavic  
       2019-06-26 15:03:50 +08:00
    不好意思误入了,我以为你在讨论 RF 的反射。。。
    Lin0936
        2
    Lin0936  
       2019-06-26 15:09:57 +08:00
    @leavic #1 乳房还能反射?
    BingoXuan
        3
    BingoXuan  
       2019-06-26 15:12:42 +08:00
    @Lin0936
    ls 应该说的是射频吧
    cjlmwcy
        4
    cjlmwcy  
       2019-06-26 15:15:19 +08:00
    实际操作的时候可以把方法缓存起来,会好一些
    cjlmwcy
        5
    cjlmwcy  
       2019-06-26 15:16:10 +08:00
    @cjlmwcy 没认真审题,我错了
    gz911122
        6
    gz911122  
       2019-06-26 15:16:47 +08:00


    比如 apt,编译期间生成代码
    再比如 aspectj 等字节码织入的
    guyeu
        7
    guyeu  
       2019-06-26 16:35:05 +08:00
    ```java
    method.setAccessible(true);
    ```

    可以比你现有代码的反射提升一倍的效率,再要提升效率,就木有办法了。。。其实反射和方法调用的性能差距已经在微秒级了,很多场合可以忽略这种差距。
    lingnin
        8
    lingnin  
       2019-06-26 17:18:48 +08:00
    别用 java
    firefffffffffly
        9
    firefffffffffly  
       2019-06-26 17:40:08 +08:00
    性能有差距,但是应该不会像例子里这么大, 这段代码做 benchmark 不太严谨,比如第二段代码可能会被 jit 优化到没有。
    依照这个测试 https://dzone.com/articles/the-performance-cost-of-reflection 不包含具体逻辑的情况下测试大约是差 10 倍。
    luozic
        10
    luozic  
       2019-06-26 17:47:41 +08:00 via iPhone
    缓存
    mind3x
        11
    mind3x  
       2019-06-26 17:56:03 +08:00   14
    2.6GHz 主频的 7 代 i5,MIPS(每秒执行百万条指令数)大约是 53K。

    0 循环到 max int,循环次数是 2,147,483,647,假设每个循环只执行三条指令,大约是 6K 个百万条指令。

    也就是说,一个什么也不做的从 0 到 max int 的循环,在 7 代 i5 上,大约应该花 0.1 秒这么个量级的时间。我们就放宽一点,给它再快个 10 倍,大约应该花 10ms 这个量级的时间。今天应该还没有一款 CPU 的单核 IPC 能达到 10 倍 i5 的水平。

    你猜猜看你的第二个循环为啥 1ms 就跑完了?

    因为 JIT 在跑了前面的几百或者几千次循环以后开始介入编译,发现你的 test()很小,应该内联进循环,然后就内联了。内联以后一看原来整个循环也啥也没做,就把循环也优化掉了。

    而第一个循环,反射是实打实没法优化掉的。

    这个故事告诉我们,microbenchmark 通常没什么鸟用。如果一定要做 microbenchmark,请至少正确使用 JMH,在代码里通过 JMH 的 API 强制添加副作用,避免不希望的优化发生。

    另外,即使反射比普通调用真的慢一千倍,实际到你的产品里很可能也只有不到 1%的差距。打个比方,如果你的方法本身要花 1 秒,反射花 1 毫秒,直接调用花 1 微秒,把你的方法调用 1 万次,区别也只有千分之一。
    MotherShip
        12
    MotherShip  
       2019-06-26 18:05:43 +08:00
    @mind3x 讲的很详细。。我有点想提醒楼主 JIT 的优化但是讲不出所以然来
    wdlth
        14
    wdlth  
       2019-06-26 23:14:53 +08:00
    试试 ReflectASM
    troywinter
        15
    troywinter  
       2019-06-27 20:55:47 +08:00
    #11 楼正解,java 的 microbenchmark 很重要,做跑分一定要有足够的预热,不然你测出来的结果是比 python 还慢,然而真实情况并不是这样,microbenchmark 是 java 开发者的基础。
    crazyweeds
        16
    crazyweeds  
       2021-05-13 22:04:13 +08:00
    @mind3x 活捉一头大佬
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5574 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 08:56 PVG 16:56 LAX 01:56 JFK 04:56
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86