This commit is contained in:
Alexander 2017-09-18 02:37:47 +03:00
parent af3dcf84af
commit 6d2be876c8
4 changed files with 149 additions and 27 deletions

View File

@ -0,0 +1,130 @@
from __future__ import division, print_function
from helper import unittest, PillowTestCase
from PIL import Image
class TestCoreStats(PillowTestCase):
def test_get_stats(self):
# Create at least one image
Image.new('RGB', (10, 10))
stats = Image.core.get_stats()
self.assertIn('new_count', stats)
self.assertIn('reused_blocks', stats)
self.assertIn('freed_blocks', stats)
self.assertIn('allocated_blocks', stats)
self.assertIn('reallocated_blocks', stats)
self.assertIn('blocks_cached', stats)
def test_reset_stats(self):
Image.core.reset_stats()
stats = Image.core.get_stats()
self.assertEqual(stats['new_count'], 0)
self.assertEqual(stats['reused_blocks'], 0)
self.assertEqual(stats['freed_blocks'], 0)
self.assertEqual(stats['allocated_blocks'], 0)
self.assertEqual(stats['reallocated_blocks'], 0)
self.assertEqual(stats['blocks_cached'], 0)
class TestCoreMemory(PillowTestCase):
def tearDown(self):
# Restore default values
Image.core.set_alignment(1)
Image.core.set_block_size(1024*1024)
Image.core.set_blocks_max(0)
Image.core.clear_cache()
def test_get_alignment(self):
alignment = Image.core.get_alignment()
self.assertGreater(alignment, 0)
def test_set_alignment(self):
for i in [1, 2, 4, 8, 16, 32]:
Image.core.set_alignment(i)
alignment = Image.core.get_alignment()
self.assertEqual(alignment, i)
# Try to construct new image
Image.new('RGB', (10, 10))
self.assertRaises(ValueError, Image.core.set_alignment, 0)
self.assertRaises(ValueError, Image.core.set_alignment, -1)
self.assertRaises(ValueError, Image.core.set_alignment, 3)
def test_get_block_size(self):
block_size = Image.core.get_block_size()
self.assertGreaterEqual(block_size, 4096)
def test_set_block_size(self):
for i in [4096, 2*4096, 3*4096]:
Image.core.set_block_size(i)
block_size = Image.core.get_block_size()
self.assertEqual(block_size, i)
# Try to construct new image
Image.new('RGB', (10, 10))
self.assertRaises(ValueError, Image.core.set_block_size, 0)
self.assertRaises(ValueError, Image.core.set_block_size, -1)
self.assertRaises(ValueError, Image.core.set_block_size, 4000)
def test_set_block_size_stats(self):
Image.core.reset_stats()
Image.core.set_blocks_max(0)
Image.core.set_block_size(4096)
Image.new('RGB', (256, 256))
stats = Image.core.get_stats()
self.assertGreaterEqual(stats['new_count'], 1)
self.assertGreaterEqual(stats['allocated_blocks'], 64)
self.assertGreaterEqual(stats['freed_blocks'], 64)
def test_get_blocks_max(self):
blocks_max = Image.core.get_blocks_max()
self.assertGreaterEqual(blocks_max, 0)
def test_set_blocks_max(self):
for i in [0, 1, 10]:
Image.core.set_blocks_max(i)
blocks_max = Image.core.get_blocks_max()
self.assertEqual(blocks_max, i)
# Try to construct new image
Image.new('RGB', (10, 10))
self.assertRaises(ValueError, Image.core.set_blocks_max, -1)
def test_set_blocks_max_stats(self):
Image.core.reset_stats()
Image.core.set_blocks_max(128)
Image.core.set_block_size(4096)
Image.new('RGB', (256, 256))
Image.new('RGB', (256, 256))
stats = Image.core.get_stats()
self.assertGreaterEqual(stats['new_count'], 2)
self.assertGreaterEqual(stats['allocated_blocks'], 64)
self.assertGreaterEqual(stats['reused_blocks'], 64)
self.assertEqual(stats['freed_blocks'], 0)
self.assertEqual(stats['blocks_cached'], 64)
def test_clear_cache_stats(self):
Image.core.reset_stats()
Image.core.set_blocks_max(128)
Image.core.set_block_size(4096)
Image.new('RGB', (256, 256))
Image.new('RGB', (256, 256))
Image.core.clear_cache()
stats = Image.core.get_stats()
self.assertGreaterEqual(stats['new_count'], 2)
self.assertGreaterEqual(stats['allocated_blocks'], 64)
self.assertGreaterEqual(stats['reused_blocks'], 64)
self.assertGreaterEqual(stats['freed_blocks'], 64)
self.assertEqual(stats['blocks_cached'], 0)

View File

@ -3350,6 +3350,8 @@ _get_stats(PyObject* self, PyObject* args)
PyInt_FromLong(arena->stats_reallocated_blocks));
PyDict_SetItemString(d, "freed_blocks",
PyInt_FromLong(arena->stats_freed_blocks));
PyDict_SetItemString(d, "blocks_cached",
PyInt_FromLong(arena->blocks_cached));
return d;
}
@ -3398,15 +3400,6 @@ _get_blocks_max(PyObject* self, PyObject* args)
return PyInt_FromLong(ImagingDefaultArena.blocks_max);
}
static PyObject*
_get_blocks_free(PyObject* self, PyObject* args)
{
if (!PyArg_ParseTuple(args, ":get_blocks_free"))
return NULL;
return PyInt_FromLong(ImagingDefaultArena.blocks_free);
}
static PyObject*
_set_alignment(PyObject* self, PyObject* args)
{
@ -3437,7 +3430,7 @@ _set_block_size(PyObject* self, PyObject* args)
if (!PyArg_ParseTuple(args, "i:set_block_size", &block_size))
return NULL;
if (block_size < 0) {
if (block_size <= 0) {
PyErr_SetString(PyExc_ValueError,
"block_size should be greater than 0");
return NULL;
@ -3649,7 +3642,6 @@ static PyMethodDef functions[] = {
{"get_alignment", (PyCFunction)_get_alignment, 1},
{"get_block_size", (PyCFunction)_get_block_size, 1},
{"get_blocks_max", (PyCFunction)_get_blocks_max, 1},
{"get_blocks_free", (PyCFunction)_get_blocks_free, 1},
{"set_alignment", (PyCFunction)_set_alignment, 1},
{"set_block_size", (PyCFunction)_set_block_size, 1},
{"set_blocks_max", (PyCFunction)_set_blocks_max, 1},

View File

@ -157,7 +157,7 @@ typedef struct ImagingMemoryArena {
int alignment;
int block_size;
int blocks_max;
int blocks_free;
int blocks_cached;
void **blocks;
int stats_new_count;
int stats_allocated_blocks;

View File

@ -268,7 +268,7 @@ struct ImagingMemoryArena ImagingDefaultArena = {
1, // alignment
1*1024*1024, // block_size
0, // blocks_max
0, // blocks_free
0, // blocks_cached
NULL, // blocks
0, 0, 0, 0, 0 // Stats
};
@ -278,9 +278,9 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
{
void *p;
/* Free already cached blocks */
while (arena->blocks_free > blocks_max) {
arena->blocks_free -= 1;
free(arena->blocks[arena->blocks_free]);
while (arena->blocks_cached > blocks_max) {
arena->blocks_cached -= 1;
free(arena->blocks[arena->blocks_cached]);
arena->stats_freed_blocks += 1;
}
@ -310,9 +310,9 @@ ImagingMemorySetBlocksMax(ImagingMemoryArena arena, int blocks_max)
void
ImagingMemoryClearCache(ImagingMemoryArena arena)
{
while (arena->blocks_free > 0) {
arena->blocks_free -= 1;
free(arena->blocks[arena->blocks_free]);
while (arena->blocks_cached > 0) {
arena->blocks_cached -= 1;
free(arena->blocks[arena->blocks_cached]);
arena->stats_freed_blocks += 1;
}
}
@ -321,16 +321,16 @@ void *
memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
{
void *block;
if (arena->blocks_free > 0) {
arena->blocks_free -= 1;
block = realloc(arena->blocks[arena->blocks_free], requested_size);
if (arena->blocks_cached > 0) {
arena->blocks_cached -= 1;
block = realloc(arena->blocks[arena->blocks_cached], requested_size);
if ( ! block) {
free(arena->blocks[arena->blocks_free]);
free(arena->blocks[arena->blocks_cached]);
arena->stats_freed_blocks += 1;
return NULL;
}
arena->stats_reused_blocks += 1;
if (block != arena->blocks[arena->blocks_free]) {
if (block != arena->blocks[arena->blocks_cached]) {
arena->stats_reallocated_blocks += 1;
}
if ( ! dirty) {
@ -350,9 +350,9 @@ memory_get_block(ImagingMemoryArena arena, int requested_size, int dirty)
void
memory_return_block(ImagingMemoryArena arena, void *block)
{
if (arena->blocks_free < arena->blocks_max) {
arena->blocks[arena->blocks_free] = block;
arena->blocks_free += 1;
if (arena->blocks_cached < arena->blocks_max) {
arena->blocks[arena->blocks_cached] = block;
arena->blocks_cached += 1;
} else {
free(block);
arena->stats_freed_blocks += 1;