阅读更多

2顶
0踩

编程语言

转载新闻 优化Java中的多态代码

2015-01-06 11:00 by 正式编辑 cao345657340 评论(3) 有4698人浏览
Oracle的Java是一个门快速的语言,有时候它可以和C++一样快。编写Java代码时,我们通常使用接口、继承或者包装类(wrapper class)来实现多态,使软件更加灵活。不幸的是,多态会引入更多的调用,让Java的性能变得糟糕。部分问题是,Java不建议使用完全的内联代码,即使它是非常安全的。(这个问题可能会在最新的Java版本里得到缓解,请看文章后面的更新部分)

考虑下这种情况,我们要用接口抽象出一个整型数组:
public interface Array {
    public int get(int i);
    public void set(int i, int x);
    public int size();
}

你为什么要这样做?可能是因为你的数据是保存在数据库里、网络上、磁盘上或者在其他的数据结构里。你想一次编码后就不用关心数组的具体实现。

编写一个与标准Java数组一样高效率的类并不难,不同之处在于它实现了这个接口:
public final class NaiveArray implements Array {
    protected int[] array;
 
    public NaiveArray(int cap) {
        array = new int[cap];
    }
 
    public int get(int i) {
        return array[i];
    }
 
    public void set(int i, int x) {
        array[i] = x; 
    }
 
    public int size() {
        return array.length;
    }
}

至少在理论上,NaiveArray类不会出现任何的性能问题。这个类是final的,所有的方法都很简短。

不幸的是,在一个简单的benchmark类里,当使用NavieArray作为数组实例时,你会发现NavieArray比标准数组慢5倍以上。就像这个例子:
public int compute() {
   for(int k = 0; k < array.size(); ++k)
      array.set(k,k);
   int sum = 0;
   for(int k = 0; k < array.size(); ++k)
      sum += array.get(k);
   return sum;
}

你可以通过使用NavieArray作为NavieArray的一个实例来稍微减缓性能问题(避免使用多态)。不幸的是,它依然会慢3倍多。而你仅是放弃了多态的好处。

那么,强制使用内联函数调用会怎样?

一个可行的解决方法是手动实现内联函数。你可以使用 instanceof 关键字来提供优化实现,否则你只会得到一个普通(更慢)的实现。例如,如果你使用下面的代码,NavieArray就会变得和标准数组一样快:
public int compute() {
     if(array instanceof NaiveArray) {
        int[] back = ((NaiveArray) array).array;
        for(int k = 0; k < back.length; ++k)
           back[k] = k;
        int sum = 0;
        for(int k = 0; k < back.length; ++k)
           sum += back[k];
        return sum;
     }
     //...
}

当然,我也会介绍一个维护问题作为需要实现不止一次的同类算法…… 当出现性能问题时,这是一个可接受的替代。

和往常一样,我的benchmarking代码可以在网上获取到

总结

  • 一些Java版本可能不完全支持频繁的内联函数调用,即使它可以并且应该支持。这会造成严重的性能问题。
  • 把类声明为 final 看起来不会缓解性能问题。
  • 对于消耗大的函数,可行的解决方法是自己手动优化多态和实现内联函数调用。使用 instanceof 关键字,你可以为一些特定的类编写代码并且(因此)保留多态的灵活性。

更新

Erich Schubert使用 double 数组运行简单的benchmark类发现他的运行结果与我的结果相矛盾,而且我们的变量实现都是一样的。我通过更新到最新版本的OpenJDK证明了他的结果。下面的表格给出了处理10百万整数需要的纳秒时间:

正如我们看到的,最新版本的OpenJDK十分智能,并且消除了多态的性能开销(1.8.0_40)。如果你足够幸运地在使用这个JDK,你不需要担心这 篇文章所说的性能问题。但是,这个总体思想依然值得应用在更复杂的场景里。例如,JDK优化可能依然达不到你期待的性能要求。



原文链接:点击这里
  • 大小: 28.6 KB
  • 大小: 6.4 KB
来自: ImportNew
2
0
评论 共 3 条 请登录后发表评论
3 楼 shiylqq 2015-01-08 10:08
感觉只是在告知结果,并没有说清楚为什么。有点难让人信服,只有自己写代码试试了。
2 楼 sleepcat 2015-01-08 09:15
这样子到底优化在哪里了
1 楼 beck5859509 2015-01-07 17:53

public int compute() {
   for(int k = 0; k < array.size(); ++k)
      array.set(k,k);
   int sum = 0;
   for(int k = 0; k < array.size(); ++k)
      sum += array.get(k);
   return sum;
}

这段代码哪里使用到了内联方法。
array.set(k,k);也只是转调了一下。
和((NaiveArray) array).array[k]=k;有什么不同?不都是引用到了内部array的数组地址么?谁看出来差别来了。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • java多态的代码_优化 Java 中的多态代码

    原标题:优化 Java 中的多态代码来源:ImportNew - 进林优化Java中的多态代码Oracle的Java是一个门快速的语言,有时候它可以和C++一样快。编写Java代码时,我们通常使用接口、继承或者包装类(wrapper class)来实现...

  • Java利用策略模式优化过多if else代码

    主要介绍了Java利用策略模式优化过多if else代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  • java中多态的使用和代码简化

    多态的使用 package 面向对象; /* 多态的定义:某一类事物的多种存在形态 */ /* 动物: 猫,狗 通过四个方面理解多态: 1.多态的体现 父类的引用指向了自己的子类对象. 父类的引用也可以接收自己的子类...

  • Java 中多态的实现原理

    这里的接口不应理解得太死板,比如在 Java 里面,继承一个类和实现一个接口本质上都是一种继承行为,因此都可以理解为多态的体现。 从静态和动态的角度进行划分,多态可以分为编译时多态和运行时多态。 编译时多态...

  • java多态优化多个if_代码优化-多态代替IF条件判断

    场景描述在开发的场景中,常常会遇到打折的业务需求,每个用户对应的等级,他们的打折情况也是不一样的。例如普通会员打9折,青铜会员打8.5折,黄金会员打8折等等。在一般开发中最简单的就是判断用户的等级,然后对...

  • java中多态的作用,多态的好处,以及为什么要用多态?

    看了这个,我终于知道了为什么要用多态了 看了大量的资料和视频之后,我终于搞清了多态的作用了,废话不多说,直接上干货! 多态的好处: 1.提高了代码的可维护性 2.提高了代码的扩展性 多态的作用: 可以...

  • java多态(java多态的概念)

    简述什么是JAVA中的多态 父类的引用可以引用子类的对象。换句话说,如果有一个类继承或实现了某个类或接口,那么被继承或实现的类或接口可以创建那一个类的对象,这样程序就会变得很灵活。 java中多态的定义是什么...

  • java多态理解和底层实现原理剖析

    这里的关键点在于实例变量和实例方法在数组中的占据的索引位置是不变的 ,例如: 子类继承了某个父类,子类自己的方法表中也是父类方法优先,接着是自己的方法,这样可以确保父类方法在子类和父类方法表中的索引都是...

  • Java——多态

    多态

  • Java多态的本质—动态分派

    Java语言的一大特性是多态性,所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用...

  • Java多态实现原理

    Java多态实现原理的大致过程:首先是Java编译器将Java源代码编译成class文件。在编译过程中,会根据静态类型将调用的符号引用写到class文件中。在执行时,JVM根据class文件找到调用方法的符号引用,然后在静态类型的...

  • java分支优化_优化Java分支结构代码

    java有两种分支结构:if else结构,switch case结构在项目开发过程中,涉及到部分逻辑特别复杂,可能需要写很长的if else结构或者switch case结构,特别是相同的逻辑判断出现在很多地方时,这样的代码可读性和可维护...

  • JAVA继承和多态详细讲解

    面向对象编程的重要知识:继承和多态。...从Java语言的底层逻辑上看,封装和继承是为实现多态做准备的。6.1 类的继承继承描述了类的所属关系,多个类通过继承可形成一个关系体系,进而在原有类的基础上

  • Java编程实现静态多态_Java 多态的实现机制

    (给ImportNew加星标,提高Java技能)转自:博客园,作者:crane_practice链接:...就是引用变量所指向的具体实现对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。浅...

  • Java方法重写与多态

    Java方法重写以及Object方法笔记

  • java函数多态_Java 多态

    Java多态,在之前的向上转型的文章中已经介绍了使用场景和为什么要通过向上转型实现运行时多态,请先看文章:张舰:Java 向上转型和向下转型这篇文章主要是总结一下Java多态的概念,具体的例子请参考向上转型那篇...

  • java的多态机制是什么_Java多态的实现机制是什么,写得非常好!

    practicewww.cnblogs.com/crane-practice/p/3671074.html2019-06-13 08:46:00Java多态的实现机制是父类或接口定义的引用变量可以指向子类或实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所...

  • java多态优化多个if_脑壳疼!代码中那么多“烦人”的if else

    虽然他是伪代码,并且看起来也很夸张,但在现实中,当我们无数次 Review 别人代码时,都会发现类似的场景。那么我们本文就来详细聊聊,有没有什么方法可以让我们避免来写这么多的 if else 呢?我们本文提供了 9 种...

  • 基于FPGA的四相八拍步进电机控制系统设计:集成交付、正反转、加速减速及调速功能

    内容概要:本文详细介绍了基于FPGA的四相八拍步进电机控制系统的开发过程。主要内容包括:1. 使用VHDL和Verilog编写LED显示屏驱动代码,用于显示角度、学号和姓名等信息;2. 实现步进电机的正反转控制,通过状态机管理相序变化;3. 开发加速减速控制模块,确保电机启动和停止时的平稳性;4. 设计调速功能,通过调节脉冲频率实现速度控制。此外,文中还讨论了调试过程中遇到的问题及其解决方案。 适合人群:对FPGA开发和步进电机控制感兴趣的电子工程师、嵌入式系统开发者以及相关专业的学生。 使用场景及目标:适用于需要高精度运动控制的应用场合,如工业自动化、机器人技术和精密仪器等领域。目标是帮助读者掌握FPGA控制步进电机的基本原理和技术细节。 其他说明:文中提供了详细的代码片段和调试经验分享,有助于读者更好地理解和应用所学知识。同时,作者还提到了一些实用技巧,如通过PWM调节实现多级变速,以及如何避免步进电机的共振问题。

Global site tag (gtag.js) - Google Analytics