--- a/CRC32Stream.st Sat Mar 23 21:49:56 2019 +0100
+++ b/CRC32Stream.st Sat Mar 23 21:54:24 2019 +0100
@@ -43,35 +43,39 @@
# ifdef __LP64__
# define uint64_t __uint64__
# endif
- typedef unsigned int uint32_t;
- typedef unsigned short uint16_t;
- typedef unsigned char uint8_t;
+ // typedef unsigned int uint32_t;
+ // typedef unsigned short uint16_t;
+ // typedef unsigned char uint8_t;
# endif
-#ifdef HAS_CRC
+# ifdef HAS_CRC
-# if __POINTER_SIZE__ == 8
+# if __POINTER_SIZE__ == 8
static inline __uint64__
__crc32_u64(__uint64__ crc, __uint64__ value) {
asm("crc32q %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
-# endif
+# endif
-static inline uint32_t __crc32_u32(uint32_t crc, uint32_t value) {
+static inline uint32_t
+__crc32_u32(uint32_t crc, uint32_t value) {
asm("crc32l %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
-static inline uint32_t __crc32_u16(uint32_t crc, uint16_t value) {
+static inline uint32_t
+__crc32_u16(uint32_t crc, uint16_t value) {
asm("crc32w %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
-static inline uint32_t __crc32_u8(uint32_t crc, uint8_t value) {
+static inline uint32_t
+__crc32_u8(uint32_t crc, uint8_t value) {
asm("crc32b %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
+
# endif // HAS_CRC
#endif // x86 or x86_64
%}
@@ -141,55 +145,55 @@
"
expect 60C1D0A0
- [exBegin]
+ [exBegin]
self information:(CRC32Stream hashValueOf:'resume') hexPrintString
- [exEnd]
+ [exEnd]
expect 16r60C1D0A0
- [exBegin]
+ [exBegin]
self information:(CRC32Stream new
- nextPut:$r;
- nextPut:$e;
- nextPut:$s;
- nextPut:$u;
- nextPut:$m;
- nextPut:$e;
- hashValue) hexPrintString
- [exEnd]
+ nextPut:$r;
+ nextPut:$e;
+ nextPut:$s;
+ nextPut:$u;
+ nextPut:$m;
+ nextPut:$e;
+ hashValue) hexPrintString
+ [exEnd]
expect 16r70E46888:
- [exBegin]
+ [exBegin]
self information:(CRC32Stream hashValueOf:#[1 2 3 4 5 6 7]) hexPrintString
- [exEnd]
+ [exEnd]
expect 16r8CD04C73:
- [exBegin]
+ [exBegin]
self information:((CRC32Stream hashValueOf:#[16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
- 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
- 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
- 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF]) hexPrintString)
- [exEnd]
+ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
+ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
+ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF]) hexPrintString)
+ [exEnd]
timing throughput:
230Mb/s (on MacBook Pro 2012 / 2.6Ghz I7)
- [exBegin]
+ [exBegin]
|hashStream n t|
hashStream := CRC32Stream new.
n := 2000000.
t := Time millisecondsToRun:[
- n timesRepeat:[
- hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
- ].
- ].
+ n timesRepeat:[
+ hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
+ ].
+ ].
t := (t / 1000) asFloat.
Transcript show:'crc32:'; showCR: hashStream hashValue hexPrintString.
Transcript show:t; show:' seconds for '; show:(50*n/1024/1024) asFloat; showCR:' Mb'.
Transcript show:(n*50/1024/1024 / t); showCR:' Mb/s'
- [exEnd]
+ [exEnd]
500Mb/s (on MacBook Pro 2012 / 2.6Ghz I7)
- [exBegin]
+ [exBegin]
|hashStream s n t l|
hashStream := CRC32Stream newCastagnoli.
@@ -197,17 +201,17 @@
s := '12345678901234567890123456789012345678901234567890'.
l := s size.
t := Time millisecondsToRun:[
- n timesRepeat:[
- hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
- ].
- ].
+ n timesRepeat:[
+ hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
+ ].
+ ].
t := (t / 1000) asFloat.
Transcript show:'crc32:'; showCR: hashStream hashValue hexPrintString.
Transcript show:t; show:' seconds for '; show:(l*n/1024/1024) asFloat; showCR:' Mb'.
Transcript show:(n*l/1024/1024 / t); showCR:' Mb/s'
- [exEnd]
+ [exEnd]
the real speed is shown with longer inputs...
- [exBegin]
+ [exBegin]
|hashStream n t l s|
hashStream := CRC32Stream newCastagnoli.
@@ -215,42 +219,42 @@
s := '1234567890' ,* 10000.
l := s size.
t := Time millisecondsToRun:[
- n timesRepeat:[
- hashStream nextPutAll:s
- ].
- ].
+ n timesRepeat:[
+ hashStream nextPutAll:s
+ ].
+ ].
t := (t / 1000) asFloat.
Transcript show:'crc32:'; showCR: hashStream hashValue hexPrintString.
Transcript show:t; show:' seconds for '; show:(l*n/1024/1024) asFloat; showCR:' Mb'.
Transcript show:(n*l/1024/1024 / t); showCR:' Mb/s'
- [exEnd]
+ [exEnd]
test vectors from https://tools.ietf.org/html/rfc3720#page-217:
expect 0
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:'') hexPrintString
- [exEnd]
+ [exEnd]
expect C1D04330
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:'a') hexPrintString
- [exEnd]
+ [exEnd]
expect E3069283
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:'123456789') hexPrintString
- [exEnd]
+ [exEnd]
expect 8A9136AA
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:(ByteArray new:32 withAll:0)) hexPrintString
- [exEnd]
+ [exEnd]
expect 62a8ab43
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:(ByteArray new:32 withAll:16rFF)) hexPrintString
- [exEnd]
+ [exEnd]
expect 46dd794e
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:(0 to:31) asByteArray) hexPrintString
- [exEnd]
+ [exEnd]
"
! !
@@ -427,7 +431,6 @@
and works only for the castagnoli polynom"
%{ /* NOCONTEXT */
-#define HAS_CRC
#if defined(HAS_CRC)
int len, offs;
@@ -437,109 +440,109 @@
offs = __intVal(start) - 1;
if (__bothSmallInteger(count, start)) {
- int objSize;
- unsigned char *extPtr;
+ int objSize;
+ unsigned char *extPtr;
- // the most common first
- if (__isStringLike(anObject)) {
- objSize = __stringSize(anObject);
- extPtr = (unsigned char *)__stringVal(anObject);
- } else if (__isByteArray(anObject)) {
- objSize = __byteArraySize(anObject);
- extPtr = (unsigned char *)__byteArrayVal(anObject);
- } else if (__isExternalBytesLike(anObject)) {
- OBJ sz = __externalBytesSize(anObject);
+ // the most common first
+ if (__isStringLike(anObject)) {
+ objSize = __stringSize(anObject);
+ extPtr = (unsigned char *)__stringVal(anObject);
+ } else if (__isByteArray(anObject)) {
+ objSize = __byteArraySize(anObject);
+ extPtr = (unsigned char *)__byteArrayVal(anObject);
+ } else if (__isExternalBytesLike(anObject)) {
+ OBJ sz = __externalBytesSize(anObject);
- extPtr = (unsigned char *)__externalBytesAddress(anObject);
- if (__isSmallInteger(sz)) {
- objSize = __intVal(sz);
- } else {
- objSize = 0; /* unknown */
- }
- } else {
- int nInstVars, nInstBytes;
- OBJ oClass = __Class(anObject);
+ extPtr = (unsigned char *)__externalBytesAddress(anObject);
+ if (__isSmallInteger(sz)) {
+ objSize = __intVal(sz);
+ } else {
+ objSize = 0; /* unknown */
+ }
+ } else {
+ int nInstVars, nInstBytes;
+ OBJ oClass = __Class(anObject);
- switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
- case BYTEARRAY:
- case WORDARRAY:
- case LONGARRAY:
- case SWORDARRAY:
- case SLONGARRAY:
- case FLOATARRAY:
- case DOUBLEARRAY:
- break;
- default:
- goto bad;
- }
- nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
- nInstBytes = __OBJS2BYTES__(nInstVars);
- // nInstBytes is the number of bytes occupied by pointer instance variables
- // subtract from size and add to byte-pointer
- objSize = __qSize(anObject) - OHDR_SIZE - nInstBytes;
- extPtr = (unsigned char *)__byteArrayVal(anObject)+nInstBytes;
- }
+ switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+ case BYTEARRAY:
+ case WORDARRAY:
+ case LONGARRAY:
+ case SWORDARRAY:
+ case SLONGARRAY:
+ case FLOATARRAY:
+ case DOUBLEARRAY:
+ break;
+ default:
+ goto bad;
+ }
+ nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+ nInstBytes = __OBJS2BYTES__(nInstVars);
+ // nInstBytes is the number of bytes occupied by pointer instance variables
+ // subtract from size and add to byte-pointer
+ objSize = __qSize(anObject) - OHDR_SIZE - nInstBytes;
+ extPtr = (unsigned char *)__byteArrayVal(anObject)+nInstBytes;
+ }
- if ((offs >= 0) && (len >= 0) && (objSize >= (len + offs))) {
- unsigned int _crc;
- unsigned int *_crcTable = __integerArrayVal( __INST(crcTable) );
- unsigned char *cp = extPtr+offs;
- unsigned int n = len;
+ if ((offs >= 0) && (len >= 0) && (objSize >= (len + offs))) {
+ unsigned int _crc;
+ unsigned int *_crcTable = __integerArrayVal( __INST(crcTable) );
+ unsigned char *cp = extPtr+offs;
+ unsigned int n = len;
- _crc = (unsigned int) (__intVal( __INST(crc) ));
- if (!__isSmallInteger(__INST(crc))) {
- _crc = __unsignedLongIntVal( __INST(crc) );
- }
+ _crc = (unsigned int) (__intVal( __INST(crc) ));
+ if (!__isSmallInteger(__INST(crc))) {
+ _crc = __unsignedLongIntVal( __INST(crc) );
+ }
# if __POINTER_SIZE__ == 8
- if (((unsigned INT)cp & 7) == 0) {
- // longword aligned
- for ( ; n >= 32 ; n -= 32, cp += 32) {
- unsigned INT w0 = ((unsigned INT *)cp)[0];
- unsigned INT w1, w2, w3;
+ if (((unsigned INT)cp & 7) == 0) {
+ // longword aligned
+ for ( ; n >= 32 ; n -= 32, cp += 32) {
+ unsigned INT w0 = ((unsigned INT *)cp)[0];
+ unsigned INT w1, w2, w3;
- _crc = __crc32_u64(_crc, w0);
- w1 = ((unsigned INT *)cp)[1];
- _crc = __crc32_u64(_crc, w1);
- w2 = ((unsigned INT *)cp)[2];
- _crc = __crc32_u64(_crc, w2);
- w3 = ((unsigned INT *)cp)[3];
- _crc = __crc32_u64(_crc, w3);
- }
- for ( ; n >= 8 ; n -= 8, cp += 8) {
- _crc = __crc32_u64(_crc, ((unsigned INT *)cp)[0]);
- }
- }
+ _crc = __crc32_u64(_crc, w0);
+ w1 = ((unsigned INT *)cp)[1];
+ _crc = __crc32_u64(_crc, w1);
+ w2 = ((unsigned INT *)cp)[2];
+ _crc = __crc32_u64(_crc, w2);
+ w3 = ((unsigned INT *)cp)[3];
+ _crc = __crc32_u64(_crc, w3);
+ }
+ for ( ; n >= 8 ; n -= 8, cp += 8) {
+ _crc = __crc32_u64(_crc, ((unsigned INT *)cp)[0]);
+ }
+ }
# endif // __POINTER_SIZE__ == 8
- if (((unsigned INT)cp & 3) == 0) {
- // word aligned
- for ( ; n >= 4 ; n -= 4, cp += 4) {
- _crc = __crc32_u32(_crc, ((unsigned int *)cp)[0]);
- }
- }
- for ( ; n >= 4 ; n -= 4, cp += 4) {
- _crc = __crc32_u8(_crc, cp[0]);
- _crc = __crc32_u8(_crc, cp[1]);
- _crc = __crc32_u8(_crc, cp[2]);
- _crc = __crc32_u8(_crc, cp[3]);
- }
- while (n-- > 0) {
- unsigned char ch = *cp++;
+ if (((unsigned INT)cp & 3) == 0) {
+ // word aligned
+ for ( ; n >= 4 ; n -= 4, cp += 4) {
+ _crc = __crc32_u32(_crc, ((unsigned int *)cp)[0]);
+ }
+ }
+ for ( ; n >= 4 ; n -= 4, cp += 4) {
+ _crc = __crc32_u8(_crc, cp[0]);
+ _crc = __crc32_u8(_crc, cp[1]);
+ _crc = __crc32_u8(_crc, cp[2]);
+ _crc = __crc32_u8(_crc, cp[3]);
+ }
+ while (n-- > 0) {
+ unsigned char ch = *cp++;
- _crc = __crc32_u8(_crc, ch);
- }
+ _crc = __crc32_u8(_crc, ch);
+ }
- if ((__POINTER_SIZE__==8) || (_crc <= _MAX_INT)) {
- __INST(crc) = __MKSMALLINT(_crc);
- } else {
- // this code fails with gcc 4.7.2:
- // __INST(crc) = __MKUINT(_crc); __STORESELF(crc);
- OBJ temp = __MKUINT(_crc);
- __INST(crc) = temp; __STORESELF(crc);
- }
+ if ((__POINTER_SIZE__==8) || (_crc <= _MAX_INT)) {
+ __INST(crc) = __MKSMALLINT(_crc);
+ } else {
+ // this code fails with gcc 4.7.2:
+ // __INST(crc) = __MKUINT(_crc); __STORESELF(crc);
+ OBJ temp = __MKUINT(_crc);
+ __INST(crc) = temp; __STORESELF(crc);
+ }
- RETURN (count);
- }
+ RETURN (count);
+ }
}
bad: ;
#endif
@@ -559,4 +562,3 @@
version_CVS
^ '$Header$'
! !
-