我对内存空间主题感到困惑。假设我们有以下字符串:
String from = "Hello I am from Chicago";
如果我使用霍夫曼编码,LZ4或GZip等对其进行编码(此时编码算法无关紧要):
String encodedFrom= encodingLibrary.encode(from);
现在,encodedName
可以容纳的存储空间是否少于name
所需要的存储空间?
我很困惑,因为当我们存储字符串时,即使位数更少,VM(或OS本身,或其他东西)也会在末尾添加填充以完成字节。这样的事情。因此,一天结束时,编码后的字符串和 un 编码后的String的内存大小(而不是消耗量)是相同的。我认为吗?
关于第一个问题的第二个问题,我实际上想对成千上万条记录进行编码并将其存储在Redis缓存中。如果我们排除压缩/解压缩和内存消耗因素所花费的时间,结果将如何发挥?编码的字符串会在Redis缓存中占用较少的空间吗?
感谢任何帮助。
答案 0 :(得分:4)
压缩一个字符串,然后将压缩结果存储回另一个字符串中是一个非常糟糕的主意。
按照惯例,字符串是字符序列。它们应该包含字母,标点,空格和类似内容。谁发现使用它们存储二进制数据的人都会生气,因为那是非常不寻常的。
如果您要压缩字符串,请尽可能诚实,并将压缩后的数据存储在字节数组中。字节数组是通用容器,可以在其中存储任意数据。
回到您的主要问题。在Java中,String
本质上是char[]
,这意味着每个字符消耗16位(就您处理普通英语或Basic Multilingual Plane中的其他字符而言)。>
由于所有字符均为ASCII,因此每个字符都可以使用7位进行编码。在最前面添加另一位说“此字符串的其余部分仅是ASCII”,最后得到一个简单的压缩方案和1 + 23 * 7
位,共21个字节。当然,在这种情况下,最后一个字节有6位填充,但是与2 * 23
个字节按原样存储字符串相比,这已经很好了。
(我只是忘记了:自Java 9开始,纯ASCII字符串以一种特殊的方式存储,每个字符仅使用8位而不是16位。因此,我上面提出的压缩方案仅在Java 8之前有效。) / p>
使用Redis进行数据存储时,请记住,它会将所有数据保留在RAM中,并且一旦无法分配更多RAM便崩溃。 (据我所知,大约是5年前的。)因此,如果您已经可以估计Redis数据变得大于几GB,则最好选择另一个数据存储库。