??xml version="1.0" encoding="utf-8" standalone="yes"?>99久久99久久精品国产片果冻,精品久久久无码人妻中文字幕,久久久久无码精品国产apphttp://www.shnenglu.com/oldworm/zh-cnTue, 06 May 2025 18:27:48 GMTTue, 06 May 2025 18:27:48 GMT60Windows下两Uiocp实现的差?/title><link>http://www.shnenglu.com/oldworm/archive/2011/02/01/139662.html</link><dc:creator>袁斌</dc:creator><author>袁斌</author><pubDate>Tue, 01 Feb 2011 02:48:00 GMT</pubDate><guid>http://www.shnenglu.com/oldworm/archive/2011/02/01/139662.html</guid><wfw:comment>http://www.shnenglu.com/oldworm/comments/139662.html</wfw:comment><comments>http://www.shnenglu.com/oldworm/archive/2011/02/01/139662.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/oldworm/comments/commentRss/139662.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/oldworm/services/trackbacks/139662.html</trackback:ping><description><![CDATA[ <p class="MsoNormal"><span lang="EN-US">Windows</span><span style="font-family: 宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-font-family: 宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin">下两U?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family: Calibri;mso-hansi-theme-font:minor-latin">实现的差?/span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">之前几天说过Q因为经?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">实现Q以下简U经典实玎ͼ多个</span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程l定在一?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">上,q样内部理?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">队列的处理,内部军_是不是需要线E切换,我上ơ修改的一个版本(以下U实?/span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">Q,用了多个</span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程Q每?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">队列仅绑定一?/span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程Q一l用户共享一?/span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程Q这和经典的多线E?/span><span lang="EN-US">epoll</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">模型的做法是很相似的Q这h?/span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程是可以独立控制了Q但理论上这U做法没有发?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">自动理U程切换的优势,昨晚没事用这两种实现分别做了?/span><span lang="EN-US">echoserver</span><span style="font-family:宋体;mso-ascii-font-family: Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">试了一下,q两套实C码仅</span><span lang="EN-US">40</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">行左右不同,其他完全一P效果真的是差很多Q测试仅用一个进E模拟了</span><span lang="EN-US">4000</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">个客LQ每U?/span><span lang="EN-US">1</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">个包Q先看实?/span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">的,</span><span lang="EN-US">cpu</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">?/span><span lang="EN-US">14%</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">Q?/span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">?/span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程Q?/span><span lang="EN-US">1</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">?/span><span lang="EN-US">accept</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程Q?/span><span lang="EN-US">1</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">个主U程Q其他线E都没干z闲|?/span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0" style="border-collapse: collapse; border-width: initial; border-color: initial; "> <tbody><tr style="mso-yfti-irow:0;mso-yfti-firstrow:yes"> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Cpu</span></p> </td> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Memory</span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Threads</span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">handles</span></p> </td> </tr> <tr style="mso-yfti-irow:1;mso-yfti-lastrow:yes"> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">14</span></p> </td> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">40088k</span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">8</span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">4236</span></p> </td> </tr> </tbody></table> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><o:p></o:p></span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">再看l典实现Q?/span><span lang="EN-US">cpu</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">几乎一直是</span><span lang="EN-US">0%</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">Q?/span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">?/span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程Q?/span><span lang="EN-US">accept</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">也是?/span><span lang="EN-US">io</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">U程里面处理Q其他跟实现</span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">一P试客户端也一栗?/span></p> <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0" style="border-collapse: collapse; border-width: initial; border-color: initial; "> <tbody><tr style="mso-yfti-irow:0;mso-yfti-firstrow:yes"> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Cpu<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Memory<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Threads<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">handles<o:p></o:p></span></p> </td> </tr> <tr style="mso-yfti-irow:1;mso-yfti-lastrow:yes"> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">0<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">39244k<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">7<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">4336<o:p></o:p></span></p> </td> </tr> </tbody></table> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">说实话,在测试之前我也没惛_有这么大的差距,l典实现是</span><span lang="EN-US">1.2w</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">个连接连上来q是q样Q就是内存占用多一点:</span></p> <table class="MsoTableGrid" border="1" cellspacing="0" cellpadding="0" style="border-collapse: collapse; border-width: initial; border-color: initial; "> <tbody><tr style="mso-yfti-irow:0;mso-yfti-firstrow:yes"> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Cpu<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Memory<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">Threads<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">handles<o:p></o:p></span></p> </td> </tr> <tr style="mso-yfti-irow:1;mso-yfti-lastrow:yes"> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">0<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.5pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">112068k<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">7<o:p></o:p></span></p> </td> <td width="142" valign="top" style="width: 106.55pt; padding-top: 0cm; padding-right: 5.4pt; padding-bottom: 0cm; padding-left: 5.4pt; "> <p class="MsoNormal"><span lang="EN-US">12280<o:p></o:p></span></p> </td> </tr> </tbody></table> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">习惯上L人喜Ƣ拿</span><span lang="EN-US">epoll</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">来对比,我到现在也没看到真正公^的对比,q是相对公q的也没见到Q因为在我看来,要对比硬件应该是一LQ?/span><span lang="EN-US">os</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">都应该是最新的Q最重要的是Q?/span><span lang="EN-US">server</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">端程序应该都是发挥了各自优势的,如果拿我q里的实?/span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">M?/span><span lang="EN-US">iocp</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">的水q_</span><span lang="EN-US">epoll</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">ҎQ势必造成?/span><span lang="EN-US">epoll</span><span style="font-family:宋体;mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin;mso-fareast-font-family:宋体;mso-fareast-theme-font: minor-fareast;mso-hansi-font-family:Calibri;mso-hansi-theme-font:minor-latin">差很多的l果Q然而这昄是不正确的?/span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US">epoll</span><span style="font-family:宋体; mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin;mso-fareast-font-family: 宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin">l典多线E模式实际实现和实现</span><span lang="EN-US">2</span><span style="font-family:宋体;mso-ascii-font-family:Calibri;mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体;mso-fareast-theme-font:minor-fareast;mso-hansi-font-family: Calibri;mso-hansi-theme-font:minor-latin">很相|理论上也有类似的U程切换问题Q不知道效率怎样?/span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p> <img src ="http://www.shnenglu.com/oldworm/aggbug/139662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/oldworm/" target="_blank">袁斌</a> 2011-02-01 10:48 <a href="http://www.shnenglu.com/oldworm/archive/2011/02/01/139662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>回调函数的常见实现方式及速度比较http://www.shnenglu.com/oldworm/archive/2011/01/30/139610.html袁斌袁斌Sun, 30 Jan 2011 03:19:00 GMThttp://www.shnenglu.com/oldworm/archive/2011/01/30/139610.htmlhttp://www.shnenglu.com/oldworm/comments/139610.htmlhttp://www.shnenglu.com/oldworm/archive/2011/01/30/139610.html#Feedback3http://www.shnenglu.com/oldworm/comments/commentRss/139610.htmlhttp://www.shnenglu.com/oldworm/services/trackbacks/139610.html回调函数的常见实现方式及速度比较

 

 

回调函数实在是用得太q泛Q回调函数又有多U实现方式,如:

1?span style="font:7.0pt "Times New Roman"">  静态函?/span>

2?span style="font:7.0pt "Times New Roman"">  虚函?/span>

3?span style="font:7.0pt "Times New Roman"">  函数对象

4?span style="font:7.0pt "Times New Roman"">  传统c函数Q通过一?/span>void *传递对象地址Q内部强制{?/span>

5?span style="font:7.0pt "Times New Roman"">  fastdelegate

6?span style="font:7.0pt "Times New Roman"">  Tr1::function + bind

7?span style="font:7.0pt "Times New Roman"">  Boost::Function + bind

基本上速度是按照由快到慢的序排列的,是

1 > 2 > 3 > 4 > 5 > 6 > 7

其实234速度很接q,有的时候函数对象效率更高一点,基本上越是高U的Ҏ使用h方便,但速度慢Q越是传l的Ҏ速度快Q呵呵,看来?/span>server端程序要l合考虑效率太新的东西还是要用啊,q是用传l的Ҏ比较靠谱一点,当然如果调用ơ数不多的地方,使用更方便的Ҏq是好一些,毕竟我们要综合权衡,而不能死板恪守教条?/span>

 

 



袁斌 2011-01-30 11:19 发表评论
]]>
一套网l框架的杯具http://www.shnenglu.com/oldworm/archive/2011/01/26/139352.html袁斌袁斌Wed, 26 Jan 2011 08:14:00 GMThttp://www.shnenglu.com/oldworm/archive/2011/01/26/139352.htmlhttp://www.shnenglu.com/oldworm/comments/139352.htmlhttp://www.shnenglu.com/oldworm/archive/2011/01/26/139352.html#Feedback1http://www.shnenglu.com/oldworm/comments/commentRss/139352.htmlhttp://www.shnenglu.com/oldworm/services/trackbacks/139352.html一套网l框架的杯具

之前设计了一套网l框Ӟ持箋改进了很多年Q用在很多目上,l合效率q行Q也很稳定,一直以来对q套东西信心满满QM为啥问题都好解决Q但最q就有个需求让我选择q是改了下这个框架?/span>

之前的框架是q样的,可以开一l?/span>N?/span>ioU程Q可以开一l?/span>N个同步线E(默认1个)Q可以开一l?/span>N个异步线E(默认1个)Q可以开一l?/span>N?/span>timerU程Q默?/span>1个)Q可以开一l?/span>N个异步线E(默认cpu个)Q每l可独立受控Q每l可支持自定义消息,可支?/span>timerQ一l?/span>N个如?/span>N大于1则无法直接给q组里面的特定线E发消息Q只能给一l发消息Q这个组里面会选择某个合适的U程处理q个消息Q这也是iocp高效和典型的用法了,但这也正是问题的l症所在?/span>

Linux下的多线E服务器更常见的做法跟这个不大相|一般都是将某些socket分配到某些线E?/span>epollQ分好之后就是固定的Q不再变化,?/span>Iocp?/span>socketl定Cl线E的做法不同Q由于某?/span>socket直接l定C某个U程Q所以有些问题就变得单了Q如同一个连接的在同一个线E内消息q行了同步,要跟ioU程l定U有化数据也单了Q而且每个U程可独立受控,所以很Ҏ实现一l?/span>io各自?/span>tlsQ线E局部存储)数据Q而我现在做的q套框架是q方面不好控了,其实也很难说q两U意义上的框架到底谁更优Q如用在web型应用上q种socket被一l?/span>ioU程理的模式很方便效率也高Q但我现在的需求需要某?/span>socket使用U程相关数据Q以避免数据之间的锁Q我用内存换旉Q由于在原来的框架上增逻辑难以实现可直接控?/span>ioU程的框架的Q所以花了一个晚上重新改写了一套框Ӟ在原?/span>iocpframe的基上派生了一l带2名称的类Q除替换cd之外只修改了几十行代码就做好了,ȝ来说q旉q是比较的。修改后ioU程一l,但独立受控,外部可对q组U程中的某一个直接发消息Q基本满了需求,现在要给每个ioU程l定U有数据q触发特定消息比之前单多了,而且l对无锁?/span>

 



袁斌 2011-01-26 16:14 发表评论
]]>
让后端服务器支持memcached协议http://www.shnenglu.com/oldworm/archive/2011/01/23/139168.html袁斌袁斌Sun, 23 Jan 2011 09:13:00 GMThttp://www.shnenglu.com/oldworm/archive/2011/01/23/139168.htmlhttp://www.shnenglu.com/oldworm/comments/139168.htmlhttp://www.shnenglu.com/oldworm/archive/2011/01/23/139168.html#Feedback1http://www.shnenglu.com/oldworm/comments/commentRss/139168.htmlhttp://www.shnenglu.com/oldworm/services/trackbacks/139168.html 

׃原先?/span>appserver功能不断增多Q最q又增了两个功能Q需要不断从后端memcached中提取数据ƈq行计算Q由于提取数据量大且频繁Q导致效率很低,_测了一下,获取数据和格式化{操作花?/span>90%以上的时_由此设想?/span>memcached改写或重写一个支?/span>memcached的服务器Q将计算功能?/span>memcached做到一P让获取数据的路径最短,也就最大限度减了数据传输和格式化{操作,是cM存储q程一样啦Q这部分可以考虑使用插g来实玎ͼ甚至可考虑使用脚本语言来实现?/span>

|上搜了一下,果然发现早有么干了,正所谓英雄所见啊Q呵c具体方法倒很多,自定?/span>key命名Q根据特D?/span>key?/span>get?/span>set?/span>replace上做Ҏ操作Q或者根据命令中?/span>flag{做Ҏ处理Q或者扩?/span>stat命o{,都是可以的,我们暂时p虑修改Ҏ的键值做Ҏ处理?/span>

要做一个完备的既支?/span>ascii命o又支?/span>binary命o的兼?/span>memcachedq是有一点点ȝ的,我暂时也没有太多需求,所以就仅支持了ascii命oQ其实也是考虑支持ascii的客L更多Q各U语a的支?/span>mc的客LC胜数Q但大多只支?/span>ascii命o。由于我之前Z试服务器框架效率,做过一个支?/span>ascii命o?/span>memcached兼容版本Q因此拿q来直接使用太方便了Q这个版本的实现其实很容易,如果有一个较好的框架代码的话基本上在一天之内可做完Q当然要做到很好可能需要多׃些时_我现在做的也不是特好Q要完全取代memcached使用q是有些差距Q主要是一些过期机制等没完全实玎ͼ虽然速度上比标准mc版本q要快一点,呵呵Q因为暂时的是不需要这些过期机Ӟ所以也没打这个版本实玎ͼ其他功能基本上都有?/span>

以后准备这?/span>memcached解码部分作ؓ一个单独的解析器,和支持其他协议一P换上q个解析那就支持mc协议了,q是很方便的Q以后有I是要做个支持binary协议的,以便可以更高效的解决问题?/span>

惛_server能支?/span>Memcached协议真是好啊Q客L基本只要用个libmemcached好了,多服务器分布Q容错,多䆾数据啥的都有现成的解x案,只要?/span>server做稳定了基?/span>ok了,对咱q种团队来说再合适不q了Q节省了很多开发维护成本啊Q现在内存这么便宜,部v几个点实在是?/span>easy的问题?/span>

 

 



袁斌 2011-01-23 17:13 发表评论
]]>
关于内存数据?/title><link>http://www.shnenglu.com/oldworm/archive/2011/01/21/139015.html</link><dc:creator>袁斌</dc:creator><author>袁斌</author><pubDate>Fri, 21 Jan 2011 05:37:00 GMT</pubDate><guid>http://www.shnenglu.com/oldworm/archive/2011/01/21/139015.html</guid><wfw:comment>http://www.shnenglu.com/oldworm/comments/139015.html</wfw:comment><comments>http://www.shnenglu.com/oldworm/archive/2011/01/21/139015.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.shnenglu.com/oldworm/comments/commentRss/139015.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/oldworm/services/trackbacks/139015.html</trackback:ping><description><![CDATA[  <p><span>关于内存数据?/span></p> <p> </p> <p><span>最q要一些数据放到内存里面做很高的ƈ发操作,考虑了很多方案,</span></p> <p><span><span>1?nbsp;</span></span><span>单点使用</span><span>map hash_map</span><span>{自q理?/span></p> <p><span><span>2?nbsp;</span></span><span>?/span><span>sqlite</span><span>内存表?/span></p> <p><span><span>3?nbsp;</span></span><span>?/span><span>fastdb</span><span>内存数据库?/span></p> <p><span><span>4?nbsp;</span></span><span>?/span><span>ExtremeDb</span><span>Q?/span><span>TimesTen</span><span>{?/span></p> <p><span>比较试了一?/span><span>123</span><span>Q发现还是自己实现速度最快,?/span><span>fastdb</span><span>模式?/span><span>3-5</span><span>倍,</span><span>fastdb</span><span>模式?/span><span>sqlite</span><span>内存表模式快</span><span>10</span><span>倍左叻I׃自己实现不具有典型通用性,多线E下讉K效率会下降,要管理多U程下各U更新查扄q是比较ȝ的,所以在</span><span>1</span><span>?/span><span>3</span><span>Ҏ之间U结?/span></p> <p><span>Z使得决策更好一些,暂时q没做决定,ZC方等上面搜烦了一些论文来看,看来看去看得真来气啊Q虽焉叫内存数据库但各U实现的都有Q有?/span><span>gdbm</span><span>来做的,有直?/span><span>map</span><span>理的,?/span><span>hash</span><span>理数据的,?/span><span>t</span><span>树管理的Q有数组队列理的,有的明显是个不大变的东西还弄个啥事务的Q靠Q刚刚居然还看到一鸟文《电|监控系l实时数据库的设计与实现》里面的试居然?/span><span>1000</span><span>条,插入旉</span><span>80</span><span>毫秒Q真可笑啊,区区q么Ҏ据也好意思测Q还要花</span><span>80</span><span>毫秒Q还自以为很快,q个速度臛_可提?/span><span>1000</span><span>倍以上啊Q这帮垃圾,写的啥鸟文章Q研I个屁啊?/span></p> <p><span>看完q十来篇论文Q俺的思A又回?/span><span>1999</span><span>q_当年我给别h优化q一个电信计费的软gQ看的论文里面有好几讲电信计费的)Q当时有个朋友的朋友拿了个需求过来,</span><span>7000</span><span>万条记录Q原来计费单要花十几个时吧,我帮他改了下Q十来分钟就完了,朋友很满意,当时的做法很单,是弄了?/span><span>mmtable</span><span>Q大体就是跟</span><span>map</span><span>cM的东西吧Q那个时?/span><span>map</span><span>q没行hQ俺也不知道Q所以就自己弄了个内存表Q内部基本就是二分查找了Q那个时候我?/span><span>hash</span><span>都不大熟悉,</span><span>B</span><span>树之cȝ法刚接触也不会用,p么个东西当时的电脑也只要花十来分钟,我估计就是那个老程序放在现在的普通台式机上要不了几秒钟就可算完。也不知道这么几千万条记录的需求怎么在这帮h眼里成了什么v量数据,对俺来说跟玩似的Q区区几千万嘛,不过是俺拿来试用的?/span></p> <p><span>d中做了个</span><span>md5 hash</span><span>反查的东西,数据都是几百亿到几万亿的Q后来的效果是一个文件可存万亿记录,一ơ查询^?/span><span>1.2</span><span>?/span><span>IO</span><span>Q即使全攑֜</span><span>SATA</span><span>盘上也十来毫U而已?/span></p> <p><span>区区几千万条记录咋就叫什么v量数据呢Qv量个毛啊Q内存都攑־下的叫什么v量,现在服务器动不动都是几十</span><span>G</span><span>内存Q区区千万根本算不上什么,查询定位都可到微妙了Q?/span><span>1</span><span>U插入至千万条了,居然q看?/span><span>1000</span><span>条插入的试Q真是不得不佩服国内q帮垃圾研究生的水^Q也不知道这U论文咋p通过审查Q只能得出结Z们的老师也都是猪?/span></p> <p><span><span>         </span></span><span>骂归骂自q问题q需要l努力,对咱目前的需求来说自q理数据,即一个线E都搞得定,因ؓ不过区区几个表,几十万条记录而已Q不q这U?/span><span>10</span><span>q前咱就会的技术还真是拿不出手Q怎么的也得做得更好一点,呵呵Ql研I吧Q多U程下内存数据库Q从概念上看的确是个很有吸引力的东西Q要是性能跟得上,其实在很多地方可以取代普通的数据l构用法了,可以大大减少~程隑ֺQ甚x在想如果有个支持事务的内存数据库Q之前设计的</span><span>cad</span><span>cY件的</span><span>undo/redo</span><span>都可以用事务来实玎ͼ完全可以抛弃先前设计的复杂结构,其实q种东西即不用内存数据库就是用个</span><span>sqlite</span><span>都完全能搞定Q唉Q往事不堪回首啊Q看来数据库斚w的确得多花功夫,特别是多U程和分布式模式下的内存数据库?/span></p> <p> </p> <p> </p> <img src ="http://www.shnenglu.com/oldworm/aggbug/139015.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/oldworm/" target="_blank">袁斌</a> 2011-01-21 13:37 <a href="http://www.shnenglu.com/oldworm/archive/2011/01/21/139015.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最q项目架构及协议决策http://www.shnenglu.com/oldworm/archive/2011/01/11/138330.html袁斌袁斌Tue, 11 Jan 2011 05:33:00 GMThttp://www.shnenglu.com/oldworm/archive/2011/01/11/138330.htmlhttp://www.shnenglu.com/oldworm/comments/138330.htmlhttp://www.shnenglu.com/oldworm/archive/2011/01/11/138330.html#Feedback3http://www.shnenglu.com/oldworm/comments/commentRss/138330.htmlhttp://www.shnenglu.com/oldworm/services/trackbacks/138330.html 

 

最q给自己换了个老板Q忙了一D|_所以有几个月没写博客,今后q是要争取多写啊Q呵c?/span>

 

换来新地方,W一件大的事情就是修改后端架构和通信协议Q架构也设计得很普通,因ؓq边的业务不需要太q复杂的后端Q所以就单设计了一下,基本是参?/span>web的模型,W合我一贯的?/span>web学习的思想Q弄了个gate理入口Q相当于web下的webserverQ后端其他服务器挂在?/span>gate下,相当?/span>web模型下的appserverQ或?/span>fastcgi模型?/span>fastcgiq程Q?/span>gate上管理连接、合法性检、登录、加密、压~、缓存?/span>Gate和后端通信本来惛_?/span>fastcgi协议Q但看了之后觉得fastcgi协议q是复杂了,所以就设计了一个更单的协议Q?/span>gate和后?/span>server之间可传?/span>key:value型数据对Q?/span>value不局限于字符Ԍ可以是Q意数据,q样基本满了当前的需求,W一版放上去之后也运行良好,C天也基本持箋E_q行快一个月了,没出q什么事情。由于在gateq边~冲?/span>job理Q所以后?/span>server升很方便,随时可关闭更斎ͼgate会在H口旉内将未执行完成的d重新提交Q有此功能可攑ֿ大胆的升U后端,q个月这L工作做了几次Q在架构修改之前q样的事情几乎是不敢做的Q因Z旦升U所有用户全部断开q接Q而现在用户则基本无感觉?/span>Gate上的~存层ؓ后端减少了一些压力,q个~存是按照请求的md5?/span>key做的QƈҎ协议配置时效Q有?/span>cache后端大多数服务可不设计缓存或降低~存设计的复杂度?/span>Gate上针Ҏ感数据统一做了加密处理Q主要是辛辛苦苦整理的数据不能轻易让竞争ҎH去了,呵呵?/span>Gate也做了压~,现在是针?/span>>=128长度的包q行压羃Q用了qlzQ压~效率还是很不错的,速度很快。目?/span>gate后端挂接的既?/span>win上的server也有linux上的serverQ这是一开始就q么规划的,现在看来当初的目的达CQ؜合发挥各自的优势Q有的项目在原有pȝ上跑得好好的Q没必要重新开发嘛?/span>

 

协议设计上本来我是计划二q制混合json格式Q以二进制ؓ主,但尝试了一个协议之后发玎ͼq边的小伙子们对直接操纵内存普遍技术不q关Q他们大多是?/span>java开始的Q后来才学习cQ对字符串用得很熟练Q权衡之下采用了jsonZQ؜合二q制的方案,q样修改之后的协议和他们之前使用?/span>xmlcMQ就是更更紧凑一点,使用Ҏ上很cMQ从现在的效果看q行Q?/span>json格式Z的协议当然不能跟使用pb之类的相比,解析效率上大U单U程每秒解析20来万10?/span>obj的对象,速度上不太快但也不太慢,对付一U至多几万数据包的应用来说还是够的,因ؓ现在cpu计算能力普遍q剩Q?/span>json的另个好处就是增删字D很方便Q各个版本之间不需要太考虑版本的问题,要是全用二进制格式就要麻烦很多了Q在使用压羃之后Q目前的json格式协议比之前的xml协议减少?/span>2/3的带宽用,M效果q是可以的。?/span>json调试也很方便Q我提供了一个工P写后端的q接用该工h?/span>json格式收发数据Q无需{?/span>client开发好了再d后端Q之后做client也很方便Q请求发q去之后q回来的是标准?/span>json格式数据Q同L解析ҎQ每个不同的应用按照不同的格式处理下即可,?/span>web{模块交互也很方便,q可是额外的好处了?/span>

 

MQ虽?/span>json格式存储效率和解析效率跟二进制方式还差半个量U到一个量U,但合理用还是可以的Q特别是?/span>xml相比优势很明显,权衡使用吧,当然q求极致效率可能q是?/span>pb之类的更合适一些,或者自p?/span>tlv格式?/span>

 



袁斌 2011-01-11 13:33 发表评论
]]>
吹牛太少Q以后要多吹http://www.shnenglu.com/oldworm/archive/2010/10/03/128475.html袁斌袁斌Sun, 03 Oct 2010 06:26:00 GMThttp://www.shnenglu.com/oldworm/archive/2010/10/03/128475.htmlhttp://www.shnenglu.com/oldworm/comments/128475.htmlhttp://www.shnenglu.com/oldworm/archive/2010/10/03/128475.html#Feedback0http://www.shnenglu.com/oldworm/comments/commentRss/128475.htmlhttp://www.shnenglu.com/oldworm/services/trackbacks/128475.html昨天去见两个老乡Q多q的朋友同学Q也是搞技术的Q大安在上P只是交流不是太多Q聊h做过的一些东西,他觉得不大相信,我说我写的远E控制程序全dlll成Q所有模块可热升U,包括L块,L块小?/span>20kQ他g难于怿Q我跟他说这个程序还?/span>2001q做的,他就更难怿了。后来又说v我最q做的那个云计算的h格查询,他也很难怿底下是云计算Q由于没带机器也没法l他看后台服务器Q所以我估计他最后还是半信半疑吧。上周另一个朋友说他们老板有个目十来个h做了3q_一直做不稳定,我说l我一D|间我肯定能把他整E_Q后来给他看了我之前做的一些东西,游戏{,g他还在怀疑我的能力,q几个其实都是Ҏ有些了解的朋友了Q看来我q是宣传得太啊。我知道大家都对n大公司的人有U崇拜,我等一直在公司؜的h没什么h瞧得上,可是我又不能跟他们说哪年哪月Q我到某个公司{了下Q看了某某写的代码,你所崇拜的h不过如此Q哪个工E里面写了个败笔 {等

可能我n边也合作伙伴、曾l的老板、同事、敌人知道我到底什么水qI2000q的时候就带队做几十万行的目Q连l做了几个,Z们申误Y件企业奠定基。云计算的h格查询,3周完成,?/span>2个客L的棋牌游戏带了两个朋友一起半q完成,全部模块接口化,模块可单独升U?/span>NetdongleQ一?/span>master?/span>slave多重保护的网l验证系l,支持由控制端上传dll?/span>db{,也就一个月完成。这些程序上U之后就几乎不用修改Q一直稳定运行哦Q一般的E序要做到第一版版本出d几乎不出错是很难的,没有一定功力的人是做不到的?/span>

昨天吹了下牛Q我?/span>windows下应用层的Y件基本没有做不出来的Q或许牛吹得有点大,那朋友惊讶了一下?/span>

今年湿疹d之后发现自己战斗力提升很多,之前做事情总觉得差一口气Q精力不,现在觉得_֊充沛Q酒也能喝了Q活也能q了Q速度也快了,也敢出去跟别Z了Q之前一直自卑,没病真好啊?/span>

以后要多宣传Q多吹牛啊!



袁斌 2010-10-03 14:26 发表评论
]]>
我的|络模块设计W二?/title><link>http://www.shnenglu.com/oldworm/archive/2010/10/03/128474.html</link><dc:creator>袁斌</dc:creator><author>袁斌</author><pubDate>Sun, 03 Oct 2010 06:25:00 GMT</pubDate><guid>http://www.shnenglu.com/oldworm/archive/2010/10/03/128474.html</guid><wfw:comment>http://www.shnenglu.com/oldworm/comments/128474.html</wfw:comment><comments>http://www.shnenglu.com/oldworm/archive/2010/10/03/128474.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/oldworm/comments/commentRss/128474.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/oldworm/services/trackbacks/128474.html</trackback:ping><description><![CDATA[<p>07q我写了一文章叫《我的网l模块设计》,姑且叫那个ؓW一版吧Q由于持l对|络模块q行改进Q所以现在的实现和当时有很大改变Q加上上层应用越来越多,又经q了几年旉考验Q现在的实现方式比之前的更灵zL有效率,也因为最q看了一些h做网l程序多q竟毫无建树Q一直要用别人写的网l模块,所以有感而写此文Qؓ了得此文不受上一《我的网l模块设计》的影响Q我军_写之前不看原来的文章Q所以此文跟原文那篇文章可能没有太多怼性?br> 一个基本的|络模块Q无非就是管理N个连接,快速处理每个连接的收发数据、消息等Q所谓好的网路模块,无非是E_、高效、灵z,下面分几部分来写Q?br> 一?q接理<br> 之所以首先写q接理Q是因ؓq接理是核心,也是最隄地方Q我写第一个网l库之前Q搜索过很多当时可以扑ֈ的例子工E,当时几乎找不到可E_q行的工E,当然更找不到好的Q于是摸索前q,期间对连接管理用了各种ҎQ从最早一个csQ界区CriticalSectionQ我UcsQ,recv send都用q个csQ到后来send用一个csQrecv用一个csQ用多个的时候还错,最后用一个cs+一个原子值ref理一个连接,每个q接send的时候用csQrecv的时候用refQ如果该q接的消息要跨线E异步执行,也用refQ如此较单的解决了连接管理的问题?br> 同样使用生存期管理方法,也有人用指针Q虽然原理和我直接操U는存期一P但实现方法毕竟不同,不过我ؓ了让实现依赖一些没有引入智能指针?br> 当然我后来也发现很多Z是用q种ҎQ如有些人就id来管理连接,每个q接分个idQ其他操作全部用idQ每ơ对q接的调用先译一下,如果id扑־到映目标就调用Q否则就说明该连接不存在了,q种Ҏ单只是不直接Q多了个查找q程Q另外查扄时候可能还需要全局锁(q依赖于q接数据l织Q?br> 也有Z用一个线E管理连接,其他所有与该连接有关的生存期问题全部到该线E处理,q样也是可行的,只是需要做一个较好的包装Q如果包装好上层调用方便Q如果包装不好,可能上层调用有一些约束?br> 虽然各种Ҏ都有Z用,但我一直选择直接的生存期理ҎQ其实内部实现的时候还是有很多优化措施的,减少了大量addref、release的调用,q一步提高了效率?br> 二?U程l?br> 我最初做|络库的时候还不是很清楚上层如何用这个库Q后来在上面做了几个应用之后慢慢有了更多xQ最q的|络库是设计了这么几l线E:ioU程l、同步线E组、异步线E组、时钟线E组、logU程l,每组U程都可开可关Q就ioU程l也是可关的Q这只是Z整个库更灉|适用性更q泛Q如只用同步U程l或异步U程l仅这个线E组当一个消息队列用?br> IoU程l就是处理io收发的,listen recv send 以及解密解压~都是在q组U程Q一般这l线E会开2个或2*cpu个?br> 同步U程l,一般这l线E开1个,用来处理logic?br> 异步U程l,q组U程Ҏ需要开0个或n个,单应用无db{慢速操作的应用不开Q有很多db{慢速操作的可以开很多个?br> 旉U程l,一般不开或开1个?br> LogU程l,一般开1个,主要Z避免其他U程调用WriteLog的时候被盘iodQ所以弄了一个logU程?br> 其实q有一个主U程Q我的每l线E(包括ȝE)都支持事件和定时器,ioU程、同步线E、异步线E组、时钟线E组、甚至logU程l都支持事g和定时器Q到d我还只是让每l线E都支持事gQ今qؓ了更好的使用旉我给每组U程设计了定时器Q现在定时器U程l有炚w肋的味道Q一般是用不上专门的定时器线E组Q不q我q没有将它删掉,主要在我的设计里面,它和同步异步U程l一P都只是一l线E,如果必要的时候可以将它用作同步线E或者异步线E组Q所以l保留了它的存在?br> q几l线E之间都是可互发消息的,所以一个逻辑要异步到别的U程执行是非常方便的Q只要调用一下PostXXEvent(TlsInfo *ptls, DWORD dwEvent, WPARAM wParam, LPARAM lParam);我凭借这个设计得这套网l库几乎可以适用上层各种应用Q不是非常单的|络应用q是复杂的,一框打。对最单的Q一个ioU程搞定Q其他线E全养I对于复杂的ioU程+同步+异步+log全开?br> 三?内存?br> 内存池其实没有想象中的那么神U,当然如果要让一个网l程序持l?*24时E_高效q行Q内存池几乎必不可少的,内存池的作用首先是减内存碎片,其次是ؓ了提高速度Q我惌两点很容易想明白的,关于内存池我之前写了pd文章Q可参考我的博客:<br> <br>《内存池之引a?<a >http://blog.csdn.net/oldworm/archive/2010/02/04/5288985.aspx</a><br> 《单U程内存池?<a >http://blog.csdn.net/oldworm/archive/2010/02/04/5289003.aspx</a><br> 《多U程内存池?<a >http://blog.csdn.net/oldworm/archive/2010/02/04/5289006.aspx</a><br> 《dlmalloc、nedmalloc?<a >http://blog.csdn.net/oldworm/archive/2010/02/04/5289010.aspx</a><br> 《线E关联内存池?<a >http://blog.csdn.net/oldworm/archive/2010/02/04/5289015.aspx</a><br> 《线E关联内存池再提速?<a >http://blog.csdn.net/oldworm/archive/2010/02/04/5289018.aspx</a><br> <br>四?定时?br> 关于定时器,上面讲线E组的时候已l讲q,我现在的设计是每个线E(包括ȝE)都支持定时器Q调用方法都是一LQ回调函数Ş式也是一LQ由于定时器攑ֈ各组U程里面Q所以减了U程之间的切换,提高了效率?br> 关于定时器,可参考《定时器模块攚w?<a >http://blog.csdn.net/oldworm/archive/2010/09/11/5877425.aspx</a><br> <br>五?包格?br> 关于包格式可参考《常用csE序自定义数据包描述?<a >http://blog.csdn.net/oldworm/archive/2010/03/24/5413013.aspx</a><br> <br>六?Buffer<br> 之前的文章其实我一直没有提q我的bufferQ其实我的buffer设计是很灉|的,现在它和pool也是有些兌的,我的poolset其实底下是按照各种不同大小的buffer预设的尺寸。Buffer我设计ؓ循环式,不允许回l,包含<br> Char *pbase 块基址<br> Char *pread 当前L?br> Char *pwrite 当前写指?br> DWORD tag;<br> Buffer *next;<br> Capacity d配尺寸,上面分配的时候可能只是指定了19Q但实际可能分配的是32个字节,所以内部用的时候要Ҏcapacity来最大限度的利用~冲区?br> Buffer分配q利用了一个技巧,事实上分配的时候是一ơ分配一个需要的大缓Ԍ前面为Buffer自n的数据,后面为数据部分,pbase指向数据部分Q这样处理减了一ơ分配,我估计很多h都在用这个技巧?br> PwriteL不会于pread的,但pread可能和pbase不一P仅当后面IZI间不够用的时候才可能会移动数据,否则数据不会Ud?br> WSARecv的时候我是这么处理的Q如果首ơ获取了一个包的一部分Q但buffer中还有够的I间放下包的剩余部分Q我不会再分配一个buffer去recvQ而是直接用原buffer指定一个合适的偏移和size去WSARecvQ这样可以最大限度的减少复制?br> 刚才q有朋友问到我recv的层ơ组l,我的|络库里面是q样l织的,OnRecv是个虚函敎ͼ最基础的IocpClient的OnRecv只处理数据而不解析格式QIocpClientMsg׃认识默认的一U包格式Q这个类的OnRecv会将m_recvbuf中的数据l织为msgQƈ可能的一ơ返回更多个msgQ回调OnMsg函数Q由上层军_该消息在哪个U程处理Q这h认ؓ是最灉|的,如果是个很小的serverQ可能直接就在ioU程里面处理了,也可postevent到同步线E处理,亦可PostEvent到异步线E处理?br> <br>七?TLSINFO<br> TlsInfo֐思义是每个U程兌的一l数据,暂时我还没有看到别hq么设计Q也许我设计得有些复杂了Q在q个数据里面有一些常用的和该U程相关的数据,如该U程的分配基、步长,用这两个参数可让每个U程刉出唯一序列Q还有常用pool的地址Q如tm_pool *p1k; tm_pool *p2k;… q样设计使得要分配的时候直接取tm_poolQ最大限度的发挥了分配速度Q还有一些常规参量long c; long d; DWORD a; DWORD b;… q几个值可理解为栈内|其实Z减少上层调用复杂度的Q如我将一个连接的包从ioU程PostEvent到同步线E处理,PostEvent首参数就是tlsinfoQPostEvent会根据tlsinfo里面的一个内部值决定是不是要调用addrefQ因为我有个地方预增?Q所以大多数情况下在io发到其他U程的时候是无需调用addref的,提高了效率,tlsinfo里的其他一些g层应用可使用Q用在逻辑处理{情况下?br> <br>八?性能分析<br> *nix下有很多知名的网l库Q但在win下特别是使用iocp的库里面Q一直就没有一个能作ؓ基准的库Q即使asio也因为出来太晚不为大多数人熟悉而不能成为基准库Qlibevent接iocp׃采用0 buffer模拟所以也没有发挥够的性能Q对比spserver我比它快70%左右Q我d惌是微软能他那个iocp的例子写得更好一点就好了Q至学的h有一个更高一点的基础Q而不至于?a >http://www.codeproject.com/KB/IP/iocp_server_client.aspx</a>q样的垃圾代码都能成为很多h的样ѝ?br> <br>九?杂谈<br> Z写好一个win下稳定高效的|络库,?7q的时候几乎搜遍了那个旉D之前所有能扑ֈ的iocp例子Q还包括通过朋友{途径看到的如snda{网l库Q可惜真没找到好的,大多C子是只要多线E发起几千个q接不断发送数据马上就MQ偶几个不ȝQ包括snda的)只要随机q接q断开׃产生句柄泄漏Q关闭所有连接之后句柄ƈ不关闭等Q也是说这些例子连基本的生存期理都没搞定Q能通过生存期管理ƈ且不ȝ只有有限的几个,可惜性能又太差,杯具啊?br> 早年写网l库的时候也加入了sodme在google上徏的那个群Q当时群q是很热闹的Q可惜大多数人都是摸索,所以很多问题只是讨论却从无定论Q没有谁能说服别人,也没有h可轻易被说服Q要是现在或许有一些很有经验的人,可惜那个由于GFW现在虽能讉K也不大活跃了?br> 最q看到有些写|络E序7q甚x久的在用libevent、ace{感惛_复杂Q可悲的是那些hq没意识到用一个库和写一个库有多大的区别Q可能那些h一辈子也认识不到写一个库比用一个库隑֤,那些Z些库基本会用了,让他自己d也基本是照这个模式,不会有什么突_无需自己动手了,悲哀啊。当Ӟ要写一个稳定的|络库需要耗费很多旉Q特别是要写一个能和知名库性能接近或更好的库,更是要费费力,没点耐心和持久力是不可能做好的。在中文领域随便查什么稍有些名气的代码,L能找到很多剖析类文章Q可原创的东西L很少Q也不知道那些大侠怎么搞的Q什么都能剖析可怎么d不出什么像L东西呢?br> 其实本来没有打算写这文章,可能是看了陈的muduo才得我有了写出来的冲动Q大概是受到他的开源鼓励吧?br> 谨以此文记录本h最q?q对|络模块的修改ƈ短ȝ?/p> <p> </p> <img src ="http://www.shnenglu.com/oldworm/aggbug/128474.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/oldworm/" target="_blank">袁斌</a> 2010-10-03 14:25 <a href="http://www.shnenglu.com/oldworm/archive/2010/10/03/128474.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的|络模块设计W一?/title><link>http://www.shnenglu.com/oldworm/archive/2010/10/03/128473.html</link><dc:creator>袁斌</dc:creator><author>袁斌</author><pubDate>Sun, 03 Oct 2010 06:25:00 GMT</pubDate><guid>http://www.shnenglu.com/oldworm/archive/2010/10/03/128473.html</guid><wfw:comment>http://www.shnenglu.com/oldworm/comments/128473.html</wfw:comment><comments>http://www.shnenglu.com/oldworm/archive/2010/10/03/128473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/oldworm/comments/commentRss/128473.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/oldworm/services/trackbacks/128473.html</trackback:ping><description><![CDATA[<p><span><strong><span>我的</span><span><span>IOCP</span></span></strong><strong><span>|络模块设计</span></strong></span></p> <p><span> </span></p> <p><span><span>Z设计一个稳定易用高效的</span><span><span>iocp</span></span><span>|络模块Q我前前后后׃好几个月的时_也曾阅读q网上很多资料和代码Q但是非帔R憾,能找到的资料一般都说得很含p,很少有具体的Q能扑ֈ的代码离真正能商用的|络模块差得太远Q大多只是演CZ下最基本的功能,而且大多是有很多问题的,主要问题如下Q?/span></span></p> <p><span><span><span><span>1?/span> </span></span></span><span><span>很多代码没有处理一ơ仅发送成功部分数据的情况?/span></span></p> <p><span><span><span><span>2?/span> </span></span></span><span><span>几乎没有扑ֈ能正管理所有资源的代码?/span></span></p> <p><span><span><span><span>3?/span> </span></span></span><span><span>大多没有采用?/span><span><span>pool</span></span><span>Q有的甚至画蛇添用什?/span><span><span>map</span></span><span>查找对应客户端,没有充分使用</span><span><span>perhandle, perio</span></span><span>?/span></span></p> <p><span><span><span><span>4?/span> </span></span></span><span><span>接收发送数据大多拷贝太多次数?/span></span></p> <p><span><span><span><span>5?/span> </span></span></span><span><span>接收理大多很低效,没有充分发挥</span><span><span>iocp</span></span><span>能力?/span></span></p> <p><span><span><span><span>6?/span> </span></span></span><span><span>几乎都没有涉及上层如何处理逻辑Q也没有提供相应解决ҎQ如合ƈ</span><span><span>io</span></span><span>U程处理或单独逻辑U程Q?/span></span></p> <p><span><span><span><span>7?/span> </span></span></span><span><span>大多没有分离数据和包数据?/span></span></p> <p><span><span>…</span></span></p> <p><span><span>问题q有很多Q就不一一列出来了Q有一定设计经验的人应该有同感。要真正解决q些问题也不是那么容易的Q特别是?/span><span><span>win</span></span><span>下用</span><span><span>iocp</span></span><span>的时候资源释放是个麻烦的问题Q我在资源管理上׃很多旉Qv初也犯了很多错误Q后来在减少同步对象上又׃不少旉Qv?/span><span><span>client</span></span><span>用了两个同步对象Q后来减ؓ</span><span><span>1</span></span><span>个)。下面我我所设计的网l模块的各个部分q行单的讲解</span></span></p> <p><strong><span><span>一、内存管理?/span></span></strong></p> <p><span><span>内存理是采用池模式Q设计了一个基池类Q可以管理某固定大小的池</span></span></p> <p><span><span>class CBufferPool</span></span></p> <p><span><span>{</span></span></p> <p><span><span><span><span>        </span>…</span></span></span></p> <p><span><span><span><span>        </span>void *newobj();</span></span></span></p> <p><span><span><span><span>        </span>void delobj(void *pbuf);</span></span></span></p> <p><span><span><span><span>        </span>…</span></span></span></p> <p><span><span>}; </span></span></p> <p><span><span>在基池类上提供了一个模板的对象?/span></span></p> <p><span><span>template <class T></span></span></p> <p><span><span>class CObjPool : public CBufferPool</span></span></p> <p><span><span>{</span></span></p> <p><span><span>public:</span></span></p> <p><span><span><span><span>        </span>T *newobj()</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>                </span>void *p = CBufferPool::newobj();</span></span></span></p> <p><span><span><span><span>                </span>T *pt = new(p) T;</span></span></span></p> <p><span><span><span><span>                </span>return pt;</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span><span><span>        </span>void delobj(T* pt)</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>                </span>pt->~T();</span></span></span></p> <p><span><span><span><span>                </span>CBufferPool::delobj(pt);</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span>};</span></span></p> <p><span> </span></p> <p><span><span>在基池的基础上定义了一个简单的通用?/span></span></p> <p><span><span>class CMemoryPool</span></span></p> <p><span><span>{</span></span></p> <p><span><span>private:</span></span></p> <p><span><span><span><span>        </span>CBufferPool bp[N];</span></span></span></p> <p><span><span>…</span></span></p> <p><span><span>};</span></span></p> <p><span><span>通用池是?/span><span><span>N</span></span><span>个不同大的基础池组成的Q分配的时候圆整到合适的相近基础池ƈ由基池分配?/span></span></p> <p><span><span>最后还提供了一个内存分配适配器类Q从该类z的类都支持内存池分配?/span></span></p> <p><span><span>class t_alloc</span></span></p> <p><span><span>{</span></span></p> <p><span><span>public:</span></span></p> <p><span><span><span><span>        </span>static void *operator new(size_t size)</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>                </span>return CMemoryPool::instance().newobj(size);</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span><span><span>        </span>static void operator delete(void *p, size_t size)</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>                </span>CMemoryPool::instance().delobj(p, size);</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span>};</span></span></p> <p><span><span>Ҏ试</span><span><span>CMempool</span></span><span>分配速度?/span><span><span>CObjpool<></span></span><span>E微慢一点点Q所以我在用的时候就直接?/span><span><span>t_alloc</span></span><span>cL生,而不是用对象池,q是个风格问题,也许有很多h喜欢用更高效一点的</span><span><span>objpool</span></span><span>方式Q但q个q不大碍?/span></span></p> <p><span> </span></p> <p><span><span>在网l模块中</span><span><span>OVERLAPPED</span></span><span>zcd要用池进行分配,q有</span><span><span>CIocpClient</span></span><span>也要用池分配Q再是</span><span><span>CBlockBuffer</span></span><span>也是从池分配的?/span></span></p> <p><span><span>如下定义Q?/span></span></p> <p><span><span>struct IOCP_ACCEPTDATA : public IOCP_RECVDATA, public t_alloc</span></span></p> <p><span><span>class CIocpClient : public t_alloc</span></span></p> <p><span> </span></p> <p><strong><span><span>二、数据缓冲区?/span></span></strong></p> <p><span><span>数据~冲?/span><span><span>CBlockBuffer</span></span><span>为环形,大小不固定,随便分配多少Q主要有以下几个元素Q?/span></span></p> <p><span><span><span>Char *pbase;<span>           </span>//</span></span><span>环Ş首部</span></span></p> <p><span><span><span>Char *pread;<span>           </span>//</span></span><span>当前L?/span></span></p> <p><span><span><span>Char *pwrite;<span>          </span>//</span></span><span>当前写指?/span></span></p> <p><span><span><span>Int nCapacity;<span>         </span>//</span></span><span>~冲区大?/span></span></p> <p><span><span><span>Long nRef;<span>              </span>//</span></span><span>兌计数?/span></span></p> <p><span><span>用这UŞ式管理缓冲区有很多好处,发送数据的时候如果只发送了部分数据只要修改</span><span><span>pread</span></span><span>指针卛_Q不用移动数据,接收数据q处理的时候如果只处理了部分数据也只要修改</span><span><span>pread</span></span><span>指针卛_Q有新数据到辑֐直接写到</span><span><span>pwrite</span></span><span>q修?/span><span><span>pwrite</span></span><span>指针Q不用多ơ拷贝数据?/span><span><span>nRef</span></span><span>兌计数q可处理一个包发给</span><span><span>N</span></span><span>个h的问题,如果要给</span><span><span>N</span></span><span>个h发送相同的包,只要分配一个缓冲区Qƈ讄</span><span><span>nRef</span></span><span>?/span><span><span>N</span></span><span>可以不用复?/span><span><span>N</span></span><span>份?/span></span></p> <p><span> </span></p> <p><strong><span><span>三、收发缓冲区理</span></span></strong></p> <p><strong><span><span>发送缓冲区</span></span></strong></p> <p><span><span>我把</span><span><span>CIocpClient</span></span><span>的发送数据设计ؓ一?/span><span><span>CBlockBuffer </span></span><span>的队列,如果队列内有多个?/span><span><span>WSASend</span></span><span>的时候一ơ发送多个,如果只有一个则仅发送一个,</span><span><span>CIocpClient</span></span><span>发送函数提供了两个Q分别是Q?/span></span></p> <p><span><span>Bool SendData(char *pdata, int len);</span></span></p> <p><span><span>Bool SendData(CBlockBuffer *pbuffer);</span></span></p> <p><span><span>W一个函C发送链的最后一个数据块能否容纳发送数据,如果能复制到最后一个块Q如果不能则分配一?/span><span><span>CBlockBuffer</span></span><span>挂到发送链最后面Q当然这个里面要处理同步?/span></span></p> <p><span> </span></p> <p><strong><span><span>接收~冲?/span></span></strong></p> <p><span><span>接收理是比较简单的Q只有一?/span><span><span>CBlockBuffer</span></span><span>Q?/span><span><span>WSARecv</span></span><span>的时候直接指?/span><span><span>CBlockBuffer->pwrite</span></span><span>Q所以如果块大小合适的话基本上是不用拼包的Q如果一ơ没有收C个完整的数据包,q且块还有够空间容U_余空_那么再提交一?/span><span><span>WSARecv</span></span><span>让v始缓冲指?/span><span><span>CBlockBuffer->pwrite</span></span><span>如此则收C个完整数据包的过E都不用重新拼包Q收C个完整数据包之后可以调用虚函数让上层q行处理?/span></span></p> <p><span><span>?/span><span><span>IocpClient</span></span><span>层其实是不支持数据包的,在这个层ơ只有流的概念,q个后面会专门讲解?/span></span></p> <p><span> </span></p> <p><span><strong><span>四?/span><span><span>IocpServer</span></span></strong><strong><span>的接入部分管?/span></strong></span></p> <p><span><span>我把</span><span><span>IocpServer</span></span><span>设计为可以支持打开多个监听端口Q对每个监听端口接入用户后调?/span><span><span>IocpServer</span></span><span>的虚函数分配客户端:</span></span></p> <p><span><span><span><span>        </span>virtual CIocpClient *CreateNewClient(int nServerPort)</span></span></span></p> <p><span><span>分配客户端之后会调用</span><span><span>IocpClient</span></span><span>的函?/span><span><span><span> </span>virtual void OnInitialize();</span></span><span>分配内部接收和发送缓冲区Q这样就可以Ҏ来自不同监听端口的客L分配不同的缓冲区和其他资源?/span></span></p> <p><span> </span></p> <p><span><span><span>Accept</span></span><span>其实是个可以有很多选择的,最单的做法可以用一个线E?/span><span><span>+accept</span></span><span>Q当然这个不是高效的Q也可以采用多个U程的领D?/span><span><span>-</span></span><span>q随者模?/span><span><span>+accept</span></span><span>实现Q还可以是一个线E?/span><span><span>+WSAAccept</span></span><span>Q或者多个线E的领导?/span><span><span>-</span></span><span>q随者模?/span><span><span>+WSAAccept</span></span><span>模式Q也可以采用</span><span><span>AcceptEx</span></span><span>模式Q我是采?/span><span><span>AcceptEx</span></span><span>模式做的Q做法是有接入后投递一?/span><span><span>AcceptEx</span></span><span>Q接入后重复利用?/span><span><span>OVERLAPPED</span></span><span>再投递,q样即ɽ理大量q接也只有v初的几十个连接会分配</span><span><span> OVERLAPPED</span></span><span>后面的都是重复利用前面分配的l构Q不会导致再度分配?/span></span></p> <p><span> </span></p> <p><span><span><span>IocpServer</span></span><span>q提供了一个虚函数</span></span></p> <p><span><span><span><span>        </span>virtual bool CanAccept(const char *pip, int port){return true;}</span></span></span></p> <p><span><span>来管理是否接入某?/span><span><span>ip:port </span></span><span>的连接,如果不接入直接会关闭该连接ƈ重复利用此前分配?/span><span><span>WSASocket</span></span><span>?/span></span></p> <p><span> </span></p> <p><strong><span><span>五、资源管?/span></span></strong></p> <p><span><span><span>Iocp</span></span><span>|络模块最隄是q个了,什么时候客L关闭或服务器d关闭某个q接q收回资源,q是最隑֤理的问题Q我试了几U做法,最后是采用计数器管理模式,具体做法是这LQ?/span></span></p> <p><span><span><span>CIocpClient</span></span><span>?/span><span><span>2</span></span><span>个计数变?/span></span></p> <p><span><span><span><span>        </span>volatile long m_nSending;<span>              </span>//</span></span><span>是否正发送中</span></span></p> <p><span><span><span><span>        </span>volatile long m_nRef;<span>                     </span>//</span></span><span>发送接收关联字</span></span></p> <p><span><span><span>m_nSending</span></span><span>表示是否有数据已</span><span><span>WSASend</span></span><span>中没有返?/span></span></p> <p><span><span><span>m_nRef</span></span><span>表示</span><span><span>WSASend</span></span><span>?/span><span><span>WSARecv</span></span><span>有效调用未返回和</span></span></p> <p><span><span>在合适的位置调用</span></span></p> <p><span><span><span><span>        </span>inline void AddRef(const char *psource);</span></span></span></p> <p><span><span><span><span>        </span>inline void Release(const char *psource);</span></span></span></p> <p><span><span>增引用计数和释放引用计数</span></span></p> <p><span><span><span><span>        </span>if(InterlockedDecrement(&m_nRef)<=0)</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>                </span>//glog.print("iocpclient %p Release %s ref %d\r\n", this, psource, m_nRef);</span></span></span></p> <p><span><span><span><span>                </span>m_server->DelClient(this);</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span>当引用计数减到</span><span><span>0</span></span><span>的时候删除客LQ其实是内存返回给内存池)?/span></span></p> <p><span> </span></p> <p><strong><span><span>六、锁使用</span></span></strong></p> <p><span><span>锁的使用臛_重要Q多了效率低下,了不能解决问题Q用多少个锁在什么粒度上用锁也是q个模块的关键所在?/span></span></p> <p><span><span><span>IocpClient</span></span><span>有一个锁</span><span><span><span>      </span>DECLARE_SIGNEDLOCK_NAME(send);<span>        </span>//</span></span><span>发送同步锁</span></span></p> <p><span><span>q个锁是用来控制发送数据链理的,该锁和前面提到的</span><span><span>volatile long m_nSending;</span></span><span>共同配合理发送数据链?/span></span></p> <p><span><span>可能有h会说</span><span><span>recv</span></span><span>怎么没有锁同步,是的Q?/span><span><span>recv</span></span><span>的确没有锁,</span><span><span>recv</span></span><span>不用锁是Z最大限度提高效率,如果和发送共一个锁则很多问题可以简化,但没有充分发?/span><span><span>iocp</span></span><span>的效率?/span><span><span>Recv</span></span><span>接收数据后就调用</span><span><span>OnReceive</span></span><span>虚函数进行处理。可以直?/span><span><span>io</span></span><span>U程内部处理Q也可以提交到某个队列由独立的逻辑U程处理。具体如何用完全由使用者决定,底层不做M限制?/span></span></p> <p><span> </span></p> <p><strong><span><span>七、服务器定时器管?/span></span></strong></p> <p><span><span>服务器定义了如下定时器函敎ͼ利用pȝ提供的时钟队列进行管理?/span></span></p> <p><span><span><span><span>        </span>bool AddTimer(int uniqueid, DWORD dueTime, DWORD period, ULONG nflags=WT_EXECUTEINTIMERTHREAD);</span></span></span></p> <p><span><span><span><span>        </span>bool ChangeTimer(int uniqueid, DWORD dueTime, DWORD period);</span></span></span></p> <p><span><span><span><span>        </span>bool DelTimer(int uniqueid);</span></span></span></p> <p><span><span><span><span>        </span>//</span></span><span>获取</span><span><span>Timers</span></span><span>数量</span></span></p> <p><span><span><span><span>        </span>int GetTimerCount() const;</span></span></span></p> <p><span><span><span><span>        </span>TimerIterator GetFirstTimerIterator();</span></span></span></p> <p><span><span><span><span>        </span>TimerNode *GetNextTimer(TimerIterator &it);</span></span></span></p> <p><span><span><span><span>        </span>bool IsValidTimer(TimerIterator it)</span></span></span></p> <p><span><span>设计思\是给每个定时器分配一个独立的</span><span><span>id</span></span><span>Q根?/span><span><span>id</span></span><span>可修改定时器的首ơ触发时间和后箋每次触发旉Q可Ҏ</span><span><span>id</span></span><span>删除定时器,也可遍历定时器。定时器旉单位为毫U?/span></span></p> <p><span> </span></p> <p><strong><span><span>八、模块类l构</span></span></strong></p> <p><span><span>模块中最重要的就是两个类</span><span><span>CIocpClient</span></span><span>?/span><span><span>CIocpServer</span></span><span>Q其他有几个cMq两个类zQ图C如下:</span></span></p> <table border=1 cellSpacing=0 cellPadding=0> <tbody> <tr> <td vAlign=top width=325> <p> </p> <p><span><span><img alt="" src="http://hi.csdn.net/attachment/201010/2/0_12860366862P0q.gif">图表</span><span> <span><span>1</span></span></span></span></p> </td> <td vAlign=top width=325> <p> </p> <p><span><span><img alt="" src="http://hi.csdn.net/attachment/201010/2/0_12860366934gcR.gif">图表</span><span> <span><span>2</span></span></span></span></p> </td> </tr> </tbody> </table> <p><span> </span></p> <p><span><span><span>CIocpClient</span></span><span>是完全流式的Q没有包概念?/span><span><span>CIocpMsgClient</span></span><span>?/span><span><span>CIocpClient</span></span><span>zQ内部支持包概念Q?/span></span></p> <p><span><span>class CIocpMsgClient : public CIocpClient</span></span></p> <p><span><span>{</span></span></p> <p><span><span>…</span></span></p> <p><span><span><span><span>        </span>virtual void OnDataTooLong(){};</span></span></span></p> <p><span><span><span><span>        </span>virtual void OnMsg(PKHEAD *ph){};</span></span></span></p> <p><span> </span></p> <p><span><span><span><span>        </span>bool SendMsg(WORD mtype, WORD stype, const char *pdata, int length);</span></span></span></p> <p><span><span>…</span></span></p> <p><span><span>};</span></span></p> <p><span> </span></p> <p><span><span>template <class TYPE></span></span></p> <p><span><span>class CIocpMsgClientT : public CIocpMsgClient</span></span></p> <p><span><span>{</span></span></p> <p><span><span>…</span></span></p> <p><span><span><span><span>        </span>void AddMsg(DWORD id, CBFN pfn);</span></span></span></p> <p><span><span><span><span>        </span>BOOL DelMsg(DWORD id);</span></span></span></p> <p><span><span>…</span></span></p> <p><span><span>};</span></span></p> <p><span><span><span>CIocpMsgClientT</span></span><span>模板cL持内嵌入式定义,如在</span></span></p> <p><span><span><span>CMyDoc</span></span><span>中可q样定义</span></span></p> <p><span><span>CIocpMsgClientT<CMyDoc> client;</span></span></p> <p><span><span>后面可以调用</span><span><span>client.AddMsg(UMSG_LOGIN, OnLogin);</span></span><span>兌一个类成员函数作ؓ消息处理函数Q用很方便?/span></span></p> <p><span> </span></p> <p><span><span><span>CIocpServerT</span></span><span>定义很简单,?/span><span><span>CIocpServer</span></span><span>zQ重载了</span><span><span>CreateNewClient</span></span><span>函数</span></span></p> <p><span><span>template <class TClient></span></span></p> <p><span><span>class CIocpServerT : public CIocpServer</span></span></p> <p><span><span>{</span></span></p> <p><span><span>public:</span></span></p> <p><span><span><span><span>        </span>//</span></span><span>如果</span><span><span>CIocpClient</span></span><span>z了则也需要重载下面的函数Q这里可以根?/span><span><span>nServerPort</span></span><span>分配不同?/span><span><span>CIocpClient</span></span><span>zc?/span></span></p> <p><span><span><span><span>        </span>virtual CIocpClient *CreateNewClient(int nServerPort)</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>                </span>CIocpClient *pclient = new TClient;</span></span></span></p> <p><span><span>…</span></span></p> <p><span><span><span><span>                </span>return pclient;</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span>};</span></span></p> <p><span> </span></p> <p><strong><span><span>八、应用D?/span></span></strong></p> <p><span> </span></p> <p><span><span>class CMyClient : public CIocpMsgClient</span></span></p> <p><span><span>{</span></span></p> <p><span><span>public:</span></span></p> <p><span><span><span><span>        </span>CMyClient() : CIocpMsgClient()</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span><span><span><span>        </span>virtual ~CMyClient()</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnConnect()</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span>Printf(“</span></span><span>用户q接</span><span><span>%s:%d</span></span><span>q接到服务器</span><span><span>\r\n”, GetPeerAddr().ip(),GetPeerAddr().port());</span></span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnClose()</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span>Printf(“</span></span><span>用户</span><span><span>%s:%d</span></span><span>关闭q接</span><span><span>\r\n”, GetPeerAddr().ip(),GetPeerAddr().port());</span></span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnMsg(PKHEAD *phead)</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span><span>        </span>SendData((const char *)phead, phead->len+PKHEADLEN);</span></span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnSend(DWORD dwbyte)</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span>Printf(“</span></span><span>成功发?/span><span><span>%d</span></span><span>个字W?/span><span><span>\r\n”, dwbyte);</span></span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnInitialize()</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span><span>        </span>m_sendbuf = newbuf(1024);</span></span></span></p> <p><span><span><span><span>        </span>m_recvbuf = newbuf(4096);</span></span></span></p> <p><span><span>}</span></span></p> <p><span> </span></p> <p><span><span><span><span>        </span>friend class CMyServer;</span></span></span></p> <p><span> </span></p> <p><span><span>};</span></span></p> <p><span> </span></p> <p><span><span>class CMyServer : public CIocpServer</span></span></p> <p><span><span>{</span></span></p> <p><span><span>public:</span></span></p> <p><span><span><span><span>        </span>CMyServer() : CIocpServer</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span> </span></p> <p><span><span><span><span>        </span>virtual void OnConnect(CIocpClient *pclient)</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span><span>                </span>printf("%p : %d </span></span><span>q端用户</span><span><span>%s:%d</span></span><span>q接到本服务?/span><span><span>.\r\n", pclient, pclient->m_socket, </span></span></span></p> <p><span><span><span><span>                        </span>pclient->GetPeerAddr().ip(), pclient->GetPeerAddr().port());</span></span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnClose(CIocpClient *pclient)</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span><span><span>        </span>printf("%p : %d </span></span><span>q端用户</span><span><span>%s:%d</span></span><span>退?/span><span><span>.\r\n", pclient, pclient->m_socket, </span></span></span></p> <p><span><span><span><span>                        </span>pclient->GetPeerAddr().ip(), pclient->GetPeerAddr().port());</span></span></span></p> <p><span><span>}</span></span></p> <p><span><span><span><span>        </span>virtual void OnTimer(int uniqueid)</span></span></span></p> <p><span><span>{</span></span></p> <p><span><span>If(uniqueid == 10)</span></span></p> <p><span><span>{</span></span></p> <p><span><span>}</span></span></p> <p><span><span>Else if(uniqueid == 60)</span></span></p> <p><span><span>{</span></span></p> <p><span><span>}</span></span></p> <p><span><span>}</span></span></p> <p><span><span><span>//</span></span><span>q里可以Ҏ</span><span><span>nServerPort</span></span><span>分配不同?/span><span><span>CIocpClient</span></span><span>zc?/span></span></p> <p><span><span><span><span>        </span>virtual CIocpClient *CreateNewClient(int nServerPort)</span></span></span></p> <p><span><span><span><span>        </span>{</span></span></span></p> <p><span><span><span><span>        </span>//<span>      </span>If(nServerPort == ?)</span></span></span></p> <p><span><span>//<span>              </span>…</span></span></p> <p><span><span><span><span>                </span>CIocpClient *pclient = new CMyClient;</span></span></span></p> <p><span><span>…</span></span></p> <p><span><span><span><span>                </span>return pclient;</span></span></span></p> <p><span><span><span><span>        </span>}</span></span></span></p> <p><span> </span></p> <p><span><span>};</span></span></p> <p><span> </span></p> <p><span><span>Int main(int argc, char *argv[])</span></span></p> <p><span><span>{</span></span></p> <p><span><span><span><span>        </span>CMyServer server;</span></span></span></p> <p><span> </span></p> <p><span><span><span><span>        </span>server.AddTimer(60, 10000, 60000);</span></span></span></p> <p><span><span><span><span>        </span>server.AddTimer(10, 10000, 60000);</span></span></span></p> <p><span> </span></p> <p><span><span><span><span>        </span>//</span></span><span>W二个参Cؓ</span><span><span>0</span></span><span>表示使用默认</span><span><span>cpu*2</span></span><span>?/span><span><span>io</span></span><span>U程Q?/span><span><span>>0</span></span><span>表示使用该数目的</span><span><span>io</span></span><span>U程?/span></span></p> <p><span><span><span>//</span></span><span>W三个参Cؓ</span><span><span>0</span></span><span>表示使用默认</span><span><span>cpu*4</span></span><span>个逻辑U程Q如果ؓ</span><span><span>-1</span></span><span>表示不用逻辑U程Q逻辑?/span><span><span>io</span></span><span>U程内计?/span><span><span>>0</span></span><span>则表CZ用该数目的逻辑U程</span></span></p> <p><span><span><span><span>        </span>server.StartServer("1000;2000;4000", 0, 0);</span></span></span></p> <p><span><span>}</span></span></p> <p><span> </span></p> <p><span><span>从示例可看出Q对使用该网l模块的人来说非常简单,只要z两个c,集中_֊处理消息函数卛_Q其他内容内部全部包装了?/span></span></p> <p><span> </span></p> <p><strong><span><span>九、后?/span></span></strong></p> <p><span><span>我研I?/span><span><span>iocp</span></span><span>大概?/span><span><span>2005</span></span><span>q初Q前一个版本的|络模块是用多线E?/span><span><span>+</span></span><span>异步事g来做的,</span><span><span>iocp</span></span><span>|络模块基本成型?/span><span><span>2005</span></span><span>q中Q后来又持箋q行了一些改q,</span><span><span>2005</span></span><span>底进入稳定期Q?/span><span><span>2006</span></span><span>q又做了一些大的改动,后来又持l进行了一些小的改q,目前该模块作为服务程序框架已l在很多目中稳定运行了</span><span><span>1</span></span><span>q半左右的时间。在此感谢大宝?/span><span><span>Chost Cheng</span></span><span>?/span><span><span>Sunway</span></span><span>{众多网友,是你们的讨论l了我灵感和持箋改进的动力,也是你们的讨论给了我把这些写出来的决心。若此文能给后来者们一点点启示我将甚感ƣ慰Q若有错误欢q批评指正?/span></span></p> <p><span> </span></p> <p><span><span>oldworm</span></span></p> <p><span><a href="mailto:oldworm@21cn.com"><span>oldworm@21cn.com</span></a></span></p> <p><span><span>2007.9.24</span></span></p> <img src ="http://www.shnenglu.com/oldworm/aggbug/128473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/oldworm/" target="_blank">袁斌</a> 2010-10-03 14:25 <a href="http://www.shnenglu.com/oldworm/archive/2010/10/03/128473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IT行业能说的h太多能做的h太少http://www.shnenglu.com/oldworm/archive/2010/10/03/128472.html袁斌袁斌Sun, 03 Oct 2010 06:24:00 GMThttp://www.shnenglu.com/oldworm/archive/2010/10/03/128472.htmlhttp://www.shnenglu.com/oldworm/comments/128472.htmlhttp://www.shnenglu.com/oldworm/archive/2010/10/03/128472.html#Feedback2http://www.shnenglu.com/oldworm/comments/commentRss/128472.htmlhttp://www.shnenglu.com/oldworm/services/trackbacks/128472.htmlIt行业从业十几q_虽然接触的hq不多,但算上网l上有点交往的hQ也不算太少Q阅读过无数代码Q很Ҏ得出q样的感悟,国内it行业能说的h太多Q能做的人太,能说大意是能说会道Q说h头头是道Q从架构Cpd模块到接口都能说得很专业Q但实施h׃行,不但架构做不好,接口定义不清Q就q小模块也未见得可搞定Q这L人实在是太多Q之前一直以Z个项目组多几个h总能加快炚w度Q现在终于明白,一个项目组加几个不合适的Z但不能加速反而要降速,甚至直接D目开发失控、失败。关键模块如果让一个不U职的h去负责,最l该模块可能需要耗费核心人员更多旉M改,甚至要重写,dD目延时Q重则导致项目失败?/span>

实施一个成功的it目Q只说技术不说市场)Q概括v来就是一句话Q找合适的人做合适的目。说hҎ做v来难啊,每个人都有他的领域,如果找来一个擅?/span>a领域的让他做b领域的项目也未必做得好,虽然有的人学习能力超强,但d是需要时间积累经验的。见q听说过很多开发失败的例子Q莫不如此,曑ָ人家优化一个电信计贚w目,原实施的人只会用数据库,所有的计算全用数据库实玎ͼ速度比其Ҏ慢一个数量以上Q将计算需要的数据预装入内存,之后全在内存里面查找计算Q速度一下提高了上百倍,修改后速度领先其对手好几倍,其实q个修改很容易,只要几天旉搞定了Q还包括熟悉他们的数据及规则?/span> q帮别h看过一个棋牌的目Q原目l十几个人搞?/span>1q多Q整?/span>40多万行代码,l果bug不断Q一直不能稳定运行,目l无搞得定,我看了之后下的结论是重写Q他们傻gQ还以ؓ改一个项目的旉肯定要少Q毕竟写了那么多代码Q他们那些外行哪里知道,修改一个漏z无数的工程哪有重写快啊Q这是典型的找了一不恰当的h做了一个不恰当的项目,几百万投入打了水漂,要是让一个有能力的h设计把关Q他那棋牌项?/span>100万够开发得出来了?/span>

刚毕业那会做目的时候带q几个水q差的手下Q都是俺领导招的人)Q他们最常说的话?#8220;优化”Q我把某某地?#8220;优化”了一下,呵呵Q外行要听到q个q以为真的是优化呢,其实很多时候他只是改写了一下,是不是算优化q值得商量Q大多数时候都不上优化,有的时候还攚w引入了更?/span>bug。对高手来说更喜Ƣ说重构Q我把某某模块重新设计了一下,以前模块有哪些缺P重新设计一下之后这些缺陷就不存在了Q还有某某好处,{等Q高手着g大局Q低手只能看C个小角落Q高手优化关键之处,低手优化无关紧要之处。看豆瓣|技术发展,是一个不断重构的q程Q看qq?/span>98q开始到现在的蜂鸟内核,大的重构?/span>3ơ了Q完全重?/span>3ơ了。最q迅L于官Ҏ?/span>v6开发失败,我之前在里表达q我的观点,我估计他?/span>v6是开发失败了Q所以一直以v5着Q现在等?/span>v7出来l于承认了,q种自诩市D100亿美刀的公司这么长旉的开发还能失败,׃要说公司小团队了,见光ȝ目很多Q未见光ȝ目更多?/span>

国内真正懂得开发的老板很少Q大多数老板觉得一个h开5w 10w的月薪太高了Q这个待遇找1w的能扑֥几个呢,其实他们不知道,it行业一个重要的?/span>100个普通的人,甚至不可比较Q因Z个普通的人去做一个项目可能根本不能完成,成功?/span>0Q?/span>1Q?/span>0q个比值是无穷大啊Q可惜等老板们失败了几个目之后才能悟出q个道理Q?/span>it目做得好和做不好的差别不是差一点的问题Q而是1?/span>0的问题。俗人L忙忙碌Q天天维护自己前一天制造的bugQ看h很敬业,高手L懒懒散散Q因?/span>100天后可能出现的问题都已经了然于胸Q于是整天看h无所事事Ӟ不懂的老板很可能青睐于前者而打压后者。也正因说的人太多,懂行的老板又太,所以得整个行业充斥着躁和急功q利Q很多关键职位其实只是个鹦鹉在顶着Q有能力的h被压Ӟ悲哀啊。千里马难找Q伯乐更难找啊?/span>



袁斌 2010-10-03 14:24 发表评论
]]>
Ʒþù鶹99վ| ޹˾þۺ| ŷ˾þۺ | վþþ| þۺϾƷ| Ů˸߳þþýˮ| þþwww˳| þþþþüƷþþ| þ99ۺϾƷҳ| ŷ龫Ʒþþþ| Ʒ99þþƷ| 9999Ʒŷþþþþ| Ʒݾþþþ| AëƬþ| þþƷһ| þþƷ99þ˿| ɫۺϾþ| þݺҹҹavapp | 69Ʒþþþþ޾Ʒ| ߾þþƷĹ| ëƬŷëƬþþ| ھƷþ޻ | ˾þþþƷ | þþþseɫ͵͵޾Ʒav| AþþƷ| ҹþӰԺ| þþƷĻ| ŷþ޾Ʒ| þۺϸϾþù| ĻۺϾþ2| þۺϳ| þþþavרˮ| LƷþ| ŷþþþƷӰԺ| 99ŷþþþƷѿ| 99þù뾫ƷѾþþþ | ˾þô߽AVɫɫ| ݺݾþŷר| ˾þþƷһ| ݺɫþ| ƷŮ߳׾þþ |