apache / brpc

brpc is an Industrial-grade RPC framework using C++ Language, which is often used in high performance system such as Search, Storage, Machine learning, Advertisement, Recommendation etc. "brpc" means "better RPC".

Home Page:https://brpc.apache.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[discuss]iobuf 什么场景下会引用多个block

cmdmspaint opened this issue · comments

commented

问题描述的不是很清晰,建议补充下更为详细的描述,或者举个例子。

在实际使用iobuf 的append方法时发现 iobuf的backing_block_num()方法的值 一直只有1个 所以有点好奇什么场景需要多个block的引用

IOBuf引用的block来自TLS,在同一个worker线程上一直append的话,数据长度超过block才会引用另一个block。如果每次append都在不同的worker线程上,应该就会引用多个block了。

或者,append其他IOBuf(没有引用相同的block),应该也会引用多个block了。

数据长度超过block才会引用另一个block中,提到的block长度是DEFAULT_BLOCK_SIZE的值吗。我尝试过1k~5M范围的数据,都是引用的一个blockref。

brpc/src/butil/iobuf.cpp

Lines 341 to 356 in 7a8df46

inline IOBuf::Block* create_block(const size_t block_size) {
if (block_size > 0xFFFFFFFFULL) {
LOG(FATAL) << "block_size=" << block_size << " is too large";
return NULL;
}
char* mem = (char*)iobuf::blockmem_allocate(block_size);
if (mem == NULL) {
return NULL;
}
return new (mem) IOBuf::Block(mem + sizeof(IOBuf::Block),
block_size - sizeof(IOBuf::Block));
}
inline IOBuf::Block* create_block() {
return create_block(IOBuf::DEFAULT_BLOCK_SIZE);
}

实际上容量是DEFAULT_BLOCK_SIZE - sizeof(Block)。

我尝试过1k~5M范围的数据,都是引用的一个blockref。

不可能吧,Block最大不超过8K。

butil::IOBuf buf;
std::string str(1024 * 8, '1');
buf.append(str);
LOG(INFO) << buf.backing_block_num();

简单写了一个demo,输出是2。

好的 了解。我具体使用的接口是append_user_data,我尝试一下。

append_user_data的block的容量是传进来的data大小,取决于调用方。

使用append_user_data接口时,会有block达到上限引用其他block的case吗。我理解这种取决于调用方的话,一个worker线程append的时候是用一个block承接所有的data?

使用append_user_data接口时,会有block达到上限引用其他block的case吗

没有

我理解这种取决于调用方的话,一个worker线程append的时候是用一个block承接所有的data?

是的,append_user_data不会用TLS上的block,只是直接new一个Block对象,接管data这块内存。

brpc/src/butil/iobuf.cpp

Lines 1261 to 1285 in 7a8df46

int IOBuf::append_user_data_with_meta(void* data,
size_t size,
std::function<void(void*)> deleter,
uint64_t meta) {
if (size > 0xFFFFFFFFULL - 100) {
LOG(FATAL) << "data_size=" << size << " is too large";
return -1;
}
if (!deleter) {
deleter = ::free;
}
if (!size) {
deleter(data);
return 0;
}
char* mem = (char*)malloc(sizeof(IOBuf::Block) + sizeof(UserDataExtension));
if (mem == NULL) {
return -1;
}
IOBuf::Block* b = new (mem) IOBuf::Block((char*)data, size, std::move(deleter));
b->u.data_meta = meta;
const IOBuf::BlockRef r = { 0, b->cap, b };
_move_back_ref(r);
return 0;
}

好的 理解了。感谢