Merge pull request #1848 from AmineChikhaoui/parallel-xz
support multi threaded xz encoder
This commit is contained in:
commit
3d2d207aad
|
@ -149,7 +149,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
|
||||||
/* Compress the NAR. */
|
/* Compress the NAR. */
|
||||||
narInfo->compression = compression;
|
narInfo->compression = compression;
|
||||||
auto now1 = std::chrono::steady_clock::now();
|
auto now1 = std::chrono::steady_clock::now();
|
||||||
auto narCompressed = compress(compression, *nar);
|
auto narCompressed = compress(compression, *nar, parallelCompression);
|
||||||
auto now2 = std::chrono::steady_clock::now();
|
auto now2 = std::chrono::steady_clock::now();
|
||||||
narInfo->fileHash = hashString(htSHA256, *narCompressed);
|
narInfo->fileHash = hashString(htSHA256, *narCompressed);
|
||||||
narInfo->fileSize = narCompressed->size();
|
narInfo->fileSize = narCompressed->size();
|
||||||
|
|
|
@ -19,6 +19,8 @@ public:
|
||||||
const Setting<bool> writeNARListing{this, false, "write-nar-listing", "whether to write a JSON file listing the files in each NAR"};
|
const Setting<bool> writeNARListing{this, false, "write-nar-listing", "whether to write a JSON file listing the files in each NAR"};
|
||||||
const Setting<Path> secretKeyFile{this, "", "secret-key", "path to secret key used to sign the binary cache"};
|
const Setting<Path> secretKeyFile{this, "", "secret-key", "path to secret key used to sign the binary cache"};
|
||||||
const Setting<Path> localNarCache{this, "", "local-nar-cache", "path to a local cache of NARs"};
|
const Setting<Path> localNarCache{this, "", "local-nar-cache", "path to a local cache of NARs"};
|
||||||
|
const Setting<bool> parallelCompression{this, false, "parallel-compression",
|
||||||
|
"enable multi-threading compression, available for xz only currently"};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
|
@ -151,10 +151,10 @@ static ref<std::string> decompressBrotli(const std::string & in)
|
||||||
#endif // HAVE_BROTLI
|
#endif // HAVE_BROTLI
|
||||||
}
|
}
|
||||||
|
|
||||||
ref<std::string> compress(const std::string & method, const std::string & in)
|
ref<std::string> compress(const std::string & method, const std::string & in, const bool parallel)
|
||||||
{
|
{
|
||||||
StringSink ssink;
|
StringSink ssink;
|
||||||
auto sink = makeCompressionSink(method, ssink);
|
auto sink = makeCompressionSink(method, ssink, parallel);
|
||||||
(*sink)(in);
|
(*sink)(in);
|
||||||
sink->finish();
|
sink->finish();
|
||||||
return ssink.s;
|
return ssink.s;
|
||||||
|
@ -189,10 +189,28 @@ struct XzSink : CompressionSink
|
||||||
lzma_stream strm = LZMA_STREAM_INIT;
|
lzma_stream strm = LZMA_STREAM_INIT;
|
||||||
bool finished = false;
|
bool finished = false;
|
||||||
|
|
||||||
XzSink(Sink & nextSink) : nextSink(nextSink)
|
XzSink(Sink & nextSink, const bool parallel) : nextSink(nextSink)
|
||||||
{
|
{
|
||||||
lzma_ret ret = lzma_easy_encoder(
|
lzma_ret ret;
|
||||||
|
if (parallel) {
|
||||||
|
lzma_mt mt_options = {};
|
||||||
|
mt_options.flags = 0;
|
||||||
|
mt_options.timeout = 300; // Using the same setting as the xz cmd line
|
||||||
|
mt_options.preset = LZMA_PRESET_DEFAULT;
|
||||||
|
mt_options.filters = NULL;
|
||||||
|
mt_options.check = LZMA_CHECK_CRC64;
|
||||||
|
mt_options.threads = lzma_cputhreads();
|
||||||
|
mt_options.block_size = 0;
|
||||||
|
if (mt_options.threads == 0)
|
||||||
|
mt_options.threads = 1;
|
||||||
|
// FIXME: maybe use lzma_stream_encoder_mt_memusage() to control the
|
||||||
|
// number of threads.
|
||||||
|
ret = lzma_stream_encoder_mt(
|
||||||
|
&strm, &mt_options);
|
||||||
|
} else
|
||||||
|
ret = lzma_easy_encoder(
|
||||||
&strm, 6, LZMA_CHECK_CRC64);
|
&strm, 6, LZMA_CHECK_CRC64);
|
||||||
|
|
||||||
if (ret != LZMA_OK)
|
if (ret != LZMA_OK)
|
||||||
throw CompressionError("unable to initialise lzma encoder");
|
throw CompressionError("unable to initialise lzma encoder");
|
||||||
// FIXME: apply the x86 BCJ filter?
|
// FIXME: apply the x86 BCJ filter?
|
||||||
|
@ -449,12 +467,12 @@ struct BrotliSink : CompressionSink
|
||||||
};
|
};
|
||||||
#endif // HAVE_BROTLI
|
#endif // HAVE_BROTLI
|
||||||
|
|
||||||
ref<CompressionSink> makeCompressionSink(const std::string & method, Sink & nextSink)
|
ref<CompressionSink> makeCompressionSink(const std::string & method, Sink & nextSink, const bool parallel)
|
||||||
{
|
{
|
||||||
if (method == "none")
|
if (method == "none")
|
||||||
return make_ref<NoneSink>(nextSink);
|
return make_ref<NoneSink>(nextSink);
|
||||||
else if (method == "xz")
|
else if (method == "xz")
|
||||||
return make_ref<XzSink>(nextSink);
|
return make_ref<XzSink>(nextSink, parallel);
|
||||||
else if (method == "bzip2")
|
else if (method == "bzip2")
|
||||||
return make_ref<BzipSink>(nextSink);
|
return make_ref<BzipSink>(nextSink);
|
||||||
else if (method == "br")
|
else if (method == "br")
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
ref<std::string> compress(const std::string & method, const std::string & in);
|
ref<std::string> compress(const std::string & method, const std::string & in, const bool parallel = false);
|
||||||
|
|
||||||
ref<std::string> decompress(const std::string & method, const std::string & in);
|
ref<std::string> decompress(const std::string & method, const std::string & in);
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ struct CompressionSink : BufferedSink
|
||||||
virtual void finish() = 0;
|
virtual void finish() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
ref<CompressionSink> makeCompressionSink(const std::string & method, Sink & nextSink);
|
ref<CompressionSink> makeCompressionSink(const std::string & method, Sink & nextSink, const bool parallel = false);
|
||||||
|
|
||||||
MakeError(UnknownCompressionMethod, Error);
|
MakeError(UnknownCompressionMethod, Error);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue