草庐IT

java - 在 Java 中声明一个内联数组会更快(或更好)吗?

coder 2023-09-03 原文

考虑以下两个几乎相同的方法调用。注意在两者上声明和分配字节数组的方式。

void Method1()
{
    byte [] bytearray = new byte[16];

    /* some code */

}

void Method2()
{
    byte [] bytearray = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    /* some code */    
}

在这两种情况下,假设当 Method1 和 Method2 返回时,“bytearray”是垃圾回收的候选者,因为操作 bytearray 变量的代码都不会持有超过方法本身末尾的引用。

方法 2 是否通过避免调用“new”而运行得更快(或不同)?或者上面的两个实现是等价的?在任何一种情况下,Java 编译器或运行时是否可以进行优化以避免为这个短暂的临时缓冲区命中内存分配器的开销?

最佳答案

哪种形式最快? 取决于 JIT - 它们可能是等价的。如果有的话,很少有程序会注意到差异。

哪种形式最好?几乎无一异常(exception)地是那种能让你的程序更具可读性的形式。

但无论我们是否会注意到,是否存在任何实际差异?一起来看看吧!

class ArrayTest {

    public int[] withNew() {
        int[] arr = new int[4];
        return arr;
    }

    public int[] withInitializer() {
        int[] arr = {0, 0, 0, 0};
        return arr;
    }

}

我们用 javap -c ArrayTest 反汇编:

Compiled from "ArrayTest.java"
class ArrayTest {
  ArrayTest();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public int[] withNew();
    Code:
       0: iconst_4      
       1: newarray       int
       3: astore_1      
       4: aload_1       
       5: areturn       

  public int[] withInitializer();
    Code:
       0: iconst_4      
       1: newarray       int
       3: dup           
       4: iconst_0      
       5: iconst_0      
       6: iastore       
       7: dup           
       8: iconst_1      
       9: iconst_0      
      10: iastore       
      11: dup           
      12: iconst_2      
      13: iconst_0      
      14: iastore       
      15: dup           
      16: iconst_3      
      17: iconst_0      
      18: iastore       
      19: astore_1      
      20: aload_1       
      21: areturn       
}

不,在这种情况下它们不一样——使用初始化器形式导致槽被单独设置为 0,这有点毫无意义,因为它们已经被数组分配归零。所以,它基本上等同于:

public int[] withNewAndSettingExplicitly() {
    int[] arr = new int[4];
    arr[0] = 0;
    arr[1] = 0;
    arr[2] = 0;
    arr[3] = 0;
    return arr;
}

尽管它编译成另一组字节码,它们大部分相同但不完全相同:

  public int[] withNewAndSettingExplicitly();
    Code:
       0: iconst_4      
       1: newarray       int
       3: astore_1      
       4: aload_1       
       5: iconst_0      
       6: iconst_0      
       7: iastore       
       8: aload_1       
       9: iconst_1      
      10: iconst_0      
      11: iastore       
      12: aload_1       
      13: iconst_2      
      14: iconst_0      
      15: iastore       
      16: aload_1       
      17: iconst_3      
      18: iconst_0      
      19: iastore       
      20: aload_1       
      21: areturn 

因此,故事的寓意是:如果您希望所有元素都设置为 0,您将使用 new int[size] 生成更少的字节码(可能会或可能不会更快),但您还必须减少输入(恕我直言,这是一个巨大的胜利)。如果您想在分配数组时直接设置数组中的值,请使用代码中看起来最好的任何内容,因为无论您选择何种形式,生成的代码都几乎相同。

现在,回答您的实际问题:

Does Method2 operate any faster (or differently) by avoiding the call to "new"?

正如我们所见,new 只是隐藏在初始化语法后面(寻找 newarray 操作码)。顺便说一句,JVM 中的分配成本非常低(分代垃圾收集器具有令人愉快的副作用)。

Or are the two implementations above equivalent?

正如我们所见 - 不完全是,但不太可能有人会注意到差异。

In either case, can the Java compiler or runtime make an optimization to avoid the overhead of hitting the memory allocator for this short-lived temporary buffer?

再一次 - 分配很便宜,所以不用担心。然而,最近的 JVM 有一个叫做 escape analysis 的小特性。这可能会导致数组被分配到堆栈而不是堆上。

关于java - 在 Java 中声明一个内联数组会更快(或更好)吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20348818/

有关java - 在 Java 中声明一个内联数组会更快(或更好)吗?的更多相关文章

  1. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  2. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  3. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  7. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  8. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  9. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  10. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

随机推荐