]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
compressor: isa-l extension for zlib plugin
authorVed-vampir <akiselyova@mirantis.com>
Wed, 22 Jun 2016 14:04:32 +0000 (17:04 +0300)
committerVed-vampir <akiselyova@mirantis.com>
Mon, 8 Aug 2016 19:33:33 +0000 (22:33 +0300)
Signed-off-by: Alyona Kiseleva <akiselyova@mirantis.com>
configure.ac
src/compressor/Compressor.h
src/compressor/zlib/CMakeLists.txt
src/compressor/zlib/CompressionPluginZlib.cc
src/compressor/zlib/Makefile.am
src/compressor/zlib/ZlibCompressor.cc
src/compressor/zlib/ZlibCompressor.h
src/test/compressor/Makefile.am
src/test/compressor/test_compression_zlib.cc

index fb806d3de2829b72b0ff6e6086f4156363c12472..7f29ba9ad048518a3dc5e2d47c15bc3098ee29cd 100644 (file)
@@ -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
index e1aa3c2d1e6e47520f6e549b4613f83a01ddc806..a9f91038938bb14ae5e5c14fa2b8a603f8f75f58 100644 (file)
@@ -22,8 +22,9 @@ class Compressor;
 typedef shared_ptr<Compressor> CompressorRef;
 
 class Compressor {
+protected:
   string type;
- public:
+public:
   Compressor(string t) : type(t) {}
   virtual ~Compressor() {}
   const string& get_type() const {
index f80131e7b6082ba5438ae819f33e8ae62d3a2186..eeb6a8e6ea3efbef5e80f70adf832ea70a35e171 100644 (file)
@@ -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})
index 7140fccba2f7bc2bcf8212342e8ae0ae5a989f59..e330d095a1e9be9a3f2bccf79c67cf6eeebacb4d 100644 (file)
@@ -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;
index a0056123b89b3b901b71751d17d3c67da6844a53..d05f9c532138f242112d592ddd9c3b238fbcc79c 100644 (file)
@@ -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
index 747ffae132e5ec6f4cad0a40b39cf3c1fe05290b..342677d4df0d7f617fad2230ce1d73b2fb182153 100644 (file)
@@ -16,6 +16,7 @@
 #include "common/debug.h"
 #include "ZlibCompressor.h"
 #include "osd/osd_types.h"
+#include "isa-l/include/igzip_lib.h"
 // -----------------------------------------------------------------------------
 
 #include <zlib.h>
@@ -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<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;
@@ -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;
index 7cac1a68b1a54d43ca953eaf93858f971fc82df6..d464c88897e182a93fb3a394cc5056c973d569db 100644 (file)
 #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);
  };
 
 
index c31032f03ca51674b34f285ea17ef7be19ba2708..e08ecd34448668ce258e7b33e60490f7ae719c47 100644 (file)
@@ -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
index 4932fbd6ff852deca1a8dd5a4f4560ec21330e73..7c3771b6e5e7cf3b0ac53bc44deedae9762d7e6d 100644 (file)
@@ -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<const char*> args;
   argv_to_vec(argc, (const char **)argv, args);