libevent的evbuffer之减少内存拷贝

libevent的evbuffer之减少内存拷贝

evbuffer是块状数组的数据结构,既是一块块连续的内存链接起来的,evbuffer有许多有用的接口,这里只想对可以减少内存拷贝的接口做详细记录。 1.int evbuffer_reserve_space(struct evbuffer *buf, ev_ssize_t size, struct evbuffer_iovec *vec, int n_vecs); int evbuffer_commit_space(struct evbuffer *buf, struct evbuffer_iovec *vec, int n_vecs); evbuffer的其他接口大部分都是把要添加的数据从用户给的buffer拷到自己的buffer,但其实是可以避免这一次拷贝的。evbuffer_reserve_space从evbuffer中保留出一片内存,用户在这片内存上可以直接写数据,待到写完,调用evbuffer_commit_space此时这片内存才真正被“占用”,例如对于bufferevent的output evbuffer,commit后就是告诉要发送数据了。用法可以简化为如下: /* some codes like OutputBuf = bufferevent_get_output(bufev); */ struct evbuffer_iovec v; /* Reserve 2048 bytes */ n = evbuffer_reserve_space(OutputBuf, 2048, &v, 1); if (n <= 0) /* reserve error */ return; assert(v.iov_len == 2048); /* Process data in reserved buf */ char *DatBuf = v.iov_base; for (i = 0; i < 2048; i ++) DatBuf[i] = gen_data(i); /* Send datas */ v.iov_len = data_len_to_send; n = evbuffer_commit_space(OutputBuf, &v, 1); if (n < 0) return; /* commit error */ 2.typedef void (*evbuffer_ref_cleanup_cb)(const void *data, size_t datalen, void *extra); int evbuffer_add_reference(struct evbuffer *outbuf, const void *data, size_t datlen, evbuffer_ref_cleanup_cb cleanupfn, void *extra); 这个接口是官方文档推荐在避免内存拷贝时使用的接口,在evbuffer中直接挂接用户提供的buffer,该buffer由用户分配,当然也该由用户释放,evbuffer_ref_cleanup_cb,在evbuffer_drain时会被回调,告诉用户你的这块内存我不用了,你释放吧。这个接口可以配合用户的自定义内存池来使用,简单用法示例如下: /* some codes like OutputBuf = bufferevent_get_output(bufev); */ ... char *DatBuf = mem_pool_alloc(2048); /* Process data in alloced buf */ char *DatBuf = v.iov_base; for (i = 0; i < 2048; i ++) DatBuf[i] = gen_data(i); evbuffer_add_reference(OutputBuf, DatBuf, 2048, cleanupfn, NULL); ... /* cleanupfn like this */ void cleanupfn(const void *data, size_t datalen, void *extra) { mem_pool_free(data, datalen); }
原文地址:https://www.cnblogs.com/persistentsnail/p/3294850.html