Java 在OpenGL渲染器循环中,什么更有效率;如果;接线员还是lambda?

Java 在OpenGL渲染器循环中,什么更有效率;如果;接线员还是lambda?,java,android,functional-programming,opengl-es,Java,Android,Functional Programming,Opengl Es,当游戏的渲染开始时,部分算法会改变(处理屏幕上的点击) 有两种选择。 1.使用“如果”操作符: public class Leve1 implements GLSurfaceView.Renderer { private boolean isLoadGame = false; public void onSurfaceChanged(GL10 glUnused, int width, int height) { ... isLoadGame = true; // game

当游戏的渲染开始时,部分算法会改变(处理屏幕上的点击)

有两种选择。 1.使用“如果”操作符:

public class Leve1 implements GLSurfaceView.Renderer {
  private boolean isLoadGame = false;
  public void onSurfaceChanged(GL10 glUnused, int width, int height) {
    ...
    isLoadGame = true; // game is now loaded
  }
  // this method is called often in the render loop
  public void setPassXY(float x, float y) {
    if (isLoadGame) {
      ... // perform algorithm 
    }
  }
}
二,。使用lambda(不带“如果”):

public类Leve1实现GLSurfaceView.Renderer{
//当游戏尚未加载时,请使用空方法体
专用pressXY接口pressXY=(pressX,pressY)->{};
表面上的公共空隙已更改(GL10已涂胶、整型宽度、整型高度){
...
按XY=(passX,passY)->{
…//游戏现在已加载-添加算法
};
}
//此方法通常在渲染循环中调用
公共void setPassXY(浮点x,浮点y){
按xy.invoke(x,y);//执行算法
}
}
@功能接口
公共接口按XY接口{
无效调用(tx,uy);
}

问题:就性能而言,哪种方法更适合使用?

TL;没有一个正确的答案。这取决于很多因素。对实际应用程序进行基准测试是获得可靠答案的唯一方法


以下是一些问题:

一方面,使用lambdas的版本保存了
if
语句

另一方面,使用方法调用的版本可能由JIT编译器内联。(这些lambda调用不能内联,因为在不同的时间点,调用站点可能调用不同的lambda。)

另一方面,如果
//perform algorithm
足够复杂,它将太大而无法内联

另一方面,如果
算法
太大而无法内联,那么
if
测试的成本可能微不足道

另一方面,
if
测试可能比您想象的要便宜。例如:

  • 如果代码在切换到
    isLoadGame==true
    状态后是JIT编译的,那么统计信息可能会告诉JIT编译器在测试成功的情况下进行优化
  • (硬件)分支预测可根据该测试的模态行为进行调整
另一方面,我不清楚哪些版本需要进行简单调用或虚拟调用。或者JIT编译器是否可以优化虚拟调用。我就是不知道。(检查字节码可以给出部分答案。)

然后是不同JIT编译器版本、不同硬件ISA、不同硬件实现的问题

简言之,有太多的因素无法预测哪种方法在现实中表现更好


这也意味着微观基准不太可能有帮助。上述许多因素将在很大程度上取决于实际应用程序代码和应用程序启动的方式。您需要对实际应用程序进行基准测试,以获得有意义的结果

实现它们并让我们知道?@NormadMaker你好!如果我愿意,我可以衡量绩效)。一般来说,这是一般问题的一个特例:循环中什么更快:lamda或“if”操作符?在您的示例中,我认为必须有第三种方法:在游戏加载之前不更新,但我现在不能尝试,我只是不知道。@NomadMaker您知道,方法setPassXY()是从外部调用的(来自扩展GLSurfaceView的类),因此可以在加载游戏之前调用它。让一个类进行设置,并且只有在所有内容都已加载之后才启动游戏对象,怎么样?感谢您提供的详细答案!顺便说一下,时间测量显示了大致相同的结果。在这种情况下使用lambdas没有特别的好处。
public class Leve1 implements GLSurfaceView.Renderer {
  // when the game is not loaded yet use the empty method body
  private PressXYInterface<Float, Float> pressXY = (pressX, pressY) -> {};
  public void onSurfaceChanged(GL10 glUnused, int width, int height) {
    ...
    pressXY = (passX, passY) -> { 
      ... // game is now loaded - add algorithm
    };
  }
  // this method is called often in the render loop
  public void setPassXY(float x, float y) {
    pressXY.invoke(x, y); // perform algorithm
  }
}

@FunctionalInterface
public interface PressXYInterface<T, U> {
  void invoke(T x, U y);
}