xz: Set the Block size for mt encoding correctly.
When opt_block_size is not used, the Block size for mt encoder is derived from the minimum of the largest Block specified by --block-list and the recommended Block size on all filter chains calculated by lzma_mt_block_size(). This avoids using unnecessary memory and ensures that all Blocks are large enough for the most memory needy filter chain.
This commit is contained in:
parent
afb2dbec3d
commit
183819bfd9
|
@ -50,6 +50,13 @@ static uint32_t filters_init_mask = 1;
|
||||||
/// Track the memory usage for all filter chains (default or --filtersX).
|
/// Track the memory usage for all filter chains (default or --filtersX).
|
||||||
/// The memory usage may need to be scaled down depending on the memory limit.
|
/// The memory usage may need to be scaled down depending on the memory limit.
|
||||||
static uint64_t filter_memusages[ARRAY_SIZE(filters)];
|
static uint64_t filter_memusages[ARRAY_SIZE(filters)];
|
||||||
|
|
||||||
|
# ifdef MYTHREAD_ENABLED
|
||||||
|
/// Represents the largest Block size specified with --block-list. This
|
||||||
|
/// is needed to help reduce the Block size in the multithreaded encoder
|
||||||
|
/// so memory is not wasted.
|
||||||
|
static uint64_t max_block_list_size = 0;
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Input and output buffers
|
/// Input and output buffers
|
||||||
|
@ -290,6 +297,18 @@ filters_memusage_max(const lzma_mt *mt, bool encode)
|
||||||
|
|
||||||
return max_memusage;
|
return max_memusage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ifdef MYTHREAD_ENABLED
|
||||||
|
static void
|
||||||
|
filter_chain_error(const uint32_t index, const char *msg)
|
||||||
|
{
|
||||||
|
if (index == 0)
|
||||||
|
message_fatal(_("Error in the filter chain: %s"), msg);
|
||||||
|
else
|
||||||
|
message_fatal(_("Error in --filters%d: %s"), index, msg);
|
||||||
|
}
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -306,6 +325,11 @@ coder_set_compression_settings(void)
|
||||||
for (uint32_t i = 0; opt_block_list[i].size != 0; i++) {
|
for (uint32_t i = 0; opt_block_list[i].size != 0; i++) {
|
||||||
validate_block_list_filter(
|
validate_block_list_filter(
|
||||||
opt_block_list[i].filters_index);
|
opt_block_list[i].filters_index);
|
||||||
|
|
||||||
|
# ifdef MYTHREAD_ENABLED
|
||||||
|
if (opt_block_list[i].size > max_block_list_size)
|
||||||
|
max_block_list_size = opt_block_list[i].size;
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// The default check type is CRC64, but fallback to CRC32
|
// The default check type is CRC64, but fallback to CRC32
|
||||||
|
@ -420,7 +444,49 @@ coder_set_compression_settings(void)
|
||||||
if (opt_format == FORMAT_XZ && hardware_threads_is_mt()) {
|
if (opt_format == FORMAT_XZ && hardware_threads_is_mt()) {
|
||||||
memory_limit = hardware_memlimit_mtenc_get();
|
memory_limit = hardware_memlimit_mtenc_get();
|
||||||
mt_options.threads = hardware_threads_get();
|
mt_options.threads = hardware_threads_get();
|
||||||
mt_options.block_size = opt_block_size;
|
|
||||||
|
uint64_t block_size = opt_block_size;
|
||||||
|
// If opt_block_size is not set, find the maximum
|
||||||
|
// recommended Block size based on the filter chains
|
||||||
|
if (block_size == 0) {
|
||||||
|
for (uint32_t i = 0; i < ARRAY_SIZE(filters);
|
||||||
|
i++) {
|
||||||
|
if (!(filters_init_mask & (1 << i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint64_t size = lzma_mt_block_size(
|
||||||
|
filters[i]);
|
||||||
|
|
||||||
|
// If this returns an error, then one
|
||||||
|
// of the filter chains in use is
|
||||||
|
// invalid, so there is no point in
|
||||||
|
// progressing further.
|
||||||
|
if (size == UINT64_MAX)
|
||||||
|
filter_chain_error(i,
|
||||||
|
message_strm(
|
||||||
|
LZMA_OPTIONS_ERROR));
|
||||||
|
|
||||||
|
if (size > block_size)
|
||||||
|
block_size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the largest block size specified
|
||||||
|
// with --block-list is less than the
|
||||||
|
// recommended Block size, then it is a waste
|
||||||
|
// of RAM to use a larger Block size. It may
|
||||||
|
// even allow more threads to be used in some
|
||||||
|
// situations. If the special 0 Block size is
|
||||||
|
// used (encode all remaining data in 1 Block)
|
||||||
|
// then max_block_list_size will be set to
|
||||||
|
// UINT64_MAX, so the recommended Block size
|
||||||
|
// will always be used in this case.
|
||||||
|
if (max_block_list_size > 0
|
||||||
|
&& max_block_list_size
|
||||||
|
< block_size)
|
||||||
|
block_size = max_block_list_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
mt_options.block_size = block_size;
|
||||||
mt_options.check = check;
|
mt_options.check = check;
|
||||||
|
|
||||||
memory_usage = filters_memusage_max(
|
memory_usage = filters_memusage_max(
|
||||||
|
|
Loading…
Reference in New Issue