我正在尝试将最初用Java编写的TIFF编码器切换到C语言以加快速度,并使用定义了
按照他的评论所述,
Z_SOLO
的Zlib 1.2.8和一组最小的C文件:adler32.c
,crc32.c
,deflate.c
,trees.c
和zutil.c
。Java正在使用java.util.zip.Deflater
。
我编写了一个简单的测试程序来评估压缩级别和速度方面的性能,并惊讶于不管我需要什么级别,压缩效果都不会太明显,而较高级别需要更长时间。我还惊讶地发现,在压缩和速度方面,Java实际上比Visual Studio Release-compile(VC2010)表现更好:
Java:
Level 1 : 8424865 => 6215200 (73,8%) in 247 cycles.
Level 2 : 8424865 => 6178098 (73,3%) in 254 cycles.
Level 3 : 8424865 => 6181716 (73,4%) in 269 cycles.
Level 4 : 8424865 => 6337236 (75,2%) in 334 cycles.
Level 5 : 8424865 => 6331902 (75,2%) in 376 cycles.
Level 6 : 8424865 => 6333914 (75,2%) in 395 cycles.
Level 7 : 8424865 => 6333350 (75,2%) in 400 cycles.
Level 8 : 8424865 => 6331986 (75,2%) in 437 cycles.
Level 9 : 8424865 => 6331598 (75,2%) in 533 cycles.
C:
Level 1 : 8424865 => 6215586 (73.8%) in 298 cycles.
Level 2 : 8424865 => 6195280 (73.5%) in 309 cycles.
Level 3 : 8424865 => 6182748 (73.4%) in 331 cycles.
Level 4 : 8424865 => 6337942 (75.2%) in 406 cycles.
Level 5 : 8424865 => 6339203 (75.2%) in 457 cycles.
Level 6 : 8424865 => 6337100 (75.2%) in 481 cycles.
Level 7 : 8424865 => 6336396 (75.2%) in 492 cycles.
Level 8 : 8424865 => 6334293 (75.2%) in 547 cycles.
Level 9 : 8424865 => 6333084 (75.2%) in 688 cycles.
我是唯一目击这种结果的人吗?我的猜测是JVM中的Zlib使用了汇编类型的优化,而我在我的C项目中没有包含,或者在编译Zlib(或Visual Studio编译器很差)时我错过了一个明显的配置步骤。
以下是两个片段:
Java:
public static void main(String[] args) throws IOException {
byte[] pix = Files.readAllBytes(Paths.get("MY_MOSTLY_UNCOMPRESSED.TIFF"));
int szin = pix.length;
byte[] buf = new byte[szin*101/100];
int szout;
long t0, t1;
for (int i = 1; i <= 9; i++) {
t0 = System.currentTimeMillis();
Deflater deflater = new Deflater(i);
deflater.setInput(pix);
szout = deflater.deflate(buf);
deflater.finish();
t1 = System.currentTimeMillis();
System.out.println(String.format("Level %d : %d => %d (%.1f%%) in %d cycles.", i, szin, szout, 100.0f*szout/szin, t1 - t0));
}
}
C:
#include <time.h>
#define SZIN 9000000
#define SZOUT 10000000
void main(void)
{
static unsigned char buf[SZIN];
static unsigned char out[SZOUT];
clock_t t0, t1;
int i, ret;
uLongf sz, szin;
FILE* f = fopen("MY_MOSTLY_UNCOMPRESSED.TIFF", "rb");
szin = fread(buf, 1, SZIN, f);
fclose(f);
for (i = 1; i <= 9; i++) {
sz = SZOUT;
t0 = clock();
compress2(out, &sz, buf, szin, i); // I rewrote compress2, as it's not available when Z_SOLO is defined
t1 = clock();
printf("Level %d : %d => %d (%.1f%%) in %ld cycles.\n", i, szin, sz, 100.0f*sz/szin, t1 - t0);
}
}
编辑:
在 @MarkAdler 的评论后,我尝试了不同的压缩策略,通过 deflateInit2()
(即 Z_FILTERED
和 Z_HUFFMAN_ONLY
):
Z_FILTERED
:
Level 1 : 8424865 => 6215586 (73.8%) in 299 cycles.
Level 2 : 8424865 => 6195280 (73.5%) in 310 cycles.
Level 3 : 8424865 => 6182748 (73.4%) in 330 cycles.
Level 4 : 8424865 => 6623409 (78.6%) in 471 cycles.
Level 5 : 8424865 => 6604616 (78.4%) in 501 cycles.
Level 6 : 8424865 => 6595698 (78.3%) in 528 cycles.
Level 7 : 8424865 => 6594845 (78.3%) in 536 cycles.
Level 8 : 8424865 => 6592863 (78.3%) in 595 cycles.
Level 9 : 8424865 => 6591118 (78.2%) in 741 cycles.
Z_HUFFMAN_ONLY
:
Level 1 : 8424865 => 6803043 (80.7%) in 111 cycles.
Level 2 : 8424865 => 6803043 (80.7%) in 108 cycles.
Level 3 : 8424865 => 6803043 (80.7%) in 106 cycles.
Level 4 : 8424865 => 6803043 (80.7%) in 106 cycles.
Level 5 : 8424865 => 6803043 (80.7%) in 107 cycles.
Level 6 : 8424865 => 6803043 (80.7%) in 106 cycles.
Level 7 : 8424865 => 6803043 (80.7%) in 107 cycles.
Level 8 : 8424865 => 6803043 (80.7%) in 108 cycles.
Level 9 : 8424865 => 6803043 (80.7%) in 107 cycles.
按照他的评论所述,
Z_HUFFMAN_ONLY
不会改变压缩效果,但速度会快得多。在我的数据中,Z_FILTERED
并没有比Z_DEFAULT_STRATEGY
更快,而且压缩效果稍差一些。
3
是最小的。你确定你的数据没有什么奇怪的地方吗? - Peter Lawreyfis.read(pix)
可能无法读取整个文件,这种情况下,pix
的剩余部分将为零。我建议用pix = Files.readAllBytes(Paths.get("MY_MOSTLY_UNCOMPRESSED.TIFF"))
替换FileInputStream的使用。 - VGR