AM_CONDITIONAL(SOLARIS, test x"$solaris" = x"yes")
AM_CONDITIONAL(AIX, test x"$aix" = x"yes")
+# Platform
+case "${host_cpu}" in
+i?86|x86_64)
+ intel="yes"
+ ;;
+esac
+AM_CONDITIONAL(INTEL, test x"$intel" = x"yes")
+
# Checks for programs.
AC_PROG_CXX
if test "$CXX" = no || test "$CXX:$GXX" = "g++:"; then
typedef shared_ptr<Compressor> CompressorRef;
class Compressor {
+protected:
string type;
- public:
+public:
Compressor(string t) : type(t) {}
virtual ~Compressor() {}
const string& get_type() const {
# zlib
-set(zlib_sources
- CompressionPluginZlib.cc
- ZlibCompressor.cc
-)
+if(INTEL_SSE4_1)
+ set(zlib_sources
+ CompressionPluginZlib.cc
+ ZlibCompressor.cc
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/hufftables_c.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/crc_utils_01.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/crc_utils_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_body_01.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_body_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_finish.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_stateless_01.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_stateless_04.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/crc_data.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/crc32_gzip.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/detect_repeated_char.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_multibinary.asm
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_stateless_base.c
+ ${CMAKE_SOURCE_DIR}/src/isa-l/igzip/igzip_base.c
+ )
+else(INTEL_SSE4_1)
+ set(zlib_sources
+ CompressionPluginZlib.cc
+ ZlibCompressor.cc
+ )
+endif(INTEL_SSE4_1)
add_library(ceph_zlib SHARED ${zlib_sources})
add_dependencies(ceph_zlib ${CMAKE_SOURCE_DIR}/src/ceph_ver.h)
target_link_libraries(ceph_zlib z)
+target_include_directories(ceph_zlib PRIVATE "${CMAKE_SOURCE_DIR}/src/isa-l/include")
set_target_properties(ceph_zlib PROPERTIES VERSION 2.0.0 SOVERSION 2)
install(TARGETS ceph_zlib DESTINATION ${compressor_plugin_dir})
// -----------------------------------------------------------------------------
#include "ceph_ver.h"
+#include "arch/probe.h"
+#include "arch/intel.h"
+#include "arch/arm.h"
#include "compressor/CompressionPlugin.h"
#include "ZlibCompressor.h"
#include "common/debug.h"
ostream *ss)
{
if (compressor == 0) {
- ZlibCompressor *interface = new ZlibCompressor();
+ ceph_arch_probe();
+ bool isal = (ceph_arch_intel_pclmul && ceph_arch_intel_sse41);
+ ZlibCompressor *interface = new ZlibCompressor(isal);
compressor = CompressorRef(interface);
}
*cs = compressor;
# zlib plugin
+
+MACHINE = $(shell uname -p)
+
+.asm.s:
+ @echo " MKTMP " $@;
+ @cp $< $@
+
noinst_HEADERS += \
- compressor/zlib/ZlibCompressor.h
+ compressor/zlib/ZlibCompressor.h \
+ isa-l/include/igzip_lib.h \
+ isa-l/include/types.h
zlib_sources = \
common/buffer.cc \
compressor/zlib/CompressionPluginZlib.cc \
compressor/zlib/ZlibCompressor.cc
+if INTEL
+zlib_sources += \
+ isa-l/igzip/igzip.c \
+ isa-l/igzip/hufftables_c.c \
+ isa-l/igzip/crc_utils_01.asm \
+ isa-l/igzip/crc_utils_04.asm \
+ isa-l/igzip/igzip_body_01.asm \
+ isa-l/igzip/igzip_body_04.asm \
+ isa-l/igzip/igzip_finish.asm \
+ isa-l/igzip/igzip_stateless_01.asm \
+ isa-l/igzip/igzip_stateless_04.asm \
+ isa-l/igzip/crc_data.asm \
+ isa-l/igzip/crc32_gzip.asm \
+ isa-l/igzip/detect_repeated_char.asm \
+ isa-l/igzip/igzip_multibinary.asm \
+ isa-l/igzip/igzip_stateless_base.c \
+ isa-l/igzip/igzip_base.c
+endif
+
compressor/zlib/CompressionPluginZlib.cc: ./ceph_ver.h
libceph_zlib_la_SOURCES = ${zlib_sources}
-libceph_zlib_la_CFLAGS = ${AM_CFLAGS}
-libceph_zlib_la_CXXFLAGS= ${AM_CXXFLAGS}
+libceph_zlib_la_CFLAGS = ${AM_CFLAGS} \
+ -I $(srcdir)/isa-l/include/
+
+if INTEL
+libceph_zlib_la_CCASFLAGS = ${AM_CCASFLAGS} \
+ -I $(srcdir)/isa-l/include/
+endif
+
+libceph_zlib_la_CXXFLAGS= ${AM_CXXFLAGS}
libceph_zlib_la_LIBADD = $(LIBCRUSH) $(PTHREAD_LIBS) $(EXTRALIBS)
libceph_zlib_la_LDFLAGS = ${AM_LDFLAGS} -lz -version-info 2:0:0
+libceph_zlib_la_LIBTOOLFLAGS = --tag=CC
if LINUX
libceph_zlib_la_LDFLAGS += -export-symbols-regex '.*__compressor_.*'
endif
#include "common/debug.h"
#include "ZlibCompressor.h"
#include "osd/osd_types.h"
+#include "isa-l/include/igzip_lib.h"
// -----------------------------------------------------------------------------
#include <zlib.h>
const long unsigned int max_len = 2048;
-int ZlibCompressor::compress(const bufferlist &in, bufferlist &out)
+int ZlibCompressor::zlib_compress(const bufferlist &in, bufferlist &out)
{
int ret;
unsigned have;
z_stream strm;
unsigned char* c_in;
int level = 5;
+ int begin = 1;
/* allocate deflate state */
strm.zalloc = Z_NULL;
do {
strm.avail_out = max_len;
bufferptr ptr = buffer::create_page_aligned(max_len);
- strm.next_out = (unsigned char*)ptr.c_str();
+ strm.next_out = (unsigned char*)ptr.c_str() + begin;
+ if (begin) {
+ ptr.c_str()[0] = 0;
+ begin = 0;
+ }
ret = deflate(&strm, flush); /* no bad return value */
if (ret == Z_STREAM_ERROR) {
dout(1) << "Compression error: compress return Z_STREAM_ERROR("
return 0;
}
+int ZlibCompressor::isal_compress(const bufferlist &in, bufferlist &out)
+{
+#if (__arm__)
+ derr << "Unsupported architecture" << dendl;
+ return -1;
+#else
+ int ret;
+ unsigned have;
+ isal_zstream strm;
+ unsigned char* c_in;
+ int begin = 1;
+
+ /* allocate deflate state */
+ isal_deflate_init(&strm);
+ strm.end_of_stream = 0;
+
+ for (std::list<buffer::ptr>::const_iterator i = in.buffers().begin();
+ i != in.buffers().end();) {
+
+ c_in = (unsigned char*) (*i).c_str();
+ long unsigned int len = (*i).length();
+ ++i;
+
+ strm.avail_in = len;
+ strm.end_of_stream = (i == in.buffers().end());
+ strm.flush = FINISH_FLUSH;
+
+ strm.next_in = c_in;
+
+ do {
+ strm.avail_out = max_len;
+ bufferptr ptr = buffer::create_page_aligned(max_len);
+ strm.next_out = (unsigned char*)ptr.c_str() + begin;
+ if (begin) {
+ ptr.c_str()[0] = 1;
+ begin = 0;
+ }
+ ret = isal_deflate(&strm);
+ if (ret != COMP_OK) {
+ dout(1) << "Compression error: isal_deflate return error ("
+ << ret << ")" << dendl;
+ return -1;
+ }
+ have = max_len - strm.avail_out;
+ out.append(ptr, 0, have);
+ } while (strm.avail_out == 0);
+ if (strm.avail_in != 0) {
+ dout(10) << "Compression error: unused input" << dendl;
+ return -1;
+ }
+ }
+
+ return 0;
+#endif
+}
+
+int ZlibCompressor::compress(const bufferlist &in, bufferlist &out)
+{
+ if (isal_enabled)
+ return isal_compress(in, out);
+ else
+ return zlib_compress(in, out);
+}
+
int ZlibCompressor::decompress(bufferlist::iterator &p, size_t compressed_size, bufferlist &out)
{
int ret;
unsigned have;
z_stream strm;
const char* c_in;
+ int begin = 1;
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
- ret = inflateInit(&strm);
+ if (*p == 1)
+ ret = inflateInit2(&strm, -HIST_SIZE);
+ else
+ ret = inflateInit(&strm);
if (ret != Z_OK) {
dout(1) << "Decompression init error: init return "
<< ret << " instead of Z_OK" << dendl;
long unsigned int len = p.get_ptr_and_advance(remaining, &c_in);
remaining -= len;
strm.avail_in = len;
- strm.next_in = (unsigned char*)c_in;
+ strm.next_in = (unsigned char*)c_in + begin;
+ begin = 0;
do {
strm.avail_out = max_len;
#include "compressor/Compressor.h"
class ZlibCompressor : public Compressor {
+ bool isal_enabled;
public:
- ZlibCompressor() : Compressor("zlib") {}
+ ZlibCompressor(bool isal) : Compressor("zlib"), isal_enabled(isal)
+ {
+ if (isal)
+ Compressor::type = "isa-l";
+ }
int compress(const bufferlist &in, bufferlist &out) override;
int decompress(const bufferlist &in, bufferlist &out) override;
int decompress(bufferlist::iterator &p, size_t compressed_len, bufferlist &out) override;
+private:
+ int zlib_compress(const bufferlist &in, bufferlist &out);
+ int isal_compress(const bufferlist &in, bufferlist &out);
};
unittest_compression_zlib_SOURCES = \
test/compressor/test_compression_zlib.cc \
${zlib_sources}
-unittest_compression_zlib_CXXFLAGS = $(UNITTEST_CXXFLAGS)
+unittest_compression_zlib_CFLAGS = ${AM_CFLAGS} \
+ -I$(srcdir)/isa-l/include/
+unittest_compression_zlib_CXXFLAGS = $(UNITTEST_CXXFLAGS) \
+ -I$(srcdir)/isa-l/include/
+unittest_compression_zlib_CCASFLAGS = ${AM_CCASFLAGS} \
+ -I$(srcdir)/isa-l/include/
unittest_compression_zlib_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL)
unittest_compression_zlib_LDFLAGS = -lz
if LINUX
check_TESTPROGRAMS += unittest_compression_zlib
unittest_compression_plugin_zlib_SOURCES = \
- test/compressor/test_compression_plugin_zlib.cc \
- ${zlib_sources}
+ test/compressor/test_compression_plugin_zlib.cc
unittest_compression_plugin_zlib_CXXFLAGS = ${AM_CXXFLAGS} ${UNITTEST_CXXFLAGS}
unittest_compression_plugin_zlib_LDADD = $(LIBOSD) $(LIBCOMMON) $(UNITTEST_LDADD) $(CEPH_GLOBAL) $(LIBCOMPRESSOR)
unittest_compression_plugin_zlib_LDFLAGS = -lz
TEST(ZlibCompressor, compress_decompress)
{
- ZlibCompressor sp;
+ ZlibCompressor sp(false);
EXPECT_STREQ(sp.get_type().c_str(), "zlib");
const char* test = "This is test text";
int len = strlen(test);
TEST(ZlibCompressor, compress_decompress_chunk)
{
- ZlibCompressor sp;
+ ZlibCompressor sp(false);
EXPECT_STREQ(sp.get_type().c_str(), "zlib");
const char* test = "This is test text";
buffer::ptr test2 ("1234567890", 10);
EXPECT_TRUE(exp.contents_equal(after));
}
+TEST(ZlibCompressor, compress_decompress_isal)
+{
+ ZlibCompressor sp(true);
+ EXPECT_STREQ(sp.get_type().c_str(), "isa-l");
+ const char* test = "This is test text";
+ int len = strlen(test);
+ bufferlist in, out;
+ in.append(test, len);
+ int res = sp.compress(in, out);
+ EXPECT_EQ(res, 0);
+ bufferlist after;
+ res = sp.decompress(out, after);
+ EXPECT_EQ(res, 0);
+ bufferlist exp;
+ exp.append(test);
+ EXPECT_TRUE(exp.contents_equal(after));
+ after.clear();
+ size_t compressed_len = out.length();
+ out.append_zero(12);
+ auto it = out.begin();
+ res = sp.decompress(it, compressed_len, after);
+ EXPECT_EQ(res, 0);
+ EXPECT_TRUE(exp.contents_equal(after));
+}
+
+TEST(ZlibCompressor, compress_decompress_chunk_isal)
+{
+ ZlibCompressor sp(true);
+ EXPECT_STREQ(sp.get_type().c_str(), "isa-l");
+ const char* test = "This is test text";
+ buffer::ptr test2 ("1234567890", 10);
+ int len = strlen(test);
+ bufferlist in, out;
+ in.append(test, len);
+ in.append(test2);
+ int res = sp.compress(in, out);
+ EXPECT_EQ(res, 0);
+ bufferlist after;
+ res = sp.decompress(out, after);
+ EXPECT_EQ(res, 0);
+ bufferlist exp;
+ exp.append("This is test text1234567890");
+ EXPECT_TRUE(exp.contents_equal(after));
+}
+
+TEST(ZlibCompressor, zlib_isal_compatibility)
+{
+ ZlibCompressor isal(true);
+ EXPECT_STREQ(isal.get_type().c_str(), "isa-l");
+ ZlibCompressor zlib(false);
+ EXPECT_STREQ(zlib.get_type().c_str(), "zlib");
+ char test[101];
+ srand(time(0));
+ for (int i=0; i<100; ++i)
+ test[i] = 'a' + rand()%26;
+ test[100] = '\0';
+ int len = strlen(test);
+ bufferlist in, out;
+ in.append(test, len);
+ // isal -> zlib
+ int res = isal.compress(in, out);
+ EXPECT_EQ(res, 0);
+ bufferlist after;
+ res = zlib.decompress(out, after);
+ EXPECT_EQ(res, 0);
+ bufferlist exp;
+ exp.append(test);
+ EXPECT_TRUE(exp.contents_equal(after));
+ after.clear();
+ out.clear();
+ exp.clear();
+ // zlib -> isal
+ res = zlib.compress(in, out);
+ EXPECT_EQ(res, 0);
+ res = isal.decompress(out, after);
+ EXPECT_EQ(res, 0);
+ exp.append(test);
+ EXPECT_TRUE(exp.contents_equal(after));
+}
+
+
int main(int argc, char **argv) {
vector<const char*> args;
argv_to_vec(argc, (const char **)argv, args);