mirror of
https://github.com/webmproject/libwebp.git
synced 2025-02-13 07:22:52 +01:00
reduce the number of malloc/free cycles in huffman.c
pre-allocating a sorted[] array for most common cases of small alphabet size cuts a lot of traffic. Change-Id: I73ff2f6e507f81b0b0bb7d9801a344aa4bcb038a
This commit is contained in:
parent
7b4b05e0dc
commit
fc8cad9f29
@ -75,11 +75,13 @@ static WEBP_INLINE int NextTableBitSize(const int* const count,
|
|||||||
return len - root_bits;
|
return len - root_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
// sorted[code_lengths_size] is a pre-allocated array for sorting symbols
|
||||||
const int code_lengths[], int code_lengths_size) {
|
// by code length.
|
||||||
|
static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||||
|
const int code_lengths[], int code_lengths_size,
|
||||||
|
uint16_t sorted[]) {
|
||||||
HuffmanCode* table = root_table; // next available space in table
|
HuffmanCode* table = root_table; // next available space in table
|
||||||
int total_size = 1 << root_bits; // total size root table + 2nd level table
|
int total_size = 1 << root_bits; // total size root table + 2nd level table
|
||||||
int* sorted = NULL; // symbols sorted by code length
|
|
||||||
int len; // current code length
|
int len; // current code length
|
||||||
int symbol; // symbol index in original or sorted table
|
int symbol; // symbol index in original or sorted table
|
||||||
// number of codes of each length:
|
// number of codes of each length:
|
||||||
@ -114,11 +116,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
|||||||
offset[len + 1] = offset[len] + count[len];
|
offset[len + 1] = offset[len] + count[len];
|
||||||
}
|
}
|
||||||
|
|
||||||
sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
|
|
||||||
if (sorted == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort symbols by length, by symbol order within each length.
|
// Sort symbols by length, by symbol order within each length.
|
||||||
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
|
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
|
||||||
const int symbol_code_length = code_lengths[symbol];
|
const int symbol_code_length = code_lengths[symbol];
|
||||||
@ -133,7 +130,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
|||||||
code.bits = 0;
|
code.bits = 0;
|
||||||
code.value = (uint16_t)sorted[0];
|
code.value = (uint16_t)sorted[0];
|
||||||
ReplicateValue(table, 1, total_size, code);
|
ReplicateValue(table, 1, total_size, code);
|
||||||
WebPSafeFree(sorted);
|
|
||||||
return total_size;
|
return total_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +149,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
|||||||
num_nodes += num_open;
|
num_nodes += num_open;
|
||||||
num_open -= count[len];
|
num_open -= count[len];
|
||||||
if (num_open < 0) {
|
if (num_open < 0) {
|
||||||
WebPSafeFree(sorted);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (; count[len] > 0; --count[len]) {
|
for (; count[len] > 0; --count[len]) {
|
||||||
@ -172,7 +167,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
|||||||
num_nodes += num_open;
|
num_nodes += num_open;
|
||||||
num_open -= count[len];
|
num_open -= count[len];
|
||||||
if (num_open < 0) {
|
if (num_open < 0) {
|
||||||
WebPSafeFree(sorted);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
for (; count[len] > 0; --count[len]) {
|
for (; count[len] > 0; --count[len]) {
|
||||||
@ -195,11 +189,35 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
|||||||
|
|
||||||
// Check if tree is full.
|
// Check if tree is full.
|
||||||
if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
|
if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
|
||||||
WebPSafeFree(sorted);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WebPSafeFree(sorted);
|
return total_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits).
|
||||||
|
// More commonly, the value is around ~280.
|
||||||
|
#define MAX_CODE_LENGTHS_SIZE \
|
||||||
|
((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
|
||||||
|
// Cut-off value for switching between heap and stack allocation.
|
||||||
|
#define SORTED_SIZE_CUTOFF 512
|
||||||
|
int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
|
||||||
|
const int code_lengths[], int code_lengths_size) {
|
||||||
|
int total_size;
|
||||||
|
assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
|
||||||
|
if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
|
||||||
|
// use local stack-allocated array.
|
||||||
|
uint16_t sorted[SORTED_SIZE_CUTOFF];
|
||||||
|
total_size = BuildHuffmanTable(root_table, root_bits,
|
||||||
|
code_lengths, code_lengths_size, sorted);
|
||||||
|
} else { // rare case. Use heap allocation.
|
||||||
|
uint16_t* const sorted =
|
||||||
|
(uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
|
||||||
|
if (sorted == NULL) return 0;
|
||||||
|
total_size = BuildHuffmanTable(root_table, root_bits,
|
||||||
|
code_lengths, code_lengths_size, sorted);
|
||||||
|
WebPSafeFree(sorted);
|
||||||
|
}
|
||||||
return total_size;
|
return total_size;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user