java 压缩 内存_为Java中的对象实现内存压缩

在Java中搜索对象的压缩通常不是很好...不太好。

首先,您需要了解Java对象有许多不需要的附加信息。如果你拥有数百万个物体,你就会有数百万次的物质损失。

作为一个例子,让我们一个双链表。每个元素都有一个前一个和一个下一个指针+为这种交互存储一个long值(timestamp)+字节,为用户id存储两个整数。由于我们使用指针压缩,所以我们是6Bytes * 2 + 8 + 4 * 2 = 28Bytes。 Java为填充添加了8字节+ 12字节。这使得每个元素有48Bytes。

现在我们创建千万列出了20元每个(过去三年(我们要找出模式)的时间系列的用户点击事件)。

所以我们有200万* 48字节的元素= 10GB的内存(好的不多)。

好了旁边的垃圾收集杀死我们和JDK skyrocks内的开销,我们最终与10GB的内存。

现在让我们使用我们自己的内存/对象存储。我们将它作为列明智的数据表存储,其中每个对象实际上是单个行。所以我们在时间戳,上一个,下一个,userIdA和userIdB集合中有2亿行。

一个和下一个正在指向行ID,并成为4个字节(或5bytes如果我们超过40亿个条目(不太可能))。所以我们有8 + 4 + 4 + 4 + 4 => 24 * 200兆欧= 4.8GB +没有GC问题。

由于时间戳列以最小最大时间存储时间戳,我们的时间戳全部在三年之内,所以我们只需要5个字节来存储每个时间戳。由于指针现在存储为相对(+和 - ),并且由于点击系列适时关系密切,因此我们只需要前后两位用户的平均值为2字节,而用户ID则使用字典,因为点击系列对于大约500,000个用户我们只需要三个字节。所以我们现在有5 + 2 + 2 + 3 + 3 => 15 * 200Mio => 3GB + 4 * 500k * 4 = 8MB = 3GB + 8MB的字典。听起来不同于10GB的权利?

但是我们还没有完成。由于我们现在没有对象,只有行和数据,所以我们将每个系列存储为一个表行,并使用特殊的列作为数组的集合,这些列实际上存储了5个值和一个指向下5个值+指针前一个的指针。我们每个列表都有20 *(5 + 3 + 3)+ 4 * 6(允许添加部分填充元素的部分开销)=> 20(因为我们有开销),所以我们有10个每个列表20个列表* 11 + 5 * 6 => 250 * 10Mio => 2,5GB +我们可以比步行元素更快地访问阵列。

但是,嘿,它还没有结束......时间戳现在相对存储,只需要每个条目3个字节+第一个条目中的5个。 - >所以我们可以节省更多20 * 9 + 2 + 5 * 6 => 212 * 10Mio => 2,12 GB。现在使用gzip将它全部存储到内存中,因为我们可以将所有的lineary存储起来,所以它首先存储数组的长度,所有的时间戳,所有的用户标识都非常高,因此可以压缩比特中的图案。由于我们使用的是字典,我们只需根据每个用户id的可行性将其排序即可成为系列的一部分。

由于所有东西都是表格,所以你可以以几乎读取的速度反序列化所有东西,所以现代固态硬盘上的1GB成本需要2秒的时间才能加载。尝试使用序列化/反序列化,你可以听到内心的用户哭泣。

因此,在您压缩序列化数据之前,将其存储在表中,检查每个列/属性是否可以逻辑压缩。最后玩得开心。

还记得今天1TB(ECC)的价格是10k。没什么。和1TB SSD 340欧元。所以不要浪费你的时间在这个问题上,除非你真的必须这样做。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值