mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-02-04 21:50:54 +03:00
ImagingMemoryBlock structure
This commit is contained in:
parent
67e1e03c79
commit
44c2698f69
|
@ -124,6 +124,7 @@ class TestCoreMemory(PillowTestCase):
|
||||||
@unittest.skipIf(is_pypy, "images are not collected")
|
@unittest.skipIf(is_pypy, "images are not collected")
|
||||||
def test_clear_cache_stats(self):
|
def test_clear_cache_stats(self):
|
||||||
Image.core.reset_stats()
|
Image.core.reset_stats()
|
||||||
|
Image.core.clear_cache()
|
||||||
Image.core.set_blocks_max(128)
|
Image.core.set_blocks_max(128)
|
||||||
Image.core.set_block_size(4096)
|
Image.core.set_block_size(4096)
|
||||||
Image.new('RGB', (256, 256))
|
Image.new('RGB', (256, 256))
|
||||||
|
@ -131,6 +132,7 @@ class TestCoreMemory(PillowTestCase):
|
||||||
Image.core.clear_cache()
|
Image.core.clear_cache()
|
||||||
|
|
||||||
stats = Image.core.get_stats()
|
stats = Image.core.get_stats()
|
||||||
|
print(stats)
|
||||||
self.assertGreaterEqual(stats['new_count'], 2)
|
self.assertGreaterEqual(stats['new_count'], 2)
|
||||||
self.assertGreaterEqual(stats['allocated_blocks'], 64)
|
self.assertGreaterEqual(stats['allocated_blocks'], 64)
|
||||||
self.assertGreaterEqual(stats['reused_blocks'], 64)
|
self.assertGreaterEqual(stats['reused_blocks'], 64)
|
||||||
|
|
|
@ -75,6 +75,11 @@ typedef struct ImagingPaletteInstance* ImagingPalette;
|
||||||
|
|
||||||
#define IMAGING_MODE_LENGTH 6+1 /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
|
#define IMAGING_MODE_LENGTH 6+1 /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *ptr;
|
||||||
|
int size;
|
||||||
|
} ImagingMemoryBlock;
|
||||||
|
|
||||||
struct ImagingMemoryInstance {
|
struct ImagingMemoryInstance {
|
||||||
|
|
||||||
/* Format */
|
/* Format */
|
||||||
|
@ -95,7 +100,7 @@ struct ImagingMemoryInstance {
|
||||||
/* Internals */
|
/* Internals */
|
||||||
char **image; /* Actual raster data. */
|
char **image; /* Actual raster data. */
|
||||||
char *block; /* Set if data is allocated in a single block. */
|
char *block; /* Set if data is allocated in a single block. */
|
||||||
char **blocks; /* Memory blocks for pixel storage */
|
ImagingMemoryBlock *blocks; /* Memory blocks for pixel storage */
|
||||||
|
|
||||||
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
|
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
|
||||||
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
|
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
|
||||||
|
@ -158,7 +163,7 @@ typedef struct ImagingMemoryArena {
|
||||||
int block_size;
|
int block_size;
|
||||||
int blocks_max;
|
int blocks_max;
|
||||||
int blocks_cached;
|
int blocks_cached;
|
||||||
void **blocks;
|
ImagingMemoryBlock *blocks;
|
||||||
int stats_new_count;
|
int stats_new_count;
|
||||||
int stats_allocated_blocks;
|
int stats_allocated_blocks;
|
||||||
int stats_reused_blocks;
|
int stats_reused_blocks;
|
||||||
|
|
|
@ -284,14 +284,14 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
|
||||||
free(arena->blocks);
|
free(arena->blocks);
|
||||||
arena->blocks = NULL;
|
arena->blocks = NULL;
|
||||||
} else if (arena->blocks != NULL) {
|
} else if (arena->blocks != NULL) {
|
||||||
p = realloc(arena->blocks, sizeof(void*) * blocks_max);
|
p = realloc(arena->blocks, sizeof(*arena->blocks) * blocks_max);
|
||||||
if ( ! p) {
|
if ( ! p) {
|
||||||
// Leave previous blocks_max value
|
// Leave previous blocks_max value
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
arena->blocks = p;
|
arena->blocks = p;
|
||||||
} else {
|
} else {
|
||||||
arena->blocks = calloc(sizeof(void*), blocks_max);
|
arena->blocks = calloc(sizeof(*arena->blocks), blocks_max);
|
||||||
if ( ! arena->blocks) {
|
if ( ! arena->blocks) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -306,49 +306,57 @@ ImagingMemoryClearCache(ImagingMemoryArena arena, int new_size)
|
||||||
{
|
{
|
||||||
while (arena->blocks_cached > new_size) {
|
while (arena->blocks_cached > new_size) {
|
||||||
arena->blocks_cached -= 1;
|
arena->blocks_cached -= 1;
|
||||||
free(arena->blocks[arena->blocks_cached]);
|
free(arena->blocks[arena->blocks_cached].ptr);
|
||||||
arena->stats_freed_blocks += 1;
|
arena->stats_freed_blocks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
ImagingMemoryBlock
|
||||||
memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
|
||||||
{
|
{
|
||||||
void *block;
|
ImagingMemoryBlock block = {NULL, 0};
|
||||||
|
|
||||||
if (arena->blocks_cached > 0) {
|
if (arena->blocks_cached > 0) {
|
||||||
|
// Get block from cache
|
||||||
arena->blocks_cached -= 1;
|
arena->blocks_cached -= 1;
|
||||||
block = realloc(arena->blocks[arena->blocks_cached], requested_size);
|
block = arena->blocks[arena->blocks_cached];
|
||||||
if ( ! block) {
|
// Reallocate if needed
|
||||||
free(arena->blocks[arena->blocks_cached]);
|
if (block.size != requested_size){
|
||||||
arena->stats_freed_blocks += 1;
|
block.ptr = realloc(block.ptr, requested_size);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
arena->stats_reused_blocks += 1;
|
if ( ! block.ptr) {
|
||||||
if (block != arena->blocks[arena->blocks_cached]) {
|
// Can't allocate, free prevous pointer (it is still valid)
|
||||||
arena->stats_reallocated_blocks += 1;
|
free(arena->blocks[arena->blocks_cached].ptr);
|
||||||
|
arena->stats_freed_blocks += 1;
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
if ( ! dirty) {
|
if ( ! dirty) {
|
||||||
memset(block, 0, requested_size);
|
memset(block.ptr, 0, requested_size);
|
||||||
|
}
|
||||||
|
arena->stats_reused_blocks += 1;
|
||||||
|
if (block.ptr != arena->blocks[arena->blocks_cached].ptr) {
|
||||||
|
arena->stats_reallocated_blocks += 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
block = malloc(requested_size);
|
block.ptr = malloc(requested_size);
|
||||||
} else {
|
} else {
|
||||||
block = calloc(1, requested_size);
|
block.ptr = calloc(1, requested_size);
|
||||||
}
|
}
|
||||||
arena->stats_allocated_blocks += 1;
|
arena->stats_allocated_blocks += 1;
|
||||||
}
|
}
|
||||||
|
block.size = requested_size;
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
memory_return_block(ImagingMemoryArena arena, void *block)
|
memory_return_block(ImagingMemoryArena arena, ImagingMemoryBlock block)
|
||||||
{
|
{
|
||||||
if (arena->blocks_cached < arena->blocks_max) {
|
if (arena->blocks_cached < arena->blocks_max) {
|
||||||
arena->blocks[arena->blocks_cached] = block;
|
arena->blocks[arena->blocks_cached] = block;
|
||||||
arena->blocks_cached += 1;
|
arena->blocks_cached += 1;
|
||||||
} else {
|
} else {
|
||||||
free(block);
|
free(block.ptr);
|
||||||
arena->stats_freed_blocks += 1;
|
arena->stats_freed_blocks += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,7 +368,7 @@ ImagingDestroyArray(Imaging im)
|
||||||
int y = 0;
|
int y = 0;
|
||||||
|
|
||||||
if (im->blocks) {
|
if (im->blocks) {
|
||||||
while (im->blocks[y]) {
|
while (im->blocks[y].ptr) {
|
||||||
memory_return_block(&ImagingDefaultArena, im->blocks[y]);
|
memory_return_block(&ImagingDefaultArena, im->blocks[y]);
|
||||||
y += 1;
|
y += 1;
|
||||||
}
|
}
|
||||||
|
@ -373,7 +381,7 @@ ImagingAllocateArray(Imaging im, int dirty)
|
||||||
{
|
{
|
||||||
int y, line_in_block, current_block;
|
int y, line_in_block, current_block;
|
||||||
ImagingMemoryArena arena = &ImagingDefaultArena;
|
ImagingMemoryArena arena = &ImagingDefaultArena;
|
||||||
char* p = NULL;
|
ImagingMemoryBlock block = {NULL, 0};
|
||||||
int linesize, lines_per_block, blocks_count;
|
int linesize, lines_per_block, blocks_count;
|
||||||
|
|
||||||
/* 0-width or 0-height image. No need to do anything */
|
/* 0-width or 0-height image. No need to do anything */
|
||||||
|
@ -391,7 +399,7 @@ ImagingAllocateArray(Imaging im, int dirty)
|
||||||
|
|
||||||
im->destroy = ImagingDestroyArray;
|
im->destroy = ImagingDestroyArray;
|
||||||
/* One extra ponter is always NULL */
|
/* One extra ponter is always NULL */
|
||||||
im->blocks = (char **)calloc(sizeof(char *), blocks_count + 1);
|
im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1);
|
||||||
if ( ! im->blocks) {
|
if ( ! im->blocks) {
|
||||||
return (Imaging) ImagingError_MemoryError();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
}
|
}
|
||||||
|
@ -406,14 +414,14 @@ ImagingAllocateArray(Imaging im, int dirty)
|
||||||
if (lines_remained > im->ysize - y) {
|
if (lines_remained > im->ysize - y) {
|
||||||
lines_remained = im->ysize - y;
|
lines_remained = im->ysize - y;
|
||||||
}
|
}
|
||||||
p = memory_get_block(arena, lines_remained * linesize, dirty);
|
block = memory_get_block(arena, lines_remained * linesize, dirty);
|
||||||
if ( ! p) {
|
if ( ! block.ptr) {
|
||||||
return (Imaging) ImagingError_MemoryError();
|
return (Imaging) ImagingError_MemoryError();
|
||||||
}
|
}
|
||||||
im->blocks[current_block] = p;
|
im->blocks[current_block] = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
im->image[y] = p + linesize * line_in_block;
|
im->image[y] = block.ptr + linesize * line_in_block;
|
||||||
|
|
||||||
line_in_block += 1;
|
line_in_block += 1;
|
||||||
if (line_in_block >= lines_per_block) {
|
if (line_in_block >= lines_per_block) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user