CostManager: cache one interval and re-use it when possible

In a lot of cases, only one interval is used. This can cause
a lot of malloc/free cycles for only 56 bytes. By caching this
single interval and re-using it, we remove this cycle in most
frequent cases.

Change-Id: Ia22d583f60ae438c216612062316b20ecb34f029
This commit is contained in:
Pascal Massimino 2016-06-08 13:30:01 +02:00
parent 41b7e6b56e
commit 0481d42ad8

View File

@ -619,6 +619,8 @@ typedef struct {
double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k). double cost_cache_[MAX_LENGTH]; // Contains the GetLengthCost(cost_model, k).
float* costs_; float* costs_;
uint16_t* dist_array_; uint16_t* dist_array_;
CostInterval spare_; // most of the time, we only will be using a single
int spare_used_; // interval. => We re-use this one first if possible.
} CostManager; } CostManager;
static int IsCostCacheIntervalWritable(int start, int end) { static int IsCostCacheIntervalWritable(int start, int end) {
@ -642,7 +644,11 @@ static void CostManagerClear(CostManager* const manager) {
CostInterval* interval = manager->head_; CostInterval* interval = manager->head_;
while (interval != NULL) { while (interval != NULL) {
CostInterval* const next = interval->next_; CostInterval* const next = interval->next_;
WebPSafeFree(interval); if (manager->spare_used_ && interval == &manager->spare_) {
manager->spare_used_ = 0;
} else {
WebPSafeFree(interval);
}
interval = next; interval = next;
} }
} }
@ -663,6 +669,7 @@ static int CostManagerInit(CostManager* const manager,
manager->head_ = NULL; manager->head_ = NULL;
manager->count_ = 0; manager->count_ = 0;
manager->dist_array_ = dist_array; manager->dist_array_ = dist_array;
manager->spare_used_ = 0;
// Fill in the cost_cache_. // Fill in the cost_cache_.
manager->cache_intervals_size_ = 1; manager->cache_intervals_size_ = 1;
@ -793,8 +800,11 @@ static WEBP_INLINE void PopInterval(CostManager* const manager,
if (interval == NULL) return; if (interval == NULL) return;
ConnectIntervals(manager, interval->previous_, next); ConnectIntervals(manager, interval->previous_, next);
if (interval == &manager->spare_) {
WebPSafeFree(interval); manager->spare_used_ = 0;
} else {
WebPSafeFree(interval);
}
--manager->count_; --manager->count_;
assert(manager->count_ >= 0); assert(manager->count_ >= 0);
} }
@ -857,12 +867,16 @@ static WEBP_INLINE void InsertInterval(CostManager* const manager,
UpdateCostPerInterval(manager, start, end, index, distance_cost); UpdateCostPerInterval(manager, start, end, index, distance_cost);
return; return;
} }
if (!manager->spare_used_) {
interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new)); interval_new = &manager->spare_;
if (interval_new == NULL) { manager->spare_used_ = 1;
// Write down the interval if we cannot create it. } else {
UpdateCostPerInterval(manager, start, end, index, distance_cost); interval_new = (CostInterval*)WebPSafeMalloc(1, sizeof(*interval_new));
return; if (interval_new == NULL) {
// Write down the interval if we cannot create it.
UpdateCostPerInterval(manager, start, end, index, distance_cost);
return;
}
} }
interval_new->distance_cost_ = distance_cost; interval_new->distance_cost_ = distance_cost;