Merge pull request #67 from plieven/small_allocations

MEMORY introduce a small allocation pool
This commit is contained in:
Ronnie Sahlberg
2013-08-02 06:45:35 -07:00
4 changed files with 77 additions and 13 deletions

View File

@@ -39,6 +39,7 @@ extern "C" {
#define ISCSI_HEADER_SIZE (ISCSI_RAW_HEADER_SIZE \
+ (iscsi->header_digest == ISCSI_HEADER_DIGEST_NONE?0:ISCSI_DIGEST_SIZE))
#define SMALL_ALLOC_MAX_FREE (128) /* must be power of 2 */
struct iscsi_in_pdu {
struct iscsi_in_pdu *next;
@@ -131,6 +132,10 @@ struct iscsi_context {
int mallocs;
int reallocs;
int frees;
int smallocs;
void* smalloc_ptrs[SMALL_ALLOC_MAX_FREE];
int smalloc_free;
size_t smalloc_size;
time_t last_reconnect;
int scsi_timeout;
@@ -301,6 +306,8 @@ inline void* iscsi_zmalloc(struct iscsi_context *iscsi, size_t size);
inline void* iscsi_realloc(struct iscsi_context *iscsi, void* ptr, size_t size);
inline void iscsi_free(struct iscsi_context *iscsi, void* ptr);
inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str);
inline void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size);
inline void iscsi_sfree(struct iscsi_context *iscsi, void* ptr);
unsigned long crc32c(char *buf, int len);

View File

@@ -33,7 +33,6 @@
#include "iscsi-private.h"
#include "slist.h"
inline void* iscsi_malloc(struct iscsi_context *iscsi, size_t size) {
void * ptr = malloc(size);
if (ptr != NULL) iscsi->mallocs++;
@@ -69,6 +68,36 @@ inline char* iscsi_strdup(struct iscsi_context *iscsi, const char* str) {
return str2;
}
inline void* iscsi_szmalloc(struct iscsi_context *iscsi, size_t size) {
void *ptr;
if (size > iscsi->smalloc_size) return NULL;
if (iscsi->smalloc_free > 0) {
ptr = iscsi->smalloc_ptrs[--iscsi->smalloc_free];
memset(ptr, 0, iscsi->smalloc_size);
iscsi->smallocs++;
} else {
ptr = iscsi_zmalloc(iscsi, iscsi->smalloc_size);
}
return ptr;
}
inline void iscsi_sfree(struct iscsi_context *iscsi, void* ptr) {
if (ptr == NULL) return;
if (iscsi->smalloc_free == SMALL_ALLOC_MAX_FREE) {
/* SMALL_ALLOC_MAX_FREE should be adjusted that this happens rarely */
ISCSI_LOG(iscsi,6,"smalloc free == SMALLOC_MAX_FREE");
int i;
/* remove oldest half of free pointers and copy
* upper half to lower half */
iscsi->smalloc_free>>=1;
for (i=0; i<iscsi->smalloc_free; i++) {
iscsi_free(iscsi, iscsi->smalloc_ptrs[i]);
iscsi->smalloc_ptrs[i] = iscsi->smalloc_ptrs[i+iscsi->smalloc_free];
}
}
iscsi->smalloc_ptrs[iscsi->smalloc_free++] = ptr;
}
struct iscsi_context *
iscsi_create_context(const char *initiator_name)
{
@@ -144,6 +173,16 @@ iscsi_create_context(const char *initiator_name)
iscsi_set_bind_interfaces(iscsi,getenv("LIBISCSI_BIND_INTERFACES"));
}
/* iscsi->smalloc_size is the size for small allocations. this should be
max(ISCSI_HEADER_SIZE, sizeof(struct iscsi_pdu), sizeof(struct iscsi_in_pdu))
rounded up to the next power of 2. */
iscsi->smalloc_size = 1;
size_t required = ISCSI_RAW_HEADER_SIZE + ISCSI_DIGEST_SIZE;
if (sizeof(struct iscsi_pdu) > required) required = sizeof(struct iscsi_pdu);
if (sizeof(struct iscsi_in_pdu) > required) required = sizeof(struct iscsi_in_pdu);
while (iscsi->smalloc_size < required) iscsi->smalloc_size <<= 1;
ISCSI_LOG(iscsi,5,"small allocation size is %d byte", iscsi->smalloc_size);
return iscsi;
}
@@ -236,6 +275,7 @@ int
iscsi_destroy_context(struct iscsi_context *iscsi)
{
struct iscsi_pdu *pdu;
int i;
if (iscsi == NULL) {
return 0;
@@ -283,10 +323,14 @@ iscsi_destroy_context(struct iscsi_context *iscsi)
iscsi->connect_data = NULL;
for (i=0;i<iscsi->smalloc_free;i++) {
iscsi_free(iscsi, iscsi->smalloc_ptrs[i]);
}
if (iscsi->mallocs != iscsi->frees) {
ISCSI_LOG(iscsi,1,"%d memory blocks lost at iscsi_destroy_context() after %d malloc(s), %d realloc(s) and %d free(s)",iscsi->mallocs-iscsi->frees,iscsi->mallocs,iscsi->reallocs,iscsi->frees);
ISCSI_LOG(iscsi,1,"%d memory blocks lost at iscsi_destroy_context() after %d malloc(s), %d realloc(s), %d free(s) and %d reused small allocations",iscsi->mallocs-iscsi->frees,iscsi->mallocs,iscsi->reallocs,iscsi->frees,iscsi->smallocs);
} else {
ISCSI_LOG(iscsi,5,"memory is clean at iscsi_destroy_context() after %d mallocs, %d realloc(s) and %d frees",iscsi->mallocs,iscsi->reallocs,iscsi->frees);
ISCSI_LOG(iscsi,5,"memory is clean at iscsi_destroy_context() after %d mallocs, %d realloc(s), %d free(s) and %d reused small allocations",iscsi->mallocs,iscsi->reallocs,iscsi->frees,iscsi->smallocs);
}
memset(iscsi, 0, sizeof(struct iscsi_context));

View File

@@ -84,15 +84,14 @@ iscsi_allocate_pdu_with_itt_flags(struct iscsi_context *iscsi, enum iscsi_opcode
{
struct iscsi_pdu *pdu;
pdu = iscsi_zmalloc(iscsi, sizeof(struct iscsi_pdu));
pdu = iscsi_szmalloc(iscsi, sizeof(struct iscsi_pdu));
if (pdu == NULL) {
iscsi_set_error(iscsi, "failed to allocate pdu");
return NULL;
}
pdu->outdata.size = ISCSI_HEADER_SIZE;
pdu->outdata.data = iscsi_malloc(iscsi, pdu->outdata.size);
memset(pdu->outdata.data, 0, ISCSI_HEADER_SIZE);
pdu->outdata.data = iscsi_szmalloc(iscsi, pdu->outdata.size);
if (pdu->outdata.data == NULL) {
iscsi_set_error(iscsi, "failed to allocate pdu header");
@@ -134,13 +133,21 @@ iscsi_free_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
return;
}
iscsi_free(iscsi, pdu->outdata.data);
if (pdu->outdata.size <= iscsi->smalloc_size) {
iscsi_sfree(iscsi, pdu->outdata.data);
} else {
iscsi_free(iscsi, pdu->outdata.data);
}
pdu->outdata.data = NULL;
iscsi_free(iscsi, pdu->indata.data);
if (pdu->indata.size <= iscsi->smalloc_size) {
iscsi_sfree(iscsi, pdu->indata.data);
} else {
iscsi_free(iscsi, pdu->indata.data);
}
pdu->indata.data = NULL;
iscsi_free(iscsi, pdu);
iscsi_sfree(iscsi, pdu);
}
@@ -164,9 +171,15 @@ iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
}
if (data->size == 0) {
data->data = iscsi_malloc(iscsi, aligned);
if (aligned <= iscsi->smalloc_size) {
data->data = iscsi_szmalloc(iscsi, aligned);
} else {
data->data = iscsi_malloc(iscsi, aligned);
}
} else {
data->data = iscsi_realloc(iscsi, data->data, aligned);
if (aligned > iscsi->smalloc_size) {
data->data = iscsi_realloc(iscsi, data->data, aligned);
}
}
if (data->data == NULL) {
iscsi_set_error(iscsi, "failed to allocate buffer for %d "

View File

@@ -492,7 +492,7 @@ iscsi_read_from_socket(struct iscsi_context *iscsi)
ssize_t data_size, count;
if (iscsi->incoming == NULL) {
iscsi->incoming = iscsi_zmalloc(iscsi, sizeof(struct iscsi_in_pdu));
iscsi->incoming = iscsi_szmalloc(iscsi, sizeof(struct iscsi_in_pdu));
if (iscsi->incoming == NULL) {
iscsi_set_error(iscsi, "Out-of-memory: failed to malloc iscsi_in_pdu");
return -1;
@@ -820,7 +820,7 @@ iscsi_free_iscsi_in_pdu(struct iscsi_context *iscsi, struct iscsi_in_pdu *in)
{
iscsi_free(iscsi, in->data);
in->data=NULL;
iscsi_free(iscsi, in);
iscsi_sfree(iscsi, in);
in=NULL;
}