Example #1
0
File: obuf.c Project: mantyr/small
void *
obuf_reserve_slow(struct obuf *buf, size_t size)
{
	struct iovec *iov = &buf->iov[buf->pos];
	size_t capacity = buf->capacity[buf->pos];
	if (iov->iov_len > 0) {
		/* Move to the next buffer. */
		if (buf->pos + 1 >= SMALL_OBUF_IOV_MAX)
			return NULL;
		buf->pos++;
		iov = &buf->iov[buf->pos];
		capacity = buf->capacity[buf->pos];
	}
	assert(iov->iov_len == 0);
	/* Make sure the next buffer can store size. */
	if (size > capacity) {
		if (capacity > 0) {
			/* Simply realloc. */
			while (capacity < size)
				capacity = capacity * 2;
			struct slab *slab = slab_get(buf->slabc, capacity);
			if (slab == NULL)
				return NULL;
			struct slab *old =
				slab_from_data(buf->iov[buf->pos].iov_base);
			slab_put(buf->slabc, old);
			buf->iov[buf->pos].iov_base = slab_data(slab);
			buf->capacity[buf->pos] = slab_capacity(slab);
		} else if (obuf_alloc_pos(buf, size) == NULL) {
			return NULL;
		}
	}
	assert(buf->iov[buf->pos].iov_len + size <= buf->capacity[buf->pos]);
	return (char*) buf->iov[buf->pos].iov_base + buf->iov[buf->pos].iov_len;
}
Example #2
0
File: slab.c Project: huayl/pelikan
void
slab_print(void)
{
    uint8_t id;
    struct slabclass *p;

    loga("slab size %zu, slab hdr size %zu, item hdr size %zu, item chunk size"
            "%zu, total memory %zu", slab_size, SLAB_HDR_SIZE, ITEM_HDR_SIZE,
            item_min, slab_mem);

    for (id = SLABCLASS_MIN_ID; id <= profile_last_id; id++) {
        p = &slabclass[id];

        loga("class %3"PRId8": items %7"PRIu32"  size %7zu  data %7zu  "
             "slack %7zu", id, p->nitem, p->size, p->size - ITEM_HDR_SIZE,
             slab_capacity() - p->nitem * p->size);
    }
}
Example #3
0
File: obuf.c Project: mantyr/small
/** Allocate memory for a single iovec buffer. */
static inline void *
obuf_alloc_pos(struct obuf *buf, size_t size)
{
	int pos = buf->pos;
	assert(buf->capacity[pos] == 0 && buf->iov[pos].iov_len == 0);
	assert(pos < SMALL_OBUF_IOV_MAX);
	assert(buf->n_iov == pos);
	/** Initialize the next pos. */
	buf->iov[pos+1] = buf->iov[pos];
	buf->capacity[pos+1] = buf->capacity[pos];
	size_t capacity = buf->start_capacity << pos;
	while (capacity < size) {
		capacity = capacity == 0 ? buf->start_capacity: capacity * 2;
	}
	struct slab *slab = slab_get(buf->slabc, capacity);
	if (slab == NULL)
		return NULL;
	buf->iov[pos].iov_base = slab_data(slab);
	buf->capacity[pos] = slab_capacity(slab);
	buf->n_iov++;
	return buf->iov[pos].iov_base;
}
Example #4
0
File: slab.c Project: huayl/pelikan
/*
 * Initialize all slabclasses.
 *
 * Every slabclass is a collection of slabs of fixed size specified by
 * --slab-size. A single slab is a collection of contiguous, equal sized
 * item chunks of a given size specified by the profile array
 */
static rstatus_i
_slab_slabclass_setup(void)
{
    uint8_t id;      /* slabclass id */

    ASSERT(profile_last_id <= SLABCLASS_MAX_ID);

    for (id = SLABCLASS_MIN_ID; id <= profile_last_id; id++) {
        struct slabclass *p; /* slabclass */
        uint32_t nitem;      /* # item per slabclass */
        size_t item_sz;      /* item size */

        nitem = slab_capacity() / profile[id];

        if (nitem == 0) {
            log_error("Invalid slab class size %u; too large to fit in slab!",
                    profile[id]);
            return CC_ERROR;
        }

        item_sz = profile[id];
        p = &slabclass[id];

        p->nitem = nitem;
        p->size = item_sz;

        /* chunk_size is static */
        perslab[id] = (perslab_metrics_st){PERSLAB_METRIC(METRIC_INIT)};
        UPDATE_VAL(&perslab[id], chunk_size, item_sz);

        p->nfree_itemq = 0;
        SLIST_INIT(&p->free_itemq);

        p->nfree_item = 0;
        p->next_item_in_slab = NULL;
    }

    return CC_OK;
}
Example #5
0
File: slab.c Project: huayl/pelikan
static rstatus_i
_slab_profile_setup(char *profile_str)
{
    int i;

    /* TODO(yao): check alignment (with machine word length) in the user config,
     * reject ones that don't align
     */
    if (profile_str != NULL) {
        /* slab profile specified */
        char *profile_entry;

        i = SLABCLASS_MIN_ID - 1;

        do {
            /*TODO(yao): strsep alters the original slab profile string, which
             * is probably not desirable (we don't want to modify options once
             * they are loaded. Do another memcpy to some local variable.
             */
            profile_entry = strsep(&profile_str, " \n\r\t");
            profile[++i] = atol(profile_entry);
            if (profile[i] <= profile[i - 1]) {
                log_error("Invalid setup profile configuration provided");
                return CC_ERROR;
            }
        } while (profile_str != NULL);

        profile_last_id = i;
    } else {
        /* generate slab profile using chunk size, slab size, and factor */
        size_t nbyte, nitem, linear_nitem;

        if (item_min <= ITEM_HDR_SIZE) {
            log_error("invalid min chunk size - too small for item overhead");
            return CC_ERROR;
        }

        if (item_max + SLAB_HDR_SIZE > slab_size) {
            log_error("invalid max chunk size - too large to fit in one slab");
            return CC_ERROR;
        }

        if (item_min > item_max) {
            log_error("Could not setup slab profile; invalid min/max chunk size");
            return CC_ERROR;
        }

        if (item_growth <= 1.0) {
            log_error("Could not setup slab profile; invalid growth factor");
            return CC_ERROR;
        }

        /*
         * Slab profile is determined as follows:
         *
         * Exponential growth of item size based on gf^n, from which we determine
         * the # items that can fit in the slab. At the point that the # items
         * change is <= 1, we form each slab profile entry as 1 item less than
         * the last until we hit 1 item.
         *
         * Example (assuming max chunk size == slab size):
         *
         * Suppose gf == 1.2, so we determine 1.2 * x >= x + 1 --> x >= 5
         * Thus, once we hit nitem == 5, we reduce nitem linearly by 1 until we
         * reach nitem == 1:
         *
         * Exponential growth while nitem increase still > 1
         * +-----------------------------------------------------------+
         * |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
         * +-----------------------------------------------------------+
         *
         * +-----------------------------------------------------------+
         * |    |    |    |    |    |    |    |    |    |    |    |    |
         * +-----------------------------------------------------------+
         *
         * +-----------------------------------------------------------+
         * |     |     |     |     |     |     |     |     |     |     |
         * +-----------------------------------------------------------+
         *
         *
         *                               .
         *                               .
         *                               .
         *
         *
         * Transition to linear growth
         * +-----------------------------------------------------------+
         * |              |              |              |              |
         * +-----------------------------------------------------------+
         *
         * +-----------------------------------------------------------+
         * |                   |                   |                   |
         * +-----------------------------------------------------------+
         *
         * +-----------------------------------------------------------+
         * |                             |                             |
         * +-----------------------------------------------------------+
         *
         * +-----------------------------------------------------------+
         * |                                                           |
         * +-----------------------------------------------------------+
         */

        linear_nitem = 1.0 / (item_growth - 1.0);
        i = SLABCLASS_MIN_ID;
        nitem = slab_capacity() / (CC_ALIGN(item_min, CC_ALIGNMENT));
        nbyte = slab_capacity() / nitem;

        /* exponential growth phase */
        while (nbyte <= item_max && nitem > linear_nitem) {
            if (i > SLABCLASS_MAX_ID) {
                log_error("Slab profile improperly configured - max chunk size "
                          "too large or growth factor too small");
                return CC_ERROR;
            }

            if (profile[i - 1] == nbyte) {
                nbyte += CC_ALIGNMENT;
            }

            profile[i++] = nbyte;
            nitem = slab_capacity() / nbyte / item_growth;
            nbyte = SLAB_ALIGN_DOWN(slab_capacity() / nitem, CC_ALIGNMENT);
        }

        /* linear growth phase */
        nitem = linear_nitem;
        nbyte = SLAB_ALIGN_DOWN(slab_capacity() / nitem, CC_ALIGNMENT);
        while (nbyte <= item_max && nitem > 0) {
            if (i > SLABCLASS_MAX_ID) {
                log_error("Slab profile improperly configured - max chunk size "
                          "too large or growth factor too small");
                return CC_ERROR;
            }
            profile[i++] = nbyte;
            if (--nitem > 0) {
                nbyte = SLAB_ALIGN_DOWN(slab_capacity() / nitem, CC_ALIGNMENT);
            }
        }

        profile_last_id = i - 1;
    }

    log_verb("setup slab profile profile_last_id: %u", profile_last_id);
    log_verb("slab profile:");

    for (i = SLABCLASS_MIN_ID; i <= profile_last_id; ++i) {
        log_verb("%u", profile[i]);
    }

    return CC_OK;
}