我有以下util类用于crc32计算:
import java.util.zip.CRC32;
import java.util.zip.Checksum;
public class StringUtils {
public static long crc32(String input) {
byte[] bytes = input.getBytes();
Checksum checksum = new CRC32();
checksum.update(bytes, 0, bytes.length);
return checksum.getValue();
}
}
表现对我来说是非常重要的标准。
现在,我正在考虑对该方法进行可能的重构,并且正在考虑将checksum
其作为静态字段移到类级别上,如下所示:
public class StringUtils {
public static Checksum checksum = new CRC32();
public static long crc32(String input) {
byte[] bytes = input.getBytes();
checksum.update(bytes, 0, bytes.length);
return checksum.getValue();
}
}
但我不确定它是否可以在并发多线程环境中正常工作。请告知-这种重构是个好主意。
就像其他人所说的那样,CRC32不是线程安全的,因此您必须同步或使用ThreadLocal,但是它们并不是特别有帮助。
如果您看一下CRC32的实现,则是一个字段。在执行任何操作之前,请对代码进行基准测试。在Java的复杂GC,JIT和转义分析之间,很难预测您是否会看到任何好处。
重写此代码以避免数组分配可能会给您带来更大的好处:
byte[] bytes = input.getBytes();
编辑:除非绝对必要,否则请不要这样做。
这会展开String的内部getBytes()
以避免某些中间缓冲,并利用CRC32对直接字节缓冲区进行了优化的优势:
public class StringUtils {
private static final ThreadLocal<ByteBuffer> BUFFER = ThreadLocal.withInitial(() -> ByteBuffer.allocateDirect(4094));
public static long crc32(String input) {
CharBuffer inputBuffer = CharBuffer.wrap(input);
ByteBuffer buffer = BUFFER.get();
CRC32 crc32 = new CRC32();
CharsetEncoder encoder = Charset.defaultCharset().newEncoder();
CoderResult coderResult;
do {
try {
coderResult = encoder.encode(inputBuffer, buffer, true);
buffer.flip();
crc32.update(buffer);
} finally {
buffer.reset();
}
} while (coderResult.isOverflow());
return crc32.getValue();
}
}
通过手动进行编码(对于ASCII而言这是微不足道的),您甚至可以做得更好。使性能复杂化的是平衡将字节复制到缓冲区中,以通过对实际CRC32实现的JNI调用读出字节。实际上,由于JNI开销,中间缓冲区可能会更快。在执行此操作之前,请确保先读取直接字节缓冲区。如果您实际上并没有重用缓冲区,则速度可能会很慢。
当您真正了解正在发生的事情时,您会发现这getBytes()
比您想像的要复杂得多,并且担心分配一个琐碎的,短暂的CRC32对象并不是对性能的主要贡献。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句