xz/src/liblzma/common/memory_usage.c

114 lines
2.8 KiB
C

///////////////////////////////////////////////////////////////////////////////
//
/// \file memory_usage.c
/// \brief Calculate rough amount of memory required by filters
//
// Copyright (C) 2007 Lasse Collin
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
///////////////////////////////////////////////////////////////////////////////
#include "common.h"
#include "lz_encoder.h"
#include "lzma_literal.h"
static uint64_t
get_usage(const lzma_options_filter *filter, bool is_encoder)
{
uint64_t ret;
switch (filter->id) {
case LZMA_FILTER_COPY:
case LZMA_FILTER_X86:
case LZMA_FILTER_POWERPC:
case LZMA_FILTER_IA64:
case LZMA_FILTER_ARM:
case LZMA_FILTER_ARMTHUMB:
case LZMA_FILTER_SPARC:
case LZMA_FILTER_DELTA:
// These don't require any significant amount of memory.
ret = 0;
break;
case LZMA_FILTER_SUBBLOCK:
if (is_encoder) {
const lzma_options_subblock *options = filter->options;
ret = options->subblock_data_size;
} else {
ret = 0;
}
break;
#ifdef HAVE_FILTER_LZMA
case LZMA_FILTER_LZMA: {
const lzma_options_lzma *options = filter->options;
// Literal coder - this can be signficant if both values are
// big, or if sizeof(probability) is big.
ret = literal_states(options->literal_context_bits,
options->literal_pos_bits) * LIT_SIZE
* sizeof(probability);
// Dictionary base size
ret += options->dictionary_size;
if (is_encoder) {
# ifdef HAVE_ENCODER
// This is rough, but should be accurate enough
// in practice.
ret += options->dictionary_size / 2;
uint32_t dummy1;
uint32_t dummy2;
uint32_t num_items;
if (lzma_lz_encoder_hash_properties(
options->match_finder,
options->dictionary_size,
&dummy1, &dummy2, &num_items))
return UINT64_MAX;
ret += (uint64_t)(num_items) * sizeof(uint32_t);
# else
return UINT64_MAX;
# endif
}
break;
}
#endif
default:
return UINT64_MAX;
}
return ret;
}
extern LZMA_API uint32_t
lzma_memory_usage(const lzma_options_filter *filters, lzma_bool is_encoder)
{
uint64_t usage = 0;
for (size_t i = 0; filters[i].id != UINT64_MAX; ++i) {
const uint64_t ret = get_usage(filters + i, is_encoder);
if (ret == UINT64_MAX)
return UINT32_MAX;
usage += ret;
}
// Convert to mebibytes with rounding.
return usage / (1024 * 1024) + (usage % (1024 * 1024) >= 512 ? 1 : 0);
}