首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否有一个有效的内存替代java.lang.String?

是否有一个有效的内存替代java.lang.String?
EN

Stack Overflow用户
提问于 2008-10-23 19:13:37
回答 14查看 22.3K关注 0票数 37

在阅读了测量几种对象类型的内存消耗的这篇旧文章之后,我惊讶地看到String在Java中使用了多少内存:

代码语言:javascript
运行
复制
length: 0, {class java.lang.String} size = 40 bytes
length: 7, {class java.lang.String} size = 56 bytes

虽然这篇文章有一些技巧来减少这一点,但我并不认为它们完全令人满意。使用char[]存储数据似乎是浪费的。对于大多数西方语言来说,最明显的改进是使用byte[]和像UTF-8这样的编码,因为您只需要一个字节来存储最频繁的字符,而不是两个字节。

当然,我们可以使用String.getBytes("UTF-8")new String(bytes, "UTF-8")。甚至字符串实例本身的开销也会消失。但是在那里你失去了非常方便的方法,比如equals()hashCode()length(),…

据我所知,Sun有一个关于字符串的专利 on byte[]表示。

用于在编程环境中高效表示字符串对象的框架 ..。这些技术可以在适当的时候作为一个字节字符数组来创建Java字符串对象.

但我没能找到那个专利的API。

为什么我在乎?

在大多数情况下,我不这样做,但我处理的应用程序具有巨大的缓存,包含了大量的String,这将从更有效地使用内存中受益。

有人知道这样的API吗?或者,是否有其他方法来保持String的内存占用空间小,即使代价是CPU性能或更丑的API?

请不要重复上述文章中的建议:

  • 自己的String.intern()变体(可能与SoftReferences一起)
  • 存储单个char[]并利用当前的String.subString(.)实现来避免数据复制(讨厌)

更新

我在Sun当前的JVM (1.6.0_10)上运行了本文中的代码。它取得了与2002年相同的结果。

EN

回答 14

Stack Overflow用户

发布于 2010-12-09 20:00:57

在JVM的帮助下.

警告:这个解决方案现在在新的Java版本中已经过时了。请参阅下面的其他临时解决方案。

如果使用Java,因为Java6UPDATE 21,您可以使用以下命令行选项:

代码语言:javascript
运行
复制
-XX:+UseCompressedStrings

JVM选项页面内容如下:

对字符串使用byte[],它可以表示为纯ASCII。(在Java 6更新21性能发布版中引入)

UPDATE:这个特性在以后的版本中被破坏了,应该在Java 6u25中再次修复,正如6u25 b03发行说明提到的那样(但是我们在6u25最终发行说明中没有看到它)。出于安全原因,错误报告7016213不可见。所以,小心使用,先检查一下。就像任何-XX选项一样,它被认为是实验性的,并且可能会在没有事先通知的情况下进行更改,所以不使用它在生产服务器的启动记录中可能并不总是最好的。

更新2013-03 (感谢https://stackoverflow.com/users/1073844/aleksey-maximus的评论):参见相关问题它接受的答案。现在这个选择似乎已经过时了。这一点在bug 7129417报告中得到了进一步证实。

只要目的正当,可以不择手段

警告:针对特定需求的(丑)解决方案

这有点太离谱了,但既然你问.别打信使!

您自己的更轻的字符串表示形式

如果ASCII适合您的需要,那么为什么不直接推出您自己的实现呢?

正如您提到的,您可以在内部使用byte[]而不是char[]。但这还不是全部。

为了做到更轻量级,为什么不使用一个助手类,而不是将您的字节数组封装在类中,它包含对您传递的这些字节数组进行操作的大多数静态方法?当然,它会让人感觉很像C-ish,但是它会工作,并将为您节省与对象一起使用的巨大开销。

当然,它会错过一些好的功能..。除非你重新实现它们。如果你真的需要它们,那就没有太多选择了。多亏了OpenJDK和许多其他好项目,您可以很好地推出您自己的只对byte[]参数进行操作的错误的LiteStrings类。每次需要调用函数时,您都会想要洗澡,但是您会节省大量的内存。

我建议使它与String类的契约非常相似,并提供有意义的适配器和构建器,以便从和从String转换而来,您可能还希望有与StringBufferStringBuilder之间的适配器,以及可能需要的其他东西的镜像实现。当然是一些工作,但可能是值得的(请看下面的“让它发挥作用!”)(第一节)

飞行压缩/减压

您可以在内存中压缩字符串,并在需要时立即解压缩它们。毕竟,当您访问它们时,您只需要能够读取它们,对吗?

当然,如此暴力意味着:

  • 更复杂(因而更不容易维护)代码,
  • 更强大的处理能力,
  • 压缩需要相对较长的字符串(或者通过实现自己的存储系统将多个字符串压缩为一个字符串,以使压缩更有效)。

双管齐下

当然,对于完全头痛的人来说,你可以做到所有这些:

  • 帮工班,
  • 字节数组,
  • 免费压缩商店。

一定要做到开源。:)

让它算数!

顺便说一句,请看N. Mitchell和G. Sevitsky:[http://domino.research.ibm.com/comm/research_people.nsf/pages/sevitsky.pubs.html/$FILE/oopsla08%20memory-efficient%20java%20slides.pdf],[http://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf]关于构建内存高效Java应用程序的精彩介绍。

从本文中,我们可以看到8字符字符串在32位系统上消耗了64字节(64位系统为96字节!!),其中大部分是由于JVM开销造成的。从这个文章中我们可以看到,一个8字节数组将只吃24字节:头的12字节,8×1字节+4字节的对齐)。

听起来这是值得的,如果你真的操纵了很多东西(可能会加速一些,因为你会花费更少的时间分配内存,但不要引用我的话,并对它进行基准测试;此外,它将在很大程度上取决于你的实现)。

票数 25
EN

Stack Overflow用户

发布于 2008-10-24 05:27:08

在Terracotta,我们有一些情况下,我们压缩大字符串,因为他们被发送到网络周围,实际上让他们压缩,直到解压缩是必要的。为此,我们将char[]转换为byte[],压缩byte[],然后将该byte[]编码回原始char[]。对于某些操作,如散列和长度,我们可以回答这些问题,而不需要解码压缩字符串。对于像大型XML字符串这样的数据,可以通过这种方式进行实质性压缩。

将压缩后的数据在网络中移动是一项肯定的胜利。保持压缩取决于用例。当然,我们有一些旋钮来关闭这个,改变压缩打开的长度,等等。

这一切都是用java.lang.String上的字节代码检测来完成的,我们发现,由于在启动时使用了早期的字符串,这是非常微妙的,但是如果您遵循一些指导原则,则是稳定的。

票数 21
EN

Stack Overflow用户

发布于 2008-10-23 21:32:25

文章指出了两件事:

  1. 字符数组以块8字节为单位增加。
  2. char[]和String对象在大小上有很大的差异。

造成这种开销的原因是包含了一个char[]对象引用和三个int:一个偏移量、一个长度和用于存储字符串的哈希代码的空间,以及简单地作为一个对象的标准开销。

与String.intern()稍有不同,或者String.substring()使用的字符数组对所有String都使用单个char[],这意味着不需要将对象引用存储在类似字符串的包装器对象中。您仍然需要偏移量,并且对您总共可以拥有多少字符设置了一个(很大的)限制。

如果使用字符串标记的特殊结尾,则不再需要长度。这为长度节省了4个字节,但标记的开销为两个字节,加上额外的时间、复杂性和缓冲区溢出风险。

如果您不经常需要哈希,则不存储散列的空时交换可能会对您有所帮助。

对于我曾经使用过的一个应用程序,在这个应用程序中,我需要对大量字符串进行超高速和内存高效的处理,我能够将数据保留在编码形式中,并处理字节数组。输出编码与输入编码相同,我不需要将字节解码为字符,也不需要将字节再编码回字节以进行输出。

此外,我可以将输入数据保留在最初读取到的字节数组中--一个内存映射文件。

我的对象包括int偏移量(限制适合我的情况)、int长度和int哈希码。

java.lang.String是我想要做的事情的耳熟能详的锤子,但不是工作的最佳工具。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/231051

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档