建议压缩库尽可能小地获取byte []而不考虑cpu费用?

Err*_*404 4 java compression

如果我接近这个错误,请纠正我,但我有一个队列服务器和一群我正在集群中运行的java工作者.我的队列有很小的工作单位,但有很多.到目前为止,我的基准测试和对工人的评估表明,我的速度大约为200mb /秒.

所以我想弄清楚如何通过我的带宽获得更多的工作单位.目前我的CPU使用率不是很高(40-50%),因为它可以比网络发送数据更快地处理数据.我希望通过队列获得更多的工作,并愿意通过昂贵的压缩/解压缩来支付它(因为现在每个核心的一半都是空闲的).

我试过java LZO和gzip,但是想知道是否有更好的东西(即使它的cpu更贵)?

更新:数据是一个字节[].基本上队列只采用那种格式,所以我ByteArrayOutputStream用来写两个整数和一个int []到一个byte []格式.int []中的值都是0到100之间的整数(或1000,但绝大多数数字都是零).列表非常大,从1000到10,000个项目(再次,多数零... int []中只有100多个非零数字)

huo*_*uon 6

听起来像使用自定义压缩机制,利用数据结构可能非常有效.

首先,使用short[](16位数据类型)而不是int[]将发送的数据量减半(!),您可以这样做,因为数字很容易在-2^15(-32768)和2^15-1(32767)之间.这非常容易实现.

其次,您可以使用类似于行程编码的方案:正数表示该字母数字,而负数表示许多零(在获取绝对值之后).例如

[10, 40, 0, 0, 0, 30, 0, 100, 0, 0, 0, 0] <=> [10, 40, -3, 30, -1, 100, -4]
Run Code Online (Sandbox Code Playgroud)

这是很难实现,只是代替shortint,但将在非常最坏的情况下提供〜80%的压缩(1000号,100非零,其中没有一个是连续的).

我只是做了一些模拟来计算压缩比.我测试了上面描述的方法,以及Louis Wasserman和sbridges建议的方法.两者表现都很好.

假设数组的长度和非零数的数量均在它们的边界之间均匀,两种方法平均节省约5400 ints(或shorts),压缩大小约为原始的2.5%!运行长度编码方法似乎可以节省大约1个额外的int(或平均压缩大小减小0.03%),即基本上没有差异,因此您应该使用最容易实现的那个.以下是50000个随机样本的压缩比的直方图(它们非常相似!).

直方图

总结:使用shorts而不是ints和其中一种压缩方法,您将能够将数据压缩到原始大小的1%!

对于模拟,我使用了以下R脚本:

SIZE <- 50000

lengths <- sample(1000:10000, SIZE, replace=T)
nonzeros <- sample(1:100, SIZE, replace=T)

f.rle <- function(len, nonzero) {
  indexes <- sort(c(0,sample(1:len, nonzero, F)))
  steps <- diff(indexes)
  sum(steps > 1) + nonzero # one short per run of zeros, and one per zero
}

f.index <- function(len, nonzero) {
  nonzero * 2
}

# using the [value, -1 * number of zeros,...] method
rle.comprs <- mapply(f.rle, lengths, nonzeros)
print(mean(lengths - rle.comprs)) # average number of shorts saved

rle.ratios <- rle.comprs / lengths * 100
print(mean(rle.ratios)) # average compression ratio

# using the [(index, value),...] method
index.comprs <- mapply(f.index, lengths, nonzeros)
print(mean(lengths - index.comprs)) # average number of shorts saved

index.ratios <- index.comprs / lengths * 100
print(mean(index.ratios)) # average compression ratio


par(mfrow=c(2,1))
hist(rle.ratios, breaks=100, freq=F, xlab="Compression ratio (%)", main="Run length encoding")
hist(index.ratios, breaks=100, freq=F, xlab="Compression ratio (%)", main="Store indices")
Run Code Online (Sandbox Code Playgroud)