【问题标题】:Performance and memory usage in Java arrays vs C++ arraysJava 数组与 C++ 数组的性能和内存使用情况
【发布时间】:2012-08-17 21:19:25
【问题描述】:

我在一家小公司工作,负责开发一些银行软件。现在,我必须构建一些数据结构,例如:

Array [Int-Max] [2] // Large 2D array

将其保存到磁盘并在第二天加载以备将来工作。

现在,由于我只知道 Java(和一点点 C),他们总是坚持让我使用 C++ 或 C。根据他们的建议:

  1. 他们已经看到,Java 中的 Array [Int-Max] [2] 占用的内存几乎是 C 的 1.5 倍,而 C++ 占用的内存比 Java 还要合理。

  2. C 和 C++ 可以处理任意大的文件,而 Java 不能。

根据他们的建议,随着数据库/数据结构变大,Java 变得不可行。由于我们必须处理如此庞大的数据库/数据结构,C/C++ 总是更可取。

现在我的问题是,

  1. 为什么 C 或 C++ 在大型数据库/数据结构上总是比 Java 更可取?因为,C 可能是,但 C++ 也是 OOP。那么,它如何获得优于 Java 的优势呢?

  2. 我应该继续使用 Java 还是他们的建议(切换到 C++)将来在大型数据库/数据结构环境中会有所帮助?有什么建议吗?

对不起,我对所有这些都知之甚少,刚刚开始从事一个项目,所以真的很困惑。因为到现在我才建了一些学校项目,对比较大的项目一无所知。

【问题讨论】:

  • 数组的type是什么?如果您使用 primitives,我怀疑内存使用量会很大。
  • @amit,任何类型的对象。在开始之前,我只想了解一下,我能做到多少——。因为我的时间真的很短:)。
  • 此外,您可以在实现核心之前使用预期的数组大小和存根算法对代码进行概要分析,并对其进行概要分析以查看预期的真正差异。 (假设数组确实是预期的主要空间消费者)
  • 我担心这里的要求可能比我们(作为读者)所知道的要多。也就是说,为什么要声明这么大的二维数组?没有其他实现,例如稀疏数组等本质上不会占用太多内存吗?就“大”文件而言,定义“大?”理论上,随机访问文件可以任意大,底层文件系统,然后是硬件,对性能的影响与任何事情一样多。非常广泛地,解释的 Java 字节码可能会比编译的 C++ 包含性能损失......这里有很多变量。
  • 还有一件事。在数组与 java 中分配 C++ 中的小对象时还有另一个问题。在 C++ 中,您分配一个对象数组——它们在内存中是连续的,而在 java 中——对象本身不是。在某些情况下,它可能会导致 C++ 具有更好的性能,因为它比 java 程序的缓存效率更高。我曾经在this thread 中解决过这个问题

标签: java c++ database arrays performance


【解决方案1】:

为什么 C/C++ 在大型数据库/数据结构上总是更可取 爪哇?因为,C 可能是,但 C++ 也是 OOP。那么,它是如何得到的 比 Java 有优势吗?

请记住,Java 数组(对象)1 实际上是一个引用数组。为简单起见,让我们看一个一维数组:

java:

[ref1,ref2,ref3,...,refN]
ref1 -> object1
ref2 -> object2
...
refN -> objectN

c++:

[object1,object2,...,objectN]

在使用 C++ 版本时,数组中不需要引用的开销,数组包含对象本身 - 而不仅仅是它们的引用。如果对象很小 - 这种开销可能确实很大。

另外,正如我在 cmets 中已经说过的 - 在 C++ 中分配小对象的数组与 java 中存在另一个问题。在 C++ 中,您分配一个对象数组——它们在内存中是连续的,而在 java 中——对象本身不是。在某些情况下,它可能会导致 C++ 具有更好的性能,因为它比 java 程序的缓存效率更高。我曾经在this thread 中解决过这个问题

2) 我应该继续使用 Java 还是他们的建议(切换到 C++)将是 将来对大型数据库/数据结构环境有帮助吗?任何 建议?

我不相信我们可以为您解答。您应该了解每个用于您的目的的所有优点和缺点(内存效率、可以使用的库、开发时间......)并做出决定。不要害怕从贵公司的资深开发人员那里获得建议,他们比我们拥有更多关于系统的信息。
如果这个问题有一个简单而通用的答案 - 不需要我们工程师,不是吗?

您还可以在实现核心之前使用预期的数组大小和存根算法来分析您的代码,并对其进行分析以了解预期的真正差异。 (假设数组确实是预期的主要空间消费者)


1:我接下来要描述的开销与基元数组无关。在这些情况下(原语),数组是 values 的数组,而不是 references 的数组,与 C++ 相同,数组本身的开销很小(length 字段,例如示例)。

【讨论】:

  • 非常感谢。但是,为什么java会这样做: [ref1,ref2,ref3,...,refN] ref1 -> object1 ref2 -> object2 额外步骤?意味着他们可以像 C++ 一样做。
  • 嗯,值得澄清的是,Java 中的原语(如 int)是值类型,就像在 C++ 中一样,所以这是否是一个问题取决于数组类型。
  • @Arpssss:在java中你不能“持有”一个对象,每个变量都是一个原始的或对一个对象的引用(而不是对象本身)。这同样适用于数组中的每个元素 (arr[x])。原因之一是它不需要指针(实际上在java中没有指针)。 C 中的指针让程序员很头疼,正如有人向我描述的那样:“它允许程序员射双腿。”它还有更多内容,但恐怕它不是正确的论坛。
  • @Arpssss:语言的简单性就是其中一个原因。使用嵌入类型的数组要求类型(不是引用,真实类型)是可赋值的,这反过来意味着您需要能够生成赋值运算符(否则数组将仅限于具有用户定义的类型分配),并为用户提供在需要深拷贝的情况下覆盖行为的方法。下一个问题是您不能再将null 存储在数组中,这反过来意味着类型必须提供默认构造函数才能在数组中使用...
  • ... 复杂性继续存在,您最终将 Java 从具有 reference 语义的语言更改为具有 value 语义的语言。随着复杂性的增加,你最终会得到一个不比 C++ 更好而且可能更糟的野兽。
【解决方案2】:

听起来你是一个没有经验的程序员,正在从事一份新工作。很有可能“他们”已经在这个行业工作了很长时间,并且比您更了解(或至少认为他们了解)该领域及其编程要求。

我的建议是做他们坚持要你做的事。如果他们想要 C 或 C++ 的代码,只需用 C 或 C++ 编写即可。如果你认为你会遇到困难,因为你不太了解 C / C++ ...提前警告他们。如果他们仍然坚持,他们可以承担任何问题的责任并拖延他们坚持的原因。只要确保你尽力而为......并且尽量不要成为“吱吱作响的轮子”。


1) 他们已经看到,Java 中的 Array [Int-Max] [Int-Max] 占用的内存几乎是 C 的 1.5 倍,而 C++ 占用的内存比 Java 还要合理。

这是可行的,尽管它取决于数组中的内容。

  • Java 可以使用接近最佳的内存量来表示大多数基本类型的大型数组。

  • 另一方面,Java 中的对象数组可能比 C/C++ 中占用更多的空间。例如,在 C++ 中,您通常会使用 new Foo[largeNumber] 分配一个大数组,以便所有 Foo 实例都是数组实例的一部分。在Java中,new Foo[largeNumber]实际上等价于new Foo*[largeNumber];即一个指针数组,其中每个指针通常指向不同的对象/堆节点。很容易看出这会占用更多空间。

2) C/C++ 可以处理任意大的文件,而 Java 不能。

单个一维 Java 数组中的元素数量有一个硬性限制... 2^31。 (您可以绕过这个限制,但它会使您的代码更加复杂。)

另一方面,如果您只是在谈论读取和写入文件,Java 最多可以处理 2^63 字节的单个文件......这超出了您的预期。

1) 为什么 C/C++ 在大型数据库/数据结构上总是比 Java 更可取?因为,C 可能是,但 C++ 也是 OOP。那么,它如何获得优于 Java 的优势呢?

因为硬限制。该限制是 JLS 和 JVM 规范的一部分。这与 OOP 无关本身

2) 我应该继续使用 Java 还是他们的建议(切换到 C++)将来在大型数据库/数据结构环境中会有所帮助?有什么建议吗?

听从他们的建议。如果您正在处理那么大的内存数据集,那么他们的担忧是有效的。即使他们的担忧(假设)有点夸大其词,与你的上级/前辈作战也不是一件好事......

【讨论】:

    【解决方案3】:

    1) 他们已经看到,Java 中的 Array [Int-Max] [Int-Max] 占用的内存几乎是 C 的 1.5 倍,而 C++ 占用的内存比 Java 还要合理。

    这取决于情况。如果您创建 new int[1]new int[1000],则 Java 或 C++ 几乎没有区别。如果在栈上分配数据,则相对差异较大,因为Java不使用栈来存储这些数据。

    我首先要确保这不是对应用程序进行微调。值得记住的是,您一天的时间值得(假设您获得最低工资)约为 2.5 GB。因此,除非您通过这样做每天节省 2.5 GB,否则怀疑它不值得追逐。

    2) C/C++ 可以处理任意大的文件,而 Java 不能。

    我在纯 Java 程序中映射了一个 8 TB 的文件,所以我不知道这是什么。

    有一个限制,您不能映射超过 2 GB 或在数组中包含超过 20 亿个元素。您可以通过拥有多个(例如多达 20 亿个)来解决此问题

    由于我们必须处理如此大的数据库/数据结构,C/C++ 总是更可取。

    我经常将 200 - 800 GB 的数据和超过 50 亿个条目加载到单个 Java 进程中(有时在同一台机器上一次不止一个)

    1) 为什么 C/C++ 在大型数据库/数据结构上总是比 Java 更可取?

    在 C/C++ 中如何做到这一点的经验比在 Java 中的经验要多,而他们如何做到这一点的经验只有在 C/C++ 中。

    因为,C 可能是,但 C++ 也是 OOP。那么,它如何获得优于 Java 的优势呢?

    在使用大型数据集时,在 Java 世界中使用单独的数据库更为常见(嵌入式数据库相对较少)

    Java 只是调用与 C 相同的系统调用,因此在您可以做什么方面没有真正的区别。

    2) 我应该继续使用 Java 还是他们的建议(切换到 C++)将来在大型数据库/数据结构环境中会有所帮助?有什么建议吗?

    归根结底,他们付钱给你,有时技术论点并不重要。 ;)

    【讨论】:

      猜你喜欢
      • 2020-12-19
      • 2012-03-20
      • 1970-01-01
      • 1970-01-01
      • 2016-01-05
      • 2013-08-13
      • 1970-01-01
      • 2014-09-04
      • 2015-12-08
      相关资源
      最近更新 更多