fallback to small block size on memory error

increase default block size to previous value
This commit is contained in:
Alexander 2017-09-23 04:15:19 +03:00
parent b51d77e4e5
commit 6a435793d8
2 changed files with 25 additions and 14 deletions

View File

@ -159,16 +159,16 @@ struct ImagingPaletteInstance {
}; };
typedef struct ImagingMemoryArena { typedef struct ImagingMemoryArena {
int alignment; int alignment; /* Alignment in memory of each line of an image */
int block_size; int block_size; /* Preferred block size */
int blocks_max; int blocks_max; /* Maximum number of cached blocks */
int blocks_cached; int blocks_cached; /* Current number of block not accociated with images */
ImagingMemoryBlock *blocks; ImagingMemoryBlock *blocks;
int stats_new_count; int stats_new_count; /* Number of new allocated images */
int stats_allocated_blocks; int stats_allocated_blocks; /* Number of allocated blocks */
int stats_reused_blocks; int stats_reused_blocks; /* Number of blocks which was retrieved from pool */
int stats_reallocated_blocks; int stats_reallocated_blocks; /* Number of blocks which was actually reallocated after retrieving */
int stats_freed_blocks; int stats_freed_blocks; /* Number of freed blocks */
} *ImagingMemoryArena; } *ImagingMemoryArena;

View File

@ -264,9 +264,11 @@ ImagingDelete(Imaging im)
/* ------------------ */ /* ------------------ */
/* Allocate image as an array of line buffers. */ /* Allocate image as an array of line buffers. */
#define IMAGING_PAGE_SIZE (4096)
struct ImagingMemoryArena ImagingDefaultArena = { struct ImagingMemoryArena ImagingDefaultArena = {
1, // alignment 1, // alignment
1*1024*1024, // block_size 16*1024*1024, // block_size
0, // blocks_max 0, // blocks_max
0, // blocks_cached 0, // blocks_cached
NULL, // blocks NULL, // blocks
@ -382,7 +384,7 @@ ImagingDestroyArray(Imaging im)
} }
Imaging Imaging
ImagingAllocateArray(Imaging im, int dirty) ImagingAllocateArray(Imaging im, int dirty, int block_size)
{ {
int y, line_in_block, current_block; int y, line_in_block, current_block;
ImagingMemoryArena arena = &ImagingDefaultArena; ImagingMemoryArena arena = &ImagingDefaultArena;
@ -395,14 +397,13 @@ ImagingAllocateArray(Imaging im, int dirty)
} }
linesize = (im->linesize + arena->alignment - 1) & -arena->alignment; linesize = (im->linesize + arena->alignment - 1) & -arena->alignment;
lines_per_block = arena->block_size / linesize; lines_per_block = block_size / linesize;
if (lines_per_block == 0) if (lines_per_block == 0)
lines_per_block = 1; lines_per_block = 1;
blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block; blocks_count = (im->ysize + lines_per_block - 1) / lines_per_block;
// printf("NEW size: %dx%d, ls: %d, lpb: %d, blocks: %d\n", // printf("NEW size: %dx%d, ls: %d, lpb: %d, blocks: %d\n",
// im->xsize, im->ysize, linesize, lines_per_block, blocks_count); // im->xsize, im->ysize, linesize, lines_per_block, blocks_count);
im->destroy = ImagingDestroyArray;
/* One extra ponter is always NULL */ /* One extra ponter is always NULL */
im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1); im->blocks = calloc(sizeof(*im->blocks), blocks_count + 1);
if ( ! im->blocks) { if ( ! im->blocks) {
@ -421,6 +422,7 @@ ImagingAllocateArray(Imaging im, int dirty)
} }
block = memory_get_block(arena, lines_remained * linesize, dirty); block = memory_get_block(arena, lines_remained * linesize, dirty);
if ( ! block.ptr) { if ( ! block.ptr) {
ImagingDestroyArray(im);
return (Imaging) ImagingError_MemoryError(); return (Imaging) ImagingError_MemoryError();
} }
im->blocks[current_block] = block; im->blocks[current_block] = block;
@ -436,6 +438,8 @@ ImagingAllocateArray(Imaging im, int dirty)
} }
} }
im->destroy = ImagingDestroyArray;
return im; return im;
} }
@ -503,7 +507,14 @@ ImagingNewInternal(const char* mode, int xsize, int ysize, int dirty)
if ( ! im) if ( ! im)
return NULL; return NULL;
if (ImagingAllocateArray(im, dirty)) { if (ImagingAllocateArray(im, dirty, ImagingDefaultArena.block_size)) {
return im;
}
ImagingError_Clear();
// Try to allocate the image once more with smallest possible block size
if (ImagingAllocateArray(im, dirty, IMAGING_PAGE_SIZE)) {
return im; return im;
} }