Path: blob/master/test/hotspot/jtreg/compiler/intrinsics/zip/TestCRC32.java
41153 views
/*1* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/**24* @test25* @bug 814301226* @summary CRC32 Intrinsics support on SPARC27*28* @run main/othervm/timeout=720 -Xbatch compiler.intrinsics.zip.TestCRC32 -m29*/3031package compiler.intrinsics.zip;3233import java.nio.ByteBuffer;34import java.util.zip.CRC32;35import java.util.zip.Checksum;3637public class TestCRC32 {38// standard CRC32 polynomial39// coefficients in different forms40// normal: polyBits = 0x04c11db7 = 0b0000 0100 1100 0001 0001 1101 1011 011141// reversed: polybits = 0xedb88320 = 0b1110 1101 1011 1000 1000 0011 0010 000042// reversed reciprocal polybits = 0x82608edb = 0b1000 0010 0110 0000 1000 1110 1101 101143//44// 0 5 9 13 17 21 25 2945// | | | | | | | |46// reversed shiftL 1 polyBits = 0x1db710641L = 0b1 1101 1011 0111 0001 0000 0110 0100 000147final static long polyBits = (1L<<(32-32)) + (1L<<(32-26)) + (1L<<(32-23)) + (1L<<(32-22))48+ (1L<<(32-16)) + (1L<<(32-12)) + (1L<<(32-11)) + (1L<<(32-10))49+ (1L<<(32-8)) + (1L<<(32-7)) + (1L<<(32-5)) + (1L<<(32-4))50+ (1L<<(32-2)) + (1L<<(32-1)) + (1L<<(32-0));51final static long polyBitsShifted = polyBits>>1;5253public static void main(String[] args) throws Exception {54int offset = Integer.getInteger("offset", 0);55int msgSize = Integer.getInteger("msgSize", 512);56boolean multi = false;57int iters = 20000;58int warmupIters = 20000;5960if (args.length > 0) {61if (args[0].equals("-m")) {62multi = true;63} else {64iters = Integer.valueOf(args[0]);65}66if (args.length > 1) {67warmupIters = Integer.valueOf(args[1]);68}69}7071if (multi) {72test_multi(warmupIters);73return;74}7576System.out.println(" offset = " + offset);77System.out.println("msgSize = " + msgSize + " bytes");78System.out.println(" iters = " + iters);7980byte[] b = initializedBytes(msgSize, offset);8182final long crcReference = update_byteLoop(0, b, offset);8384CRC32 crc0 = new CRC32();85CRC32 crc1 = new CRC32();86CRC32 crc2 = new CRC32();8788crc0.update(b, offset, msgSize);89check(crc0, crcReference);9091System.out.println("-------------------------------------------------------");9293/* warm up */94for (int i = 0; i < warmupIters; i++) {95crc1.reset();96crc1.update(b, offset, msgSize);97check(crc1, crcReference);98}99100/* check correctness101* Do that before measuring performance102* to even better heat up involved methods.103*/104for (int i = 0; i < iters; i++) {105crc1.reset();106crc1.update(b, offset, msgSize);107check(crc1, crcReference);108}109report("CRCs", crc1, crcReference);110111/* measure performance112* Don't spoil times with error checking.113*/114long start = System.nanoTime();115for (int i = 0; i < iters; i++) {116crc1.reset();117crc1.update(b, offset, msgSize);118}119long end = System.nanoTime();120121double total = (double)(end - start)/1e9; // in seconds122double thruput = (double)msgSize*iters/1e6/total; // in MB/s123System.out.println("CRC32.update(byte[]) runtime = " + total + " seconds");124System.out.println("CRC32.update(byte[]) throughput = " + thruput + " MB/s");125report("CRCs", crc1, crcReference);126127System.out.println("-------------------------------------------------------");128129ByteBuffer buf = ByteBuffer.allocateDirect(msgSize);130buf.put(b, offset, msgSize);131buf.flip();132133/* warm up */134for (int i = 0; i < warmupIters; i++) {135crc2.reset();136crc2.update(buf);137buf.rewind();138check(crc2, crcReference);139}140141/* check correctness142* Do that before measuring performance143* to even better heat up involved methods.144*/145for (int i = 0; i < iters; i++) {146crc2.reset();147crc2.update(buf);148buf.rewind();149check(crc2, crcReference);150}151report("CRCs", crc2, crcReference);152153/* measure performance154* Don't spoil times with error checking.155*/156start = System.nanoTime();157for (int i = 0; i < iters; i++) {158crc2.reset();159crc2.update(buf);160buf.rewind();161}162end = System.nanoTime();163total = (double)(end - start)/1e9; // in seconds164thruput = (double)msgSize*iters/1e6/total; // in MB/s165System.out.println("CRC32.update(ByteBuffer) runtime = " + total + " seconds");166System.out.println("CRC32.update(ByteBuffer) throughput = " + thruput + " MB/s");167report("CRCs", crc2, crcReference);168169System.out.println("-------------------------------------------------------");170}171172// Just a loop over a byte array, updating the CRC byte by byte.173public static long update_byteLoop(long crc, byte[] buf, int offset) {174return update_byteLoop(crc, buf, offset, buf.length-offset);175}176177// Just a loop over a byte array, with given length, updating the CRC byte by byte.178public static long update_byteLoop(long crc, byte[] buf, int offset, int length) {179int end = length+offset;180for (int i = offset; i < end; i++) {181crc = update_singlebyte(crc, polyBitsShifted, buf[i]);182}183return crc;184}185186// Straight-forward implementation of CRC update by one byte.187// We use this very basic implementation to calculate reference188// results. It is necessary to have full control over how the189// reference results are calculated. It is not sufficient to rely190// on the interpreter (or c1, or c2) to do the right thing.191public static long update_singlebyte(long crc, long polynomial, int val) {192crc = (crc ^ -1L) & 0x00000000ffffffffL; // use 1's complement of crc193crc = crc ^ (val&0xff); // XOR in next byte from stream194for (int i = 0; i < 8; i++) {195boolean bitset = (crc & 0x01L) != 0;196197crc = crc>>1;198if (bitset) {199crc = crc ^ polynomial;200crc = crc & 0x00000000ffffffffL;201}202}203crc = (crc ^ -1L) & 0x00000000ffffffffL; // revert taking 1's complement204return crc;205}206207private static void report(String s, Checksum crc, long crcReference) {208System.out.printf("%s: crc = %08x, crcReference = %08x\n",209s, crc.getValue(), crcReference);210}211212private static void check(Checksum crc, long crcReference) throws Exception {213if (crc.getValue() != crcReference) {214System.err.printf("ERROR: crc = %08x, crcReference = %08x\n",215crc.getValue(), crcReference);216throw new Exception("TestCRC32 Error");217}218}219220private static byte[] initializedBytes(int M, int offset) {221byte[] bytes = new byte[M + offset];222for (int i = 0; i < offset; i++) {223bytes[i] = (byte) i;224}225for (int i = offset; i < bytes.length; i++) {226bytes[i] = (byte) (i - offset);227}228return bytes;229}230231private static void test_multi(int iters) throws Exception {232int len1 = 8; // the 8B/iteration loop233int len2 = 32; // the 32B/iteration loop234int len3 = 4096; // the 4KB/iteration loop235236byte[] b = initializedBytes(len3*16, 0);237int[] offsets = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 16, 32, 64, 128, 256, 512 };238int[] sizes = { 0, 1, 2, 3, 4, 5, 6, 7,239len1, len1+1, len1+2, len1+3, len1+4, len1+5, len1+6, len1+7,240len1*2, len1*2+1, len1*2+3, len1*2+5, len1*2+7,241len2, len2+1, len2+3, len2+5, len2+7,242len2*2, len2*4, len2*8, len2*16, len2*32, len2*64,243len3, len3+1, len3+3, len3+5, len3+7,244len3*2, len3*4, len3*8,245len1+len2, len1+len2+1, len1+len2+3, len1+len2+5, len1+len2+7,246len1+len3, len1+len3+1, len1+len3+3, len1+len3+5, len1+len3+7,247len2+len3, len2+len3+1, len2+len3+3, len2+len3+5, len2+len3+7,248len1+len2+len3, len1+len2+len3+1, len1+len2+len3+3,249len1+len2+len3+5, len1+len2+len3+7,250(len1+len2+len3)*2, (len1+len2+len3)*2+1, (len1+len2+len3)*2+3,251(len1+len2+len3)*2+5, (len1+len2+len3)*2+7,252(len1+len2+len3)*3, (len1+len2+len3)*3-1, (len1+len2+len3)*3-3,253(len1+len2+len3)*3-5, (len1+len2+len3)*3-7 };254CRC32[] crc1 = new CRC32[offsets.length*sizes.length];255long[] crcReference = new long[offsets.length*sizes.length];256int i, j, k;257258System.out.printf("testing %d cases ...\n", offsets.length*sizes.length);259260// Initialize CRC32 result arrays, CRC32 reference array.261// Reference is calculated using a very basic Java implementation.262for (i = 0; i < offsets.length; i++) {263for (j = 0; j < sizes.length; j++) {264crc1[i*sizes.length + j] = new CRC32();265crcReference[i*sizes.length + j] = update_byteLoop(0, b, offsets[i], sizes[j]);266}267}268269// Warm up the JIT compiler. Over time, all methods involved will270// be executed by the interpreter, then get compiled by c1 and271// finally by c2. Each calculated CRC value must, in each iteration,272// be equal to the precalculated reference value for the test to pass.273for (k = 0; k < iters; k++) {274for (i = 0; i < offsets.length; i++) {275for (j = 0; j < sizes.length; j++) {276crc1[i*sizes.length + j].reset();277crc1[i*sizes.length + j].update(b, offsets[i], sizes[j]);278check(crc1[i*sizes.length + j], crcReference[i*sizes.length + j]);279}280}281}282}283}284285286