util: Use ZSTD for shader cache if possible
authorDylan Baker <dylan@pnwbakers.com>
Thu, 31 Oct 2019 20:26:00 +0000 (13:26 -0700)
committerDylan Baker <dylan@pnwbakers.com>
Mon, 11 Nov 2019 18:53:45 +0000 (18:53 +0000)
This allows ZSTD instead of ZLIB to be used for compressing the shader
cache.

On a 72 core system emulating skl with a full shader-db (with i965):
ZSTD:
    1915.10s user 229.27s system 5150% cpu 41.632 total (cold cache)
    225.40s user 10.87s system 3810% cpu 6.201 total (warm cache)
    154M (235M on disk)
ZLIB:
    2231.33s user 194.24s system 1899% cpu 2:07.72 total (cold cache)
    229.15s user 10.63s system 3906% cpu 6.139 total (warm cache)
    163M (244M on disk)

Tim Arceri sees (8 core ryzen and a full shader-db):
ZSTD:
    2505.22 user 40.50 system 3:18.73 elapsed 1280% CPU (cold cache)
    418.71 user 14.93 system 0:46.53 elapsed 931% CPU (warm cache)
    454.3 MB (681.7 MB on disk)
ZLIB:
    3069.83 user 40.02 system 4:20.13 elapsed 1195% CPU (cold cache)
    425.50 user 15.17 system 0:46.80 elapsed 941% CPU (warm cache)
    470.3 MB (701.4 MB on disk)

Reviewed-by: Eric Engestrom <eric.engestrom@intel.com> (v1)
Reviewed-by: Eric Anholt <eric@anholt.net>
meson.build
meson_options.txt
src/util/disk_cache.c
src/util/meson.build

index b9a6da01d314503f7e54bfe18c9e76be46adb66d..39907709f71d608744391dafe9aac013e0f0273c 100644 (file)
@@ -1251,6 +1251,17 @@ endif
 # TODO: some of these may be conditional
 dep_zlib = dependency('zlib', version : '>= 1.2.3', fallback : ['zlib', 'zlib_dep'])
 pre_args += '-DHAVE_ZLIB'
+
+_zstd = get_option('zstd')
+if _zstd != 'false'
+  dep_zstd = dependency('libzstd', required : _zstd == 'true')
+  if dep_zstd.found()
+    pre_args += '-DHAVE_ZSTD'
+  endif
+else
+  dep_zstd = null_dep
+endif
+
 dep_thread = dependency('threads')
 if dep_thread.found() and host_machine.system() != 'windows'
   pre_args += '-DHAVE_PTHREAD'
index 626baf3d5c2cf78c3db1f501322f52b904ce6881..8c3e9978529310baafa852d0e1260c30f6df079a 100644 (file)
@@ -1,4 +1,4 @@
-# Copyright © 2017-2018 Intel Corporation
+# Copyright © 2017-2019 Intel Corporation
 
 # Permission is hereby granted, free of charge, to any person obtaining a copy
 # of this software and associated documentation files (the "Software"), to deal
@@ -366,3 +366,10 @@ option(
   value : 25,
   description : 'Android Platform SDK version. Default: Nougat version.'
 )
+option(
+  'zstd',
+  type : 'combo',
+  choices : ['auto', 'true', 'false'],
+  value : 'auto',
+  description : 'Use ZSTD instead of ZLIB in some cases.'
+)
index 0cd92ca2d5bef081f82a952065174702e44b8f14..e5b21b9a79f5620c4f040561908a2a299a7c1df6 100644 (file)
 #include <inttypes.h>
 #include "zlib.h"
 
+#ifdef HAVE_ZSTD
+#include "zstd.h"
+#endif
+
 #include "util/crc32.h"
 #include "util/debug.h"
 #include "util/rand_xor.h"
@@ -75,6 +79,9 @@
  */
 #define CACHE_VERSION 1
 
+/* 3 is the recomended level, with 22 as the absolute maximum */
+#define ZSTD_COMPRESSION_LEVEL 3
+
 struct disk_cache {
    /* The path to the cache directory. */
    char *path;
@@ -738,6 +745,23 @@ static size_t
 deflate_and_write_to_disk(const void *in_data, size_t in_data_size, int dest,
                           const char *filename)
 {
+#ifdef HAVE_ZSTD
+   /* from the zstd docs (https://facebook.github.io/zstd/zstd_manual.html):
+    * compression runs faster if `dstCapacity` >= `ZSTD_compressBound(srcSize)`.
+    */
+   size_t out_size = ZSTD_compressBound(in_data_size);
+   void * out = malloc(out_size);
+
+   size_t ret = ZSTD_compress(out, out_size, in_data, in_data_size,
+                              ZSTD_COMPRESSION_LEVEL);
+   if (ZSTD_isError(ret)) {
+      free(out);
+      return 0;
+   }
+   write_all(dest, out, ret);
+   free(out);
+   return ret;
+#else
    unsigned char *out;
 
    /* allocate deflate state */
@@ -798,6 +822,7 @@ deflate_and_write_to_disk(const void *in_data, size_t in_data_size, int dest,
    (void)deflateEnd(&strm);
    free(out);
    return compressed_size;
+# endif
 }
 
 static struct disk_cache_put_job *
@@ -1059,6 +1084,10 @@ static bool
 inflate_cache_data(uint8_t *in_data, size_t in_data_size,
                    uint8_t *out_data, size_t out_data_size)
 {
+#ifdef HAVE_ZSTD
+   size_t ret = ZSTD_decompress(out_data, out_data_size, in_data, in_data_size);
+   return !ZSTD_isError(ret);
+#else
    z_stream strm;
 
    /* allocate inflate state */
@@ -1089,6 +1118,7 @@ inflate_cache_data(uint8_t *in_data, size_t in_data_size,
    /* clean up and return */
    (void)inflateEnd(&strm);
    return true;
+#endif
 }
 
 void *
index 972d757195a5059567be354cbab7d30946682960..a7990ad52cc35bfa014246adad4a6ce9d7c0174a 100644 (file)
@@ -149,6 +149,7 @@ deps_for_libmesa_util = [
   dep_atomic,
   dep_m,
   dep_valgrind,
+  dep_zstd,
 ]
 
 if with_platform_android