/** * Grow @str for @n new chunks. * New branches of the string tree are created on 2nd level only, * i.e. there is no possibility to grow number of chunks of duplicate string. * Pass pointer to one of the duplicates to do so. * @return pointer to the first of newly added chunk. * * TODO do we need exponential growing? */ static TfwStr * __str_grow_tree(TfwPool *pool, TfwStr *str, unsigned int flag, int n) { if (str->flags & flag) { unsigned int l; void *p; if (unlikely(TFW_STR_CHUNKN_LIM(str))) { TFW_WARN("Reaching chunks hard limit\n"); return NULL; } l = TFW_STR_CHUNKN(str) * sizeof(TfwStr); p = tfw_pool_realloc(pool, str->ptr, l, l + n * sizeof(TfwStr)); if (!p) return NULL; str->ptr = p; TFW_STR_CHUNKN_ADD(str, n); } else { TfwStr *a = tfw_pool_alloc(pool, (n + 1) * sizeof(TfwStr)); if (!a) return NULL; a[0] = *str; str->ptr = a; __TFW_STR_CHUNKN_SET(str, n + 1); } str = (TfwStr *)str->ptr + TFW_STR_CHUNKN(str) - n; memset(str, 0, sizeof(TfwStr) * n); return str; }
static TfwStr * alloc_str(void) { TfwStr *s; s = tfw_pool_alloc(str_pool, sizeof(*s)); BUG_ON(!s); TFW_STR_INIT(s); return s; }
static TfwRrPtrSet * alloc_srv_set(TfwPool *pool, size_t max_srv_n) { size_t size = tfw_ptrset_size(max_srv_n); TfwRrPtrSet *ptrset = tfw_pool_alloc(pool, size); if (!ptrset) { ERR("Can't allocate memory from pool: %p\n", pool); return NULL; } tfw_ptrset_init(ptrset, max_srv_n); return ptrset; }
TfwHttpMsg * tfw_http_msg_alloc(int type) { TfwHttpMsg *hm = (type & Conn_Clnt) ? (TfwHttpMsg *)tfw_pool_new(TfwHttpReq, TFW_POOL_ZERO) : (TfwHttpMsg *)tfw_pool_new(TfwHttpResp, TFW_POOL_ZERO); if (!hm) return NULL; ss_skb_queue_head_init(&hm->msg.skb_list); hm->h_tbl = (TfwHttpHdrTbl *)tfw_pool_alloc(hm->pool, TFW_HHTBL_SZ(1)); hm->h_tbl->size = __HHTBL_SZ(1); hm->h_tbl->off = TFW_HTTP_HDR_RAW; memset(hm->h_tbl->tbl, 0, __HHTBL_SZ(1) * sizeof(TfwHttpHdr)); INIT_LIST_HEAD(&hm->msg.msg_list); return hm; }
void * tfw_pool_realloc(TfwPool *p, void *ptr, size_t old_n, size_t new_n) { void *a; BUG_ON(new_n < old_n); old_n = TFW_POOL_ALIGN_SZ(old_n); new_n = TFW_POOL_ALIGN_SZ(new_n); if ((char *)ptr + old_n == (char *)TFW_POOL_CHUNK_END(p) && p->off - old_n + new_n <= TFW_POOL_CHUNK_SZ(p)) { p->off += new_n - old_n; return ptr; } a = tfw_pool_alloc(p, new_n); if (likely(a)) memcpy(a, ptr, old_n); return a; }
int __init pool_benchmark(void) { long i, j, t0, t1; ngx_pool_t *np; TfwPool *tp; printk(KERN_ERR "object sizes: Small - %lu, Big - %lu Huge - %lu\n", sizeof(Small), sizeof(Big), sizeof(Huge)); t0 = jiffies; for (i = 0; i < N_ALLOC; ++i) { p_arr[i] = (void *)__get_free_pages(GFP_KERNEL, 0); touch_obj(p_arr[i]); } for (i = 0; i < N_ALLOC; ++i) free_pages((unsigned long)p_arr[i], 0); t1 = jiffies; printk(KERN_ERR "alloc & free: %ldms\n", t1 - t0); /*****************************************************************/ np = ngx_create_pool(PAGE_SIZE); BUG_ON(!np); t0 = jiffies; for (i = 0; i < N; ++i) { Small *o = (Small *)ngx_palloc(np, sizeof(Small)); touch_obj(o); } t1 = jiffies; ngx_destroy_pool(np); /* HZ = 1000 for my kernel. */ printk(KERN_ERR "ngx_pool (Small): %ldms\n", t1 - t0); np = ngx_create_pool(PAGE_SIZE); BUG_ON(!np); t0 = jiffies; for (i = 0; i < N * sizeof(Small) / sizeof(Big); ++i) { Big *o = (Big *)ngx_palloc(np, sizeof(Big)); touch_obj(o); } t1 = jiffies; ngx_destroy_pool(np); printk(KERN_ERR "ngx_pool (Big): %ldms\n", t1 - t0); np = ngx_create_pool(PAGE_SIZE); BUG_ON(!np); t0 = jiffies; for (i = 0; i < N; ++i) { if (unlikely(!(i & 0xfff))) { Huge *o = (Huge *)ngx_palloc(np, sizeof(*o)); touch_obj(o); if (!(i & 1)) ngx_pfree(np, o); } else if (unlikely(!(i & 3))) { Big *o = (Big *)ngx_palloc(np, sizeof(*o)); touch_obj(o); } else { Small *o = (Small *)ngx_palloc(np, sizeof(*o)); touch_obj(o); } } t1 = jiffies; ngx_destroy_pool(np); printk(KERN_ERR "ngx_pool w/ free (Mix): %ldms\n", t1 - t0); t0 = jiffies; for (i = 0; i < N / 100; ++i) { np = ngx_create_pool(PAGE_SIZE); for (j = 0; j < 100; ++j) { if (unlikely(!(i & 3))) { Big *o = (Big *)ngx_palloc(np, sizeof(*o)); touch_obj(o); } else { Small *o; o = (Small *)ngx_palloc(np, sizeof(*o)); touch_obj(o); } } ngx_destroy_pool(np); } t1 = jiffies; printk(KERN_ERR "ngx_pool cr. & destr.: %ldms\n", t1 - t0); /*****************************************************************/ tp = __tfw_pool_new(0); BUG_ON(!tp); t0 = jiffies; for (i = 0; i < N; ++i) { Small *o = (Small *)tfw_pool_alloc(tp, sizeof(Small)); touch_obj(o); } t1 = jiffies; tfw_pool_destroy(tp); printk(KERN_ERR "tfw_pool (Small): %ldms\n", t1 - t0); tp = __tfw_pool_new(0); BUG_ON(!tp); t0 = jiffies; for (i = 0; i < N; ++i) { Small *o = (Small *)tfw_pool_alloc(tp, sizeof(Small)); touch_obj(o); if (unlikely(!(i & 3))) tfw_pool_free(tp, o, sizeof(Small)); } t1 = jiffies; tfw_pool_destroy(tp); printk(KERN_ERR "tfw_pool w/ free (Small): %ldms\n", t1 - t0); tp = __tfw_pool_new(0); BUG_ON(!tp); t0 = jiffies; for (i = 0; i < N * sizeof(Small) / sizeof(Big); ++i) { Big *o = (Big *)tfw_pool_alloc(tp, sizeof(Big)); touch_obj(o); } t1 = jiffies; tfw_pool_destroy(tp); printk(KERN_ERR "tfw_pool (Big): %ldms\n", t1 - t0); tp = __tfw_pool_new(0); BUG_ON(!tp); t0 = jiffies; for (i = 0; i < N * sizeof(Small) / sizeof(Big); ++i) { Big *o = (Big *)tfw_pool_alloc(tp, sizeof(Big)); touch_obj(o); if (unlikely(!(i & 3))) tfw_pool_free(tp, o, sizeof(Big)); } t1 = jiffies; tfw_pool_destroy(tp); printk(KERN_ERR "tfw_pool w/ free (Big): %ldms\n", t1 - t0); tp = __tfw_pool_new(0); BUG_ON(!tp); t0 = jiffies; for (i = 0; i < N; ++i) { if (unlikely(!(i & 0xfff))) { Huge *o = (Huge *)tfw_pool_alloc(tp, sizeof(*o)); touch_obj(o); if (!(i & 1)) tfw_pool_free(tp, o, sizeof(*o)); } else if (unlikely(!(i & 3))) { Big *o = (Big *)tfw_pool_alloc(tp, sizeof(*o)); touch_obj(o); if (!(i & 1)) tfw_pool_free(tp, o, sizeof(*o)); } else { Small *o = (Small *)tfw_pool_alloc(tp, sizeof(*o)); touch_obj(o); } } t1 = jiffies; tfw_pool_destroy(tp); printk(KERN_ERR "tfw_pool w/ free (Mix): %ldms\n", t1 - t0); t0 = jiffies; for (i = 0; i < N / 100; ++i) { tp = __tfw_pool_new(0); for (j = 0; j < 100; ++j) { if (unlikely(!(i & 3))) { Big *o = (Big *)tfw_pool_alloc(tp, sizeof(*o)); touch_obj(o); } else { Small *o; o = (Small *)tfw_pool_alloc(tp, sizeof(*o)); touch_obj(o); } } tfw_pool_destroy(tp); } t1 = jiffies; printk(KERN_ERR "tfw_pool cr. & destr.: %ldms\n", t1 - t0); return 0; }