Speed up software CRC-32 computation by a factor of 1.5 to 3.

Use the interleaved method of Kadatch and Jenkins in order to make
use of pipelined instructions through multiple ALUs in a single
core. This also speeds up and simplifies the combination of CRCs,
and updates the functions to pre-calculate and use an operator for
CRC combination.
This commit is contained in:
Mark Adler 2018-12-11 01:11:38 -08:00
parent 41d86c73b2
commit f8719f5ae5
6 changed files with 10210 additions and 1097 deletions

33
configure vendored
View File

@ -367,8 +367,11 @@ else
try() try()
{ {
show $* show $*
( $* ) >> configure.log 2>&1 got=`( $* ) 2>&1`
ret=$? ret=$?
if test "$got" != ""; then
printf "%s\n" "$got" >> configure.log
fi
if test $ret -ne 0; then if test $ret -ne 0; then
echo "(exit code "$ret")" >> configure.log echo "(exit code "$ret")" >> configure.log
fi fi
@ -381,8 +384,11 @@ tryboth()
show $* show $*
got=`( $* ) 2>&1` got=`( $* ) 2>&1`
ret=$? ret=$?
printf %s "$got" >> configure.log if test "$got" != ""; then
printf "%s\n" "$got" >> configure.log
fi
if test $ret -ne 0; then if test $ret -ne 0; then
echo "(exit code "$ret")" >> configure.log
return $ret return $ret
fi fi
test "$got" = "" test "$got" = ""
@ -457,17 +463,11 @@ size_t dummy = 0;
EOF EOF
if try $CC -c $CFLAGS $test.c; then if try $CC -c $CFLAGS $test.c; then
echo "Checking for size_t... Yes." | tee -a configure.log echo "Checking for size_t... Yes." | tee -a configure.log
need_sizet=0
else else
echo "Checking for size_t... No." | tee -a configure.log echo "Checking for size_t... No." | tee -a configure.log
need_sizet=1 # find a size_t integer type
fi # check for long long
cat > $test.c << EOF
echo >> configure.log
# find the size_t integer type, if needed
if test $need_sizet -eq 1; then
cat > $test.c <<EOF
long long dummy = 0; long long dummy = 0;
EOF EOF
if try $CC -c $CFLAGS $test.c; then if try $CC -c $CFLAGS $test.c; then
@ -495,17 +495,13 @@ EOF
if try $CC $CFLAGS -o $test $test.c; then if try $CC $CFLAGS -o $test $test.c; then
sizet=`./$test` sizet=`./$test`
echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log echo "Checking for a pointer-size integer type..." $sizet"." | tee -a configure.log
CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}"
SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}"
else else
echo "Failed to find a pointer-size integer type." | tee -a configure.log echo "Checking for a pointer-size integer type... not found." | tee -a configure.log
leave 1
fi fi
fi fi
if test $need_sizet -eq 1; then
CFLAGS="${CFLAGS} -DNO_SIZE_T=${sizet}"
SFLAGS="${SFLAGS} -DNO_SIZE_T=${sizet}"
fi
echo >> configure.log echo >> configure.log
# check for large file support, and if none, check for fseeko() # check for large file support, and if none, check for fseeko()
@ -849,7 +845,6 @@ echo SHAREDLIBV = $SHAREDLIBV >> configure.log
echo STATICLIB = $STATICLIB >> configure.log echo STATICLIB = $STATICLIB >> configure.log
echo TEST = $TEST >> configure.log echo TEST = $TEST >> configure.log
echo VER = $VER >> configure.log echo VER = $VER >> configure.log
echo Z_U4 = $Z_U4 >> configure.log
echo SRCDIR = $SRCDIR >> configure.log echo SRCDIR = $SRCDIR >> configure.log
echo exec_prefix = $exec_prefix >> configure.log echo exec_prefix = $exec_prefix >> configure.log
echo includedir = $includedir >> configure.log echo includedir = $includedir >> configure.log

1072
crc32.c

File diff suppressed because it is too large Load Diff

10169
crc32.h

File diff suppressed because it is too large Load Diff

BIN
doc/crc-doc.1.0.pdf Normal file

Binary file not shown.

22
zlib.h
View File

@ -1724,7 +1724,7 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
negative, the result has no meaning or utility. negative, the result has no meaning or utility.
*/ */
ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
/* /*
Update a running CRC-32 with the bytes buf[0..len-1] and return the Update a running CRC-32 with the bytes buf[0..len-1] and return the
updated CRC-32. If buf is Z_NULL, this function returns the required updated CRC-32. If buf is Z_NULL, this function returns the required
@ -1758,19 +1758,17 @@ ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
*/ */
/* /*
ZEXTERN void ZEXPORT crc32_combine_gen OF((z_crc_t op[32], z_off_t len2)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t len2));
Generate the operator op corresponding to length len2, to be used with Return the operator corresponding to length len2, to be used with
crc32_combine_op(). op must have room for 32 z_crc_t values. (32 is the crc32_combine_op().
number of bits in the CRC.)
*/ */
ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, ZEXTERN uLong ZEXPORT crc32_combine_op OF((uLong crc1, uLong crc2, uLong op));
const z_crc_t *op));
/* /*
Give the same result as crc32_combine(), using op in place of len2. op is Give the same result as crc32_combine(), using op in place of len2. op is
is generated from len2 by crc32_combine_gen(). This will be faster than is generated from len2 by crc32_combine_gen(). This will be faster than
crc32_combine() if the generated op is used many times. crc32_combine() if the generated op is used more than once.
*/ */
@ -1860,7 +1858,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t));
ZEXTERN void ZEXPORT crc32_combine_gen64 OF((z_crc_t *op, z_off64_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off64_t));
#endif #endif
#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) #if !defined(ZLIB_INTERNAL) && defined(Z_WANT64)
@ -1888,7 +1886,7 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN void ZEXPORT crc32_combine_gen64 OF((z_crc_t *op, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen64 OF((z_off_t));
# endif # endif
#else #else
ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *));
@ -1897,14 +1895,14 @@ ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */
ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile));
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
ZEXTERN void ZEXPORT crc32_combine_gen OF((z_crc_t *op, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
#endif #endif
#else /* Z_SOLO */ #else /* Z_SOLO */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t));
ZEXTERN void ZEXPORT crc32_combine_gen OF((z_crc_t *op, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine_gen OF((z_off_t));
#endif /* !Z_SOLO */ #endif /* !Z_SOLO */

11
zutil.h
View File

@ -42,6 +42,17 @@ typedef unsigned short ush;
typedef ush FAR ushf; typedef ush FAR ushf;
typedef unsigned long ulg; typedef unsigned long ulg;
#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
# include <limits.h>
# if (ULONG_MAX == 0xffffffffffffffffULL)
# define Z_U8 unsigned long
# elif (ULLONG_MAX == 0xffffffffffffffffULL)
# define Z_U8 unsigned long long
# elif (UINT_MAX == 0xffffffffffffffffULL)
# define Z_U8 unsigned
# endif
#endif
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */ /* (size given to avoid silly warnings with Visual C++) */