关于http解析部分的一些疑惑
predatorbigbear opened this issue · 6 comments
predatorbigbear commented
Barenboim commented
你好。这个地方进一步优化的话,是可以使用原来的空间保存数据,哪怕加上‘\0'破坏原始掉数据都没有什么问题,这样可以减少一些malloc和free。但同时我们还支持set header,set version这样的操作,所以如果是用户传进来的数据,那也不可避免的要重新分配空间,然后内部做标记来决定要不要free。
目前这个parser肯定没有做到极致,但我们目前各种性能测试里并没有发现parser占用太多CPU,不太可能是性能瓶颈。你可以结合实际应用试一下。
predatorbigbear commented
你好,谢谢你的回复。workflow的框架很了不起,尤其是mysql解析的地方确实有了自解析之后可以做到真正的异步,对于上面提到的问题,长期以来,业界的做法是对于http消息,超出读取buffer之后进行append再进行解析,我思考过之后采用的办法是对于超出长度的消息另外开辟一块新的读取buffer,这样做的好处是每一个读取buffer中间的完整数据段可以用指针指向,高效保存,而一个vector<pair<char*,char*>>则对跨界的指针位置进行保存,当解析完整时仅对中间位置的一小部分数据进行拼接即可。这里提供一个自己开发中的尝试用STL直接做到高并发的服务器部分代码,至于malloc和free,我个人做了一个特殊的内存池,使用时直接取指针使用即可。里面用到ASIO
…------------------ 原始邮件 ------------------
发件人: "sogou/workflow" <notifications@github.com>;
发送时间: 2021年2月26日(星期五) 下午3:57
收件人: "sogou/workflow"<workflow@noreply.github.com>;
抄送: "1075716088"<1075716088@qq.com>;"Author"<author@noreply.github.com>;
主题: Re: [sogou/workflow] 关于http解析部分的一些疑惑 (#267)
你好。这个地方进一步优化的话,是可以使用原来的空间保存数据,哪怕加上‘\0'破坏原始掉数据都没有什么问题,这样可以减少一些malloc和free。但同时我们还支持set header,set version这样的操作,所以如果是用户传进来的数据,那也不可避免的要重新分配空间,然后内部做标记来决定要不要free。
目前这个parser肯定没有做到极致,但我们目前各种性能测试里并没有发现parser占用太多CPU,不太可能是性能瓶颈。你可以结合实际应用试一下。
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Barenboim commented
可以贴一下您的代码我们参考一下。parser这块我们尽量做成ansi c的,优化的空间肯定有,主要还是减少malloc和free,内存copy可能影响反而不大,毕竟header就那么点字节。你可以整体跑一下我们的框架看看性能问题。
predatorbigbear commented
工程采用VS 远程开发 我的linux环境是gcc10.0以上 boost1.75 C++17
代码还在完善修改中,有很多遗留下来的历史代码待后期清理,mysql部分后面选定multiSQLREADSW作为读取部分,
redis部分后期选定multiREDISREAD作为读取部分。
另以上两者再加一个写入类做读写分离,
初步做了一个对象池(早期设计时将socket与处理类分开了,后期整合),对象池设计成不可扩容,在连接数满了对象池取不出对象时停止监听,有对象放回时恢复监听,
以保证在大量连接时的服务质量以及不会被冲垮。
从设计之初就考虑到健壮性的问题,因此做了大量异常处理以及静态字符串,即使某些处理实例因为内存不足以处理本次业务也无妨,仍然可以返回响应,毕竟不能因为
几个人的问题影响一大群用户。
为了达到高性能,从http解析开始,到插入读取命令,均采用指针或string_view,仅仅在生成命令时才一次性生成(发生一次拷贝)
返回数据库结果 redis结果也同样如此,配合一种指针级生成json的算法与STL算法 使得业务处理过程中可以以逼近完全指针化方式处理,
在返回http消息时,首先计算好整块http消息长度(考虑上需要转换特殊字符的长度TRANSFORM(用C++17 if constexpr控制) ),然后定位到body开始处进行真正拷贝与转换,然后获取
body长度,返回前面写下http前缀字段
SQL部分做了一个自动释放MYSQL_RES*的机制,在生成命令时会进行检查插入异步释放队列,并且做隐式流水线
redis 则预先申请一块足够大的空间(预设每次结果最大长度 * 每次请求最大次数 *对象池对象总数),并且做隐式流水线 以做到真正0拷贝,这样即使采用STL也能有惊人的性能实现高并发
测试场景为进行一次http解析,redis(redis和服务程序装在同一机器上)进行一次查询,获取一个string(hello_WORLD),返回http消息,其中body以json格式返回,
采用了3台i5四核的机器运行测试程序,同时各发送200万次请求
在香港腾讯云2核4g机器上公网测试到的结果除以cpu比率之后约为单核2万qps
目前可以先进行接口10测试redis GET,(为了更快,post接口直接用数字命名)
我先完成我的工程再来测试workflow
…------------------ 原始邮件 ------------------
发件人: "sogou/workflow" <notifications@github.com>;
发送时间: 2021年2月26日(星期五) 下午5:02
收件人: "sogou/workflow"<workflow@noreply.github.com>;
抄送: "1075716088"<1075716088@qq.com>;"Author"<author@noreply.github.com>;
主题: Re: [sogou/workflow] 关于http解析部分的一些疑惑 (#267)
可以贴一下您的代码我们参考一下。parser这块我们尽量做成ansi c的,优化的空间肯定有,主要还是减少malloc和free,内存copy可能影响反而不大,毕竟header就那么点字节。你可以整体跑一下我们的框架看看性能问题。
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.
Barenboim commented
嗯嗯,您描述的使用场景是比较适合用我们的框架来实现的,之后希望能试一试。你也可以先用workflow写一点简单的中转服务器体会一下用法。可以参考http_proxy的示例。如果需要并发访问下游就简单创建一个parallel任务就可以了,可以实现真正的全异步。
predatorbigbear commented
好的,主要是应用实战一下,自己实现后面跳槽时用 https://gitee.com/deng_dan_jun/function_finishing/blob/master/%E5%B8%B8%E8%A7%81%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8FC++%E5%AE%9E%E7%8E%B0%E5%87%BD%E6%95%B0 这里有些我写的简单正则的高效实现,可以看看
…------------------ 原始邮件 ------------------
发件人: "xiehan"<notifications@github.com>;
发送时间: 2021年2月26日(星期五) 晚上8:33
收件人: "sogou/workflow"<workflow@noreply.github.com>;
抄送: "1075716088"<1075716088@qq.com>; "Author"<author@noreply.github.com>;
主题: Re: [sogou/workflow] 关于http解析部分的一些疑惑 (#267)
嗯嗯,您描述的使用场景是比较适合用我们的框架来实现的,之后希望能试一试。你也可以先用workflow写一点简单的中转服务器体会一下用法。可以参考http_proxy的示例。如果需要并发访问下游就简单创建一个parallel任务就可以了,可以实现真正的全异步。
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or unsubscribe.