Merge pull request #67 from plieven/small_allocations
MEMORY introduce a small allocation pool
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
50
lib/init.c
50
lib/init.c
@@ -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));
|
||||
|
||||
29
lib/pdu.c
29
lib/pdu.c
@@ -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 "
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user