Headchen 请进!请继续说说‘蚂蚁’与‘快车’的一些问题!其它高手也可进来讨论! (200分)

  • 主题发起人 主题发起人 kk98
  • 开始时间 开始时间
K

kk98

Unregistered / Unconfirmed
GUEST, unregistred user!
在http://www.delphibbs.com/delphibbs/dispq.asp?LID=456229中你欲言又止,请在
这里继续说完吧!
>>>
1.两者均采用了多线程技术,每一个“蚂蚁”或一个“快车”采用一个线程,两者均采用
的是winsock2的异步选择模型,这种模型把异步事件映射为Windows的消息,这样就可以通过
Windows的消息处理网络事件,比如数据到达,下载失败等。若要在工作线程中处理消息,则
Windows会自动给每个线程建立消息循环。两者不同的是:网络蚂蚁的Winsock是在工作线程
中建立的,也就是说,在工作线程中首先创建一个窗口,再把winsock“选择”到此窗口,这样
当此“Winsock”发生了事件,会发送消息给工作线程中的窗口,工作线程中的窗口会处理这些
事件。而“快车”的处理方法是在主线程中建立了所有窗口,并创建所有的Winsock并“选择”
到相应窗口,根据多线程的原则“那个线程中创建的窗口,应该在此线程中处理所有的消息”,
“快车”则在工作线程中干了些什么呢?在不断地尝试“接收”数据,而不理会数据是否到达,(
它根本就没有处理相应的消息),这样的结果是“接收”100次,仅仅能够有大约7-8次能够接收到
数据,在大多少情况下,工作线程在作“无用功”,可见“快车”在大多少情况下是在“空跑”,
这样的方式能有效率吗?现在一般情况下,用户的电脑的速度都比较快,可以忍受这种“空跑”,
但从作软件的角度来看则不可取。
写了不少了,还有很多问题,本来想写,竟然招致如此的谩骂,我还是打住吧,看来还是少参和为
好。顺便提一下:有兴趣的可以通过Boundchecker等调试工具跟踪一下就知道了。

还有也可介绍一下Boundchecker等调试工具!
 
说实话,本来不想参和了,看你这么热心,我就谈一谈不太成熟的想法,大家有不同意见可以
交流,我不愿意看到与技术无关的谩骂了。

首先,我不是什么高手,可能“很低”,但我原意把我知道的和大家交流,大家“对事不对人”。
由于涉及到的方面比较多,我想分几个专题谈一谈我的看法:


关于下载软件的多线程:

一定要用多线程吗?

相当一部分人认为,若要实现多个网络任务同时进行(比如多点传送),要采用多线程的方式,其实这种看法是片面的。
不采用多线程,照样可以实现多个网络任务同时进行,你可以创建多个winsock就可以了,采用异步模式,那个
Winsock发生了事件需要处理,则处理就可以了。

多线程能够加快下载速度吗?

回答是不一定。多点下载在一些情况下可以加快速度,但多点下载并不意味着一定要多线程,原因上面我已经
说了。

下载软件采用多线程有什么好处吗?

多线程也不能滥用,一般而言,对于客户端软件,一个进程中线程的数量超过16,则意味不太合理了,因为线程
的维护需要大量的Windows资源,而且占用CPU时间,从效率来说,并不是线程越多越好。
一般情况下,在线程环境中,我们把线程分为两类:主线程和工作线程,一般把长时间,大量的处理任务放在
工作线程,防止主线程执行长时间工作而导致界面无反应。另外是考虑到“实时性”,某些工作必须得到“实时”
处理,把他放在工作线程中。
对于下载任务而言,下载的瓶颈是“传输速度”而不是“处理速度”,处理任务仅仅是把下载的数据安全的存放
在磁盘上而已。所以采用一个winsock对于一个工作线程,此工作线程大部分时间处于“等待”下载数据的状态,而传输
是通过调用相关的API由Windows的网络层来处理的,所以在应用程序中建立工作线程专门用来“等待”就不是什么好
主意了。当然像 FlashGet在工作线程中进行“空跑”作无用功显得更不可取了。从实时性角度来说,若对传输缓冲
区的数据得不到及时处理,有可能影响下载速度或造成“溢出”,关于“溢出”的问题一般不严重。由于“处理”的
过程比较简单,所用时间远远小于等待时间,故不会造成“实时”性的问题。

那么是不是就不需要多线程了?

回答也是不一定,我认为,可以把所有的下载任务全部放在一个工作线程,和主线程分开,这样防止主线程处理
长时间任务而不能对下载任务作出及时的处理,以影响下载速度。这样减少了资源的占用,提高了效率。也减少
了线程之间通讯等多种问题,减少了隐患。
当然你也可以采用netants的方法,一个Winsock采用一个线程,但这样并没有太多的好处,反而增加了复杂性。

多线程Winsock应如何创建?

因为当采用“异步选择模型”时,需要创建窗口和winsock相关连,接收Winsock事件,这样窗口在那个线程中创建
是非常重要的,根据“在哪个线程中创建窗口,则在此窗口中处理所有此窗口的消息”的原则,应该把Winsock相关的
窗口在相应的工作线程中创建(netant就是这么作的,而FlashGet则企图在一个线程中创建窗口,则另外一个线程中
处理他的消息,显然是比较荒唐的,因为他们不在一个消息循环中,造成大量的“空跑”)。
当然多线程还要注意很多问题,特别是采用Delphi编程时,相当多的控件不是线程安全的,甚至连创建窗口都需要
自己编程实现,当然这是另外一个问题,这里就不罗嗦了。

多点下载一定能提高下载速度吗?

注意:我这里说的是“多点”而不是“多线程”,多线程仅仅是实现多点下载的一种方法而已。
对于比较大的文件下载,多点毫无疑问会加快下载速度,但对于比较小的文件而言,应该从总体的下载用时来考虑,
一个下载过程一般而言是这样的(比较简单的说一下),
连接主机->发送下载命令->接收数据... ->完成->等待一段时间(为了稳定缘故)->再连接->....
当文件比较小时,连接和等待的时间占用了比较大的比例,从而使得整个下载用时不经济,netant和FlashGet为了
克服此问题,提高了“最小分段”的参数设置,但一般用户那里会研究这些东西?
 
学习
听课。
 
关于Boundchecker,你可以到www.51delphi.com上面下载一个,使用一下就明白了。
 
听上去挺高深,不过你能解释为什么快车的速度比蚂蚁快呢? 我前两天在
一个电影下载站点看到下载软件的调查,几乎99%的人使用快车,看来他们都有病哈。
 
你又来了!我一再说过,从使用角度来说,两者差不多,FlashGet的一些功能甚至比netants强,
比如当不知道文件大小的下载功能。我这里说的是哪一个软件的实现方式比较合理,值得借鉴。
关于下载速度,市场上大凡用多点下载的软件没有多大差别,netant在分段处理上还需要优化,
比如当一段下载完毕后,不管下一段是否已经开始下载,他的处理方法均是:断开->等待->连接,其实
完全可以一直下载下去,让没有开始的蚂蚁停止,重新分配下载段。
FlashGet的下载管理功能比网络蚂蚁强,另外他的营销作的也不错,也许这是使用他的人数比较多的
原因。但我们这里不是探讨市场营销问题,若你有见解,可以发表出来,因为这里是“技术论坛”,与技
术无关的问题一般情况我不愿意多纠缠。
 
to 一个过客:
这个论坛是一个技术交流的地方,不论对错,你有什么高见也可以说出来,
让大家学习,但请不要对别人发泄不满情绪。

to Headchen:
请继续说说你对网络方面的研究心得吧。

别的高手请尽情发言。
 
看了你们的发言我有不吐不快之感,不过是纯技术的,与蚂蚁、快车之争无关。
我主要是想谈一谈winsocket的几种工作模型(假设都采用多线程):
1.阻塞下的SELECT
就是在线程中不断的调用select函数,以判断是否有连接或数据到来。
这种方法效率低下不过最容易编写。indy采用的就是这种方法。
2.异步选择模型
上面已有介绍,不过他必须创建窗口,建立消息循环机制,而且是一个连接就要
开一个线程。这种方法比第一种好了许多,不过只适合做client。Delphi的socket
控件,ics采用的就是这种方法。
3.重叠IO模型
利用重叠结构,允许你几个线程同时操作在同一个套接字上,可以同时读或同时写或
边写边读;或者一个线程操作多个套接字。举个例子,你可以创建3个线程,1个处理
连接;1各处理所有连接的读;1各处理所有连接的写。平时各个线程处于sleep状态,
不会浪费cpu的时间,如果有数据到达或写操作成功等网络事件发生,线程就会脱离
slee状态,系统会用事件(不是消息)或回调函数通知你。这是做client最好的方法
也可以做server,不过连接不能过多。
4.完成端口重叠IO操作模型
特殊的重叠IO模型,NT/2000专用,做server比选。跟重叠IO模型差不多,不过性能
更好。iis采用的就是这种方法

 
To mywyn:
2:对于异步选择模型,必须建立窗口,这是正确的,但一个连接就开一个线程?这是从什么地方
得出的结论?正因为并不是一个连接就需要一个线程,才有我上述的结论。对于Client来说,一
个连接一个线程是没有必要的。
 
to Headchen:
是小弟犯了低级错误,没有考虑到一个线程可以创建多个窗口。
另外,老兄你怎么把蚂蚁、快车分析的这么清楚。是不是用了工具?能告诉我吗?
我一直在找。


 
佩服Headchen:
是否是蚂蚁的作者,呵呵!
其实我想说的,系统处理线程的情况,
原来的文件我找到贴上来,
win31是软件维护线程必须考虑多方面的问题,
win32采用时间片段处理各个线程,系统分配给每个
线程一段时间,系统就在各个线程之间循环!
 
一群笨蛋!分析这么多顶个屁用,快车比蚂蚁用户多无数倍是不争的事实,
而造成这种情况的原因恐怕并不仅仅是下载管理或是什么营销做的好吧?哼哼

不过我要承认,我不懂这些什么线程什么套接字,所以也不会胡乱分析。
ok,你们这帮家伙继续讨论,老子去也。别忘了讨论完一起高呼“蚂蚁万岁”!哈哈!
 
to: 一个过客:您这样不负责任的言论只能造成别人对您的印象大打折扣。我都怀疑您是
flashget的说客,专门来给蚂蚁抹黑。

To mywyn:

2.异步选择模型
上面已有介绍,不过他必须创建窗口,建立消息循环机制,而且是一个连接就要
开一个线程。这种方法比第一种好了许多,不过只适合做client。Delphi的socket
控件,ics采用的就是这种方法。

一个线程可以管理多个socket,并不是每个socket都需要一个线程。您关于这样的模型只适合
做client的结论我也表示反对。
至于说应该每个线程管理多少个socket,是要依靠benchmark来决定的。其实只要CPU足够强劲,
每个线程已经足够管理所有的socket。
比如说apache,在unix上的apache并没有采取多个进程的方式,而是用一个大循环来处理所有
的socket连接,用select来判断有数据到来的socket进行操作。您所说的
"就是在线程中不断的调用select函数,以判断是否有连接或数据到来。
这种方法效率低下不过最容易编写"就是这种模型。
apache的成功可以有力的反驳关于这种模式效率低下的结论。

就算在windows平台中,我认为采用线程只能带来编程上的方便,而效率还是这种循环
select最高。

我接触过的一个实际的例子是,一共有5个线程,一个线程专门负责做负载平衡调度,接受新
连接,然后引导client重新连接到其他4线程中最低负荷的一个去,每一个线程都执行一个
大循环,使用select处理数据。我们的测试是这个程序运行于一台DELL 6500服务器, 4个Pentium xeon CPU(主频,
还有是PII还是PII已经忘了),使用2G memory,
12台Dell dimension 作为一组客户机,每台机器执行50个虚拟的客户端模拟器。

服务器和客户机之间是100M的网络。

一共上了6组客户端,负载稳定后每个CPU的占用率是70%,每个client的命令响应时间<1s。
如果负载下降一半,相应时间下降到只有不到0.1s。

最后的极限测试中,增加客户端的数目,直到我们用光了server windows的所有socket ...
(赫赫,够狠吧?好像是不到30000,不是一个整数,也不是32768).每个client socket
响应时间不到5s。

这个结论就是说,线程多并不能带来实际的性能提升。对于像flashget,netants这样
的低负荷下载来说,关键在于减少在两次select之间的时间消耗。这才是有实际意义的。

而对于有些人对于netants和flashget之争,我觉得没有任何意义。我的同事中既有
用flashget的,也有用netants的。我用flashget,另一个水平很高的同事就是用netants.
一个软件的选择并不能说明使用者的水平高低。
我主要是嫌netants界面太花哨,无谓的消耗系统资源而已。对于普通的下载,
他们都已经足够了。就算时间有差别,相信也不会>5%。这样已经属于同一级别。
 
曹大侠真是高论,不管是什么,只要能下载东东就行了,何必这样呢,
每个都有不同习惯,个人的喜好,不能决定一个软件的优劣。
 
to headchen:
我从您的论述上来看,您并不赞同flashget的这种只用于一个进程,来select的方法。
但是其实如果带宽足够高,导致数据包到达的速度和select循环的次数在一个数量级
的情况下,flashget的效率更高。您的测试很可能是在低速率的情况下进行的,这时候
flashget主线程‘空跑’的情况的确存在。我认为这样的实现无可厚非,大多数工业级
的http server包括apache, xitami 都是这样做的。
 
关注.不过比起 小 ANT,我更加喜欢 FLASH GET.我觉得这个比较COOL,好用.[:)]
 
T0:曹晓钢
您的部分观点我是同意的,就效率而言,线程的增加并不一定能够增加效率。
具我的调试结论,FlashGet采用的也是异步选择模型,他是在主线程中建立了所有的Socket和相应
窗口,而在工作线程中(很多个)不断地recv() 然后sleep(2),从recv()返回的结果来看,10有8,9是失败,
然后调用GetLastError来判断是什么原因再作处理,我对这种处理的方法大惑不解,难道有其他玄机?从CPU
占用率的角度来看,确实也加重了CPU的负担,不过对于低负荷的下载软件而言,矛盾不太突出而已。

另外,我们其实没有什么“蚂蚁/快车之争”,我本人是本着学习别人的先进经验的角度去研究别人的实现
方法,“去伪存真”,提高自己的编程水平。因为蚂蚁和快车是都是比较优秀的软件,我们从程序员的角度学
习和研究,有了我上述的结论,并不一定正确,但我认为用“批判地学习”的方法对自己是有好处。同时把自己
的体会和别人交流对大家也是有好处的,这里不带任何除了技术之外的因素,我和两者的作者均不认识。
 
to Headchen:
我说“蚂蚁/快车之争”,针对的不是你,是一个过客。
 
to all:
我发起这个贴子的本意是请Headchen说说蚂蚁与快车的工作原理,引来各位高手讨论
Socket与线程的开发经验,让大家学习学习,并不是发起(也拒绝)一场“蚂蚁/快车之争”
 
后退
顶部