- All packages come from the official repository at download.ceph.com.
- The probed Ceph version is
v12.2.4
. It usesceph/rocksdb
commit ID 62782e7357ff569d836b0ad91e5776fc1d6137e5.
RocksDB uses rocksdb::crc32c::IsFastCrc32Supported()
to generate the log message whether the fast CRC32 path is available or not. The function resorts to isSSE42()
when the macro __SSE4_2__
is defined. Otherwise it returns false
.
bool IsFastCrc32Supported() {
#ifdef __SSE4_2__
return isSSE42();
#elif defined(_WIN64)
return isSSE42();
#else
return false;
#endif
}
The usage of rocksdb::crc32c::IsFastCrc32Supported()
:
void DumpSupportInfo(Logger* logger) {
ROCKS_LOG_HEADER(logger, "Compression algorithms supported:");
ROCKS_LOG_HEADER(logger, "\tSnappy supported: %d", Snappy_Supported());
ROCKS_LOG_HEADER(logger, "\tZlib supported: %d", Zlib_Supported());
ROCKS_LOG_HEADER(logger, "\tBzip supported: %d", BZip2_Supported());
ROCKS_LOG_HEADER(logger, "\tLZ4 supported: %d", LZ4_Supported());
ROCKS_LOG_HEADER(logger, "\tZSTD supported: %d", ZSTD_Supported());
ROCKS_LOG_HEADER(logger, "Fast CRC32 supported: %d",
crc32c::IsFastCrc32Supported());
}
However, the check is too costly (because of relying on the cpuid
instruction) to be executed each time a CRC calculation is invoked. Thus, the result is cached with the assistance of Choose_Extend()
function used to initialize a static variable.
static inline Function Choose_Extend() {
return isSSE42() ? ExtendImpl<Fast_CRC32> : ExtendImpl<Slow_CRC32>;
}
In contrast to IsFastCrc32Supported()
, isSSE42()
is called unconditionally and likely returns true
. However, Fast_CRC32()
on its own does fallback to Slow_CRC32()
when __SSE4_2__
is undefined.
static inline void Fast_CRC32(uint64_t* l, uint8_t const **p) {
#ifdef __SSE4_2__
# ifdef __LP64__
*l = _mm_crc32_u64(*l, LE_LOAD64(*p));
*p += 8;
# else
*l = _mm_crc32_u32(static_cast<unsigned int>(*l), LE_LOAD32(*p));
*p += 4;
*l = _mm_crc32_u32(static_cast<unsigned int>(*l), LE_LOAD32(*p));
*p += 4;
# endif
#elif defined(_WIN64)
// ...
#else
Slow_CRC32(l, p);
#endif
}
Conclusion: to judge whether RocksDB uses the fast CRC32 path it is enough to verify the value returned by IsFastCrc32Supported()
. [UPDATED]: The logic of the check is tricky. A situation where isSSE42()
returns true
(and an user pays the init-time cost of cpuid
) but Fast_CRC32
turns ultimately into Slow_CRC32
is possible.
$ objdump -D -C ./usr/bin/ceph-osd
...
0000000000db2850 <rocksdb::crc32c::IsFastCrc32Supported()@@Base>:
db2850: 31 c0 xor %eax,%eax
db2852: c3 retq
db2853: 66 66 66 66 2e 0f 1f data16 data16 data16 nopw %cs:0x0(%rax,%rax,1)
db285a: 84 00 00 00 00 00
Result: there is no support for the fast CRC32 path.
$ objdump -D -C ./usr/bin/ceph-osd
...
0000000000e829f0 <rocksdb::crc32c::IsFastCrc32Supported()@@Base>:
e829f0: 31 c0 xor %eax,%eax
e829f2: c3 retq
e829f3: 0f 1f 00 nopl (%rax)
e829f6: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
e829fd: 00 00 00
Result: there is no support for the fast CRC32 path.
$ objdump -D -C ./usr/bin/ceph-osd
...
0000000000e43670 <rocksdb::crc32c::IsFastCrc32Supported()@@Base>:
e43670: 31 c0 xor %eax,%eax
e43672: c3 retq
e43673: 0f 1f 00 nopl (%rax)
e43676: 66 2e 0f 1f 84 00 00 nopw %cs:0x0(%rax,%rax,1)
e4367d: 00 00 00
Result: there is no support for the fast CRC32 path.
The indentation of macro directives in
Fast_CRC32
has been added by me to make the code more readable.