【问题标题】:Is encapsulating Strings as byte[] in order to save memory overkill ? (Java)是否将字符串封装为 byte[] 以节省内存? (爪哇)
【发布时间】:2011-03-22 23:54:26
【问题描述】:

最近正在查看一些 Java Swing 代码并看到了这个:

byte[] fooReference;

String getFoo() {
   returns new String(fooReference); 
}

void setFoo(String foo) {
  this.fooReference = foo.getBytes();
}

以上内容对于节省您的记忆足迹可能很有用,或者我被告知。

这是不是有点矫枉过正,还有其他人以这种方式封装他们的字符串吗?

【问题讨论】:

  • 除非你要存储数千兆或千兆的字符串,否则我什至不会考虑这样做

标签: java string oop memory-management byte


【解决方案1】:

这是一个真的,真的坏主意。不要使用平台默认编码。没有什么可说的,如果你打电话给setFoo 然后getFoo 你会得到相同的数据。

如果你必须做这样的事情,那么使用 UTF-8 可以肯定地代表整个 Unicode...但我真的不会这样做。它可能节省了一些内存,但代价是大部分时间执行不必要的转换 - 并且容易出错,因为未能使用适当的编码。

我敢说有一些应用程序适合这样做,但对于其中 99.99% 的应用程序来说,这是一个糟糕的主意。

【讨论】:

  • 这甚至假设将其存储为字节并在每次访问时创建一个新字符串首先是一个好主意。
  • @mmyers:我正要这么做:)
  • 他可能使用了字符集选项,不记得了——即便如此,这似乎是一个不受欢迎的想法。很高兴我问了。
【解决方案2】:

这不是真的有用:
1. 每次调用 getFoo 或 setFoo 时都会复制字符串,因此会增加 CPU 和内存使用率
2. 晦涩难懂

【讨论】:

    【解决方案3】:

    这很可能是矫枉过正,甚至可能会消耗更多的内存,因为您现在有两个字符串副本。实际字符串的生存时间取决于客户端,但与许多此类 hack 一样,它闻起来很像过早的优化。

    【讨论】:

    • 使用的情况是在摆动客户端缓存中。被告知在 JTable 中,这将节省内存。
    【解决方案4】:

    如果在分析代码后发现字符串的内存使用存在问题,那么最好使用通用的字符串压缩器并存储压缩的字符串,而不是尝试使用 UTF-8 字符串进行小幅缩减在他们给你的空间里。使用英语字符串,您通常可以将它们压缩到每个字符 1-2 位;大多数其他语言可能是相似的。每个字符

    【讨论】:

      【解决方案5】:

      如果您预计会有很多相同的字符串,另一种更好的节省内存的方法是使用String.intern() 方法。

      【讨论】:

        【解决方案6】:

        每次调用 getFoo() 都会实例化一个新字符串。这如何节省内存?如果有的话,当这些新引用变为未引用时,您会为垃圾收集器增加额外的开销来清理这些新实例

        【讨论】:

          【解决方案7】:

          这确实没有任何意义。如果它是一个编译时间常数,您不需要将其按摩回String,那么它会让 bit 更有意义。你还是有字符编码的问题。

          如果它是 char[] 常量,对我来说会更有意义。在现实世界中,有几个 JSP 编译器将字符串常量优化为 char[],而后者又可以轻松地写入 Writer#write(char[])。这最终“稍微”更有效率,但这些小部分在 Google 搜索等大型和大量使用的应用程序中非常重要。

          Tomcat 的 JSP 编译器 Jasper 也可以做到这一点。检查genStringAsCharArray 设置。然后就是这样

          static final char[] text1 = "some static text".toCharArray();
          

          而不是

          static final String text1 = "some static text";
          

          这最终会减少开销。它不需要围绕这些字符的整个 String 实例。

          【讨论】:

            【解决方案8】:

            一点历史之旅...

            如果您可以确定在 ISO-8859-1 之外永远不需要任何东西,那么在 Java(1.0/1.1)的早期,使用字节数组而不是 String 对象实际上具有相当大的优势。与当时的虚拟机相比,使用 drawBytes() 比使用 drawString() 快 10 倍以上,而且它实际上确实节省了当时仍然非常稀缺的内存,并且小程序过去的硬编码内存屏障为 32 和反正后来 64 MB。不仅 byte[] 比 String 对象的嵌入 char[] 小,而且您还可以保存相对较重的 String 对象本身,如果您有很多短字符串,这确实会产生很大的不同。除此之外,访问纯字节数组也比使用带有所有额外边界检查的 String 的访问器方法更快。

            但是由于 drawBytes 在 Java 1.2 中不再更快,并且由于当前的 JIT 比当时的 Symantec JIT 好得多,因此 byte[] 数组相对于字符串的剩余最小性能优势不再值得麻烦。内存优势仍然存在,因此在一些非常罕见的极端情况下它可能仍然是一种选择,但现在如果不是真的必要,它就不需要考虑了。

            【讨论】:

              猜你喜欢
              • 2019-09-21
              • 2011-01-10
              • 1970-01-01
              • 2011-06-24
              • 1970-01-01
              • 1970-01-01
              • 2016-09-30
              • 2022-01-10
              相关资源
              最近更新 更多