From: Ved-vampir Date: Wed, 22 Jun 2016 14:04:32 +0000 (+0300) Subject: compressor: isa-l extension for zlib plugin X-Git-Tag: v11.0.1~351^2~1 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=b759021f32be55213b30c1524ffeb436c3cbf87c;p=ceph.git compressor: isa-l extension for zlib plugin Signed-off-by: Alyona Kiseleva --- diff --git a/configure.ac b/configure.ac index fb806d3de282..7f29ba9ad048 100644 --- a/configure.ac +++ b/configure.ac @@ -81,6 +81,14 @@ AM_CONDITIONAL(DARWIN, test x"$darwin" = x"yes") 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 diff --git a/src/compressor/Compressor.h b/src/compressor/Compressor.h index e1aa3c2d1e6e..a9f91038938b 100644 --- a/src/compressor/Compressor.h +++ b/src/compressor/Compressor.h @@ -22,8 +22,9 @@ class Compressor; typedef shared_ptr CompressorRef; class Compressor { +protected: string type; - public: +public: Compressor(string t) : type(t) {} virtual ~Compressor() {} const string& get_type() const { diff --git a/src/compressor/zlib/CMakeLists.txt b/src/compressor/zlib/CMakeLists.txt index f80131e7b608..eeb6a8e6ea3e 100644 --- a/src/compressor/zlib/CMakeLists.txt +++ b/src/compressor/zlib/CMakeLists.txt @@ -1,12 +1,35 @@ # 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}) diff --git a/src/compressor/zlib/CompressionPluginZlib.cc b/src/compressor/zlib/CompressionPluginZlib.cc index 7140fccba2f7..e330d095a1e9 100644 --- a/src/compressor/zlib/CompressionPluginZlib.cc +++ b/src/compressor/zlib/CompressionPluginZlib.cc @@ -15,6 +15,9 @@ // ----------------------------------------------------------------------------- #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" @@ -32,7 +35,9 @@ public: 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; diff --git a/src/compressor/zlib/Makefile.am b/src/compressor/zlib/Makefile.am index a0056123b89b..d05f9c532138 100644 --- a/src/compressor/zlib/Makefile.am +++ b/src/compressor/zlib/Makefile.am @@ -1,6 +1,15 @@ # 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 \ @@ -8,13 +17,40 @@ zlib_sources = \ 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 diff --git a/src/compressor/zlib/ZlibCompressor.cc b/src/compressor/zlib/ZlibCompressor.cc index 747ffae132e5..342677d4df0d 100644 --- a/src/compressor/zlib/ZlibCompressor.cc +++ b/src/compressor/zlib/ZlibCompressor.cc @@ -16,6 +16,7 @@ #include "common/debug.h" #include "ZlibCompressor.h" #include "osd/osd_types.h" +#include "isa-l/include/igzip_lib.h" // ----------------------------------------------------------------------------- #include @@ -37,13 +38,14 @@ _prefix(std::ostream* _dout) 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; @@ -71,7 +73,11 @@ int ZlibCompressor::compress(const bufferlist &in, bufferlist &out) 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(" @@ -93,12 +99,77 @@ int ZlibCompressor::compress(const bufferlist &in, bufferlist &out) 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::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; @@ -106,7 +177,10 @@ int ZlibCompressor::decompress(bufferlist::iterator &p, size_t compressed_size, 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; @@ -119,7 +193,8 @@ int ZlibCompressor::decompress(bufferlist::iterator &p, size_t compressed_size, 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; diff --git a/src/compressor/zlib/ZlibCompressor.h b/src/compressor/zlib/ZlibCompressor.h index 7cac1a68b1a5..d464c88897e1 100644 --- a/src/compressor/zlib/ZlibCompressor.h +++ b/src/compressor/zlib/ZlibCompressor.h @@ -20,12 +20,20 @@ #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); }; diff --git a/src/test/compressor/Makefile.am b/src/test/compressor/Makefile.am index c31032f03ca5..e08ecd344486 100644 --- a/src/test/compressor/Makefile.am +++ b/src/test/compressor/Makefile.am @@ -49,7 +49,12 @@ check_TESTPROGRAMS += unittest_compression_plugin_snappy 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 @@ -58,8 +63,7 @@ endif 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 diff --git a/src/test/compressor/test_compression_zlib.cc b/src/test/compressor/test_compression_zlib.cc index 4932fbd6ff85..7c3771b6e5e7 100644 --- a/src/test/compressor/test_compression_zlib.cc +++ b/src/test/compressor/test_compression_zlib.cc @@ -26,7 +26,7 @@ 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); @@ -51,7 +51,7 @@ TEST(ZlibCompressor, compress_decompress) 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); @@ -69,6 +69,87 @@ TEST(ZlibCompressor, compress_decompress_chunk) 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 args; argv_to_vec(argc, (const char **)argv, args);