WangCong
WangCong
@wenweihu86 这个功能有计划支持么,或者可以提供下思路该如何实现么
> 可以看看IOBuf的append_user_data函数 我在数据发送端通过append_user_data避免了发送端的数据拷贝,但是在接收端拿到的就是IOBuf,从网络拿到的数据放到IOBuf这一步已经是不连续的内存了,这里接收端能保证接收到连续的内存来避免拷贝吗
> > > 可以看看IOBuf的append_user_data函数 > > > > > > 我在数据发送端通过append_user_data避免了发送端的数据拷贝,但是在接收端拿到的就是IOBuf,从网络拿到的数据放到IOBuf这一步已经是不连续的内存了,这里接收端能保证接收到连续的内存来避免拷贝吗 > > 如果要接收端能拿到连续的buf,意味着接收端在接收body之前,需要从协议头里获取body的长度,然后分配出相应长度的内存,再用这段内存来接收网络数据。这个逻辑应该是协议相关的,需要修改协议的实现,仅仅改IOBuf是不够的 请问一下这一块是需要在哪里进行修改呢,我理解这一层在自定义协议是没法完成的,因为自定义协议的接口都是基于IOBuf,理论上是否是需要修改OnNewMessages这个函数的实现,例如申请一块连续内存,然后通过append_user_data保证接收端接收到的内存是连续的?这个问题的背景是因为在高性能计算的场景下,向量化的计算需要保证内存是连续的,现在其实多了一层内存拷贝的开销,这在大数据量的场景下其实有比较大的性能损耗
> IOBufAsZeroCopyOutputStream可以满足需求吗 不太能满足,IOBufAsZeroCopyOutputStream只是在逻辑上wrap了一下,但是其实物理内存还是不连续的
> > 请问一下这一块是需要在哪里进行修改呢,我理解这一层在自定义协议是没法完成的,因为自定义协议的接口都是基于IOBuf,理论上是否是需要修改OnNewMessages这个函数的实现,例如申请一块连续内存,然后通过append_user_data保证接收端接收到的内存是连续的?这个问题的背景是因为在高性能计算的场景下,向量化的计算需要保证内存是连续的,现在其实多了一层内存拷贝的开销,这在大数据量的场景下其实有比较大的性能损耗 > > 可能需要大改,包括IOBuf、Socket、InputMessenger、协议 这里还有个麻烦就是brpc支持多协议,所以一开始不知道要准备多大的buf,只能先随便读一段数据再尝试逐个协议解析,这时候可能已经读进来一部分body了,那么后续再读就不连续了 协议解析的时候需要的应该只是一小部分body吧,例如brpc的协议其实只需要前12个字节就可以确认了,后续的内存可以先申请,然后把前12个字节的数据重新set一下就可以了吧,不知道这个理解是否正确?
> @WingsGo 请问下你这里大数据量指的是单个rpc payload很大还是qps很高. 单个RPC的payload比较大
@chenzhangyi @wwbmmm 我理解对于baidu_rpc协议来说,meta和payload的length是在协议头就已经确定好了的,这样可以修改append_from_file_descriptor,在从socket的fd读取数据的时候,将allocate内存的方法提供给用户,然后通过append_user_data就可以在recever端减少这一次拷贝了吧?我可以提一个PR来实现一下,不知道这样的方案是否可行?
> > @chenzhangyi @wwbmmm 我理解对于baidu_rpc协议来说,meta和payload的length是在协议头就已经确定好了的,这样可以修改append_from_file_descriptor,在从socket的fd读取数据的时候,将allocate内存的方法提供给用户,然后通过append_user_data就可以在recever端减少这一次拷贝了吧?我可以提一个PR来实现一下,不知道这样的方案是否可行? > > 可以考虑给iobuf加个reserve_continuous_buffer(int size)方法,然后由协议来控制预留buffer的大小 那也就是说可以这么实现?在协议层直接预先分配内存,后续从fd读取的数据可以保证不会超过这个大小,这样就能保证block的数量始终保持为1,然后在读取数据的时候通过fetch方法来避免拷贝,我理解这样的改动是最小的? else if (source->length() < sizeof(header_buf) + body_size) { // 预先分配size大小的内存,并作为一个block放入source中,然后将source->length()的内容拷贝进这个block里 source-> reserve_continuous_buffer(sizeof(header_buf) + body_size) return MakeParseError(PARSE_ERROR_NOT_ENOUGH_DATA); }