[多进程]多进程同步完成的效率问题?

77 views
Skip to first unread message

sagasw

unread,
Jan 2, 2010, 8:56:22 PM1/2/10
to pongba
09年末的几天在改写一份代码,从单线程、单进程改到多进程,目的是想提高处理速度,
但是收效非常不明显,甚至还有些效率降低的问题,想跟大家咨询一下,如何改进?

我们的代码是基于Windows的(所以Linux那些技术是没法用的),主要完成这样一系列工作。

1,从cab中解压缩一系列文本文件(大约三四万个)到临时目录,解压以后大概700M,这个文本文件的数量只会越来越多。
2,我的程序解析(动作a)文本文件,判断是否满足一定的条件,然后需要注册一些信息到注册表中(动作b)。
3,从临时目录中删除(动作c)。

原来的代码是基于单线程处理,每个文件都要完成动作abc,如果时间为T,那么基本上一万个就是10000*T这样。
我的第一个改进方案是基于多线程,建立消费、生产关系来处理,但是因为整个进程共享单一manager对象(CSingleThreadModule),而动作abc需要访问manager对象的成员,
另外原来的系统设计完全没有考虑多线程访问,修改代价比较大,所以先否定了这个方案,并没有做性能测试。

第二个方案是多进程,另外建立几个进程,然后通过共享内存来进行进程通讯,花了两三天时间调试完成。
主进程只负责建立子进程,然后建立同样数目的子线程负责发送新任务到共享内存A,
然后等待读取共享内存B接收动作a和b的结果(成功或失败),如果失败了,主进程要写log。

子进程从共享内存A读入任务,然后完成动作a和b,把结果写入共享内存B。
这样主程序中每个子线程与子进程都对应了一个生产、消费关系。

但是问题来了,很奇怪的是,这个方案在双核机器上测试,并没有节省多少时间,
想问问大家,这种设计有问题么?该如何改进实验?


------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------

Fei Yan

unread,
Jan 2, 2010, 9:17:29 PM1/2/10
to pon...@googlegroups.com
我对Windows编程基本没有经验;
不过一个通用的经验是:

你们的项目有没有做profiling?能否确定性能低下的瓶颈在哪里?
根据你的描述,我揣测是CPU load过高,但有没有仔细观察过运行期的行为,
具体哪一部分占用的CPU比预期的要多?

老赵的博客里边有很多windows下VS2005做profiling的东东(他的大部分是c#的,我也只懂个大概),可能会有所帮助。

我的一点拙见:
1> Windows创建进程的开销是比传统Unix要大得多,
       或许进程context switch的开销已经抵消了你的分离设计带来的好处。
2> 共享内存的通信方式是否并没有缓解你问题的根本?我怀疑问题在解压缩本身这个操作
3>   压缩cab的过程是怎样的?能否将压缩过程并发起来?
这些假设我觉得都应该在profiling的数据之上


我碰到过类似的状况,但是是要生成xml并用tar压缩;多的时候会有上千个甚至更多个并发任务;
只是我的项目是Unix的。

2010/1/3 sagasw <sag...@gmail.com>

sagasw

unread,
Jan 2, 2010, 10:05:21 PM1/2/10
to pon...@googlegroups.com
profiling在这一部分没有做,但是准备对我改动这一块做。相关Visula C++ profiling我也早写过相关文章
http://sunxiunan.com/?p=1216

只是这次有些自以为新方案应该有所改进,所以没有做详细的数据收集。
估计还是需要做一下实验,自以为是果然害人。

CPU load过高是我需要的,因为要求是快速完成任务,尽可能利用cpu是目的。
另外设计方案中进程创建的开销几乎不需要考虑,因为只建立一次,后面都是在反复使用而已。
另外进程间是通过share memory通讯,5个进程-》子线程同时运行的生产消费模型,应该是效率比较高才是。

解压缩本身不在这次改进的目标,它是前面的一个动作,可以看我描述的过程。当然也可以优化,只是不是现在的问题。


------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/3 Fei Yan <skyscr...@gmail.com>

zhang xuecheng

unread,
Jan 2, 2010, 10:24:42 PM1/2/10
to pon...@googlegroups.com
你有没有量过过程a的时间? 往硬盘里写三四万个文件的话应该耗时挺长的

2010/1/3 sagasw <sag...@gmail.com>



--
   best regards,
   zhang xuecheng
   http://veryzhang.cn

陨落雕

unread,
Jan 2, 2010, 10:25:11 PM1/2/10
to TopLanguage
听起来像IO瓶颈。你看看你的Disk IO和Memory IO满没有。

redsea

unread,
Jan 3, 2010, 1:59:38 AM1/3/10
to TopLanguage
每个进程并发做 1, 2, 3 ?
这样性能不会好, 你碰到硬盘寻道开销了.
你可以试试看, 用total commander 或者 total copy 从一个分区复制10000个小文件到另外一个分区, 是一个窗口
10000 个快, 还是开两个窗口各 5000快.

这个程序, 有 io 和 cpu 两个各自可能是瓶颈, 如果两个动作互相等待, 那么性能也会上不去.

从 io 的角度看, 性能好的做法应该是:
首先读一批 cab, 然后删除这批 cab, 然后写一批文本文件, 从文件系统布局来看, 这样有最大的可能连续读写的机会多, 磁头来回绕的几
率最小.

用多线程/多进程来做, 就应该分为 io线程和解压线程, 中间应该有很大的 buffer.

另外, 如果不打算运行在 P3 600 之类的慢机器上的话, 我很怀疑解压 cab 这一块, 需要用多线程/多进程, 因为解压 cab 的
cpu 开销应该不大的, 只需要 io 线程和 解压线程并发就好了.

sagasw schrieb:


> 09年末的几天在改写一份代码,从单线程、单进程改到多进程,目的是想提高处理速度,
> 但是收效非常不明显,甚至还有些效率降低的问题,想跟大家咨询一下,如何改进?
>
> 我们的代码是基于Windows的(所以Linux那些技术是没法用的),主要完成这样一系列工作。
>
> 1,从cab中解压缩一系列文本文件(大约三四万个)到临时目录,解压以后大概700M,这个文本文件的数量只会越来越多。
> 2,我的程序解析(动作a)文本文件,判断是否满足一定的条件,然后需要注册一些信息到注册表中(动作b)。
> 3,从临时目录中删除(动作c)。
>

许峰峰

unread,
Jan 3, 2010, 2:08:13 AM1/3/10
to pon...@googlegroups.com
 觉得应该先profiling确定性能的瓶颈。
 这里用多进程,多线程,都是为了增加并发能力。

简单来考虑:一个cpu同一时间就能执行一个运算,所谓的并发只能cpu和io并发。

这里不清楚你程序io的时间和cpu的时间比例大概是怎么样的。

如果cpu的时间很大,那么只靠多进程,多线程没有太多的效果,主要看改进算法或者增加cpu。

可以考虑1解压得开始时,动作a开始,动作b写修改注册表可以合并写入也就是等到一定数量的结果时,一次性写入。
(不明白写注册表时,注册表是否会lock之类的,如果这个动作很慢,那么很多时候,多个进程在等待写注册表)


还有,现在的多进程模型是集中式管理,共享内存访问会存在lock问题。如果处理得问题本都是独立的话,能否让每个线程各自走自己的流水线,完成所有动作。

最重要的还profiling,看程序的性能瓶颈,这样才好确定方案。



2010/1/3 陨落雕 <geo...@gmail.com>

pvoid

unread,
Jan 3, 2010, 11:42:33 PM1/3/10
to TopLanguage
同意,并发的话最好能把磁盘i/o和其它的分开,避免多线程抢磁盘
不知道楚楼主是一遍解压cab,一遍解析文件,还是先全部解压出来,再来解析?另外,不知道cab解压缩是调用外部程序还是自己写代码实现的
我有这样一些想法供参考
1 如果每个文本文件都不大,是否可以考虑直接解压到内存来做解析,这样可以避免写磁盘的开销
2 可以考虑不要每次b操作完了之后删,而是若干次b操作完成之后删,或者干脆等所有文件处理完了再删
3 a和b操作应该是并发的,a解析文件后得到必要的信息,然后就可以交给另一个线程来做b操作,尽量将a操作中跟磁盘I/O无关的代码移到b操作中执

如果b操作不是很复杂的话,那程序的主要瓶颈应该就在磁盘I/O了,最好是能够让某个线程专门处理相关的磁盘操作,以避免多个线程的竞争降低磁盘性能。
并且像ls说的,减少不必要的磁盘随机访问很重要

sagasw

unread,
Jan 4, 2010, 12:34:58 AM1/4/10
to pon...@googlegroups.com
磁盘IO只有几个地方,1)解析开始时读取读入所有内容。2)解析出错时写log。
1)的时间相比整个解析需要的时间要短很多,基本上不需要优化。2的时间应该也非常短,因为最后写出来的log不过就十几k。
如果解析结果成功的话,是不需要写log的。
而且为了尽可能减少磁盘操作,也去掉了删除文件这个动作,速度一样没有改进。

解压cab是我提的一个多余条件,实际上它在这次优化是不需要考虑的一个单独过程。主要操作就是这个
“程序解析(动作a)文本文件,判断是否满足一定的条件,然后需要注册一些信息到注册表中(动作b)”

现在主流的台式机机型应该都是双核了吧(什么p3 600客户那里不可能有的),我的疑问就是,对于双核机器,单进程单线程的应用改成多进程多线程并发,IO很少主要是cpu运算,应该有一定的速度提高,可结果是非常不明显,
准备build一个安装版本,做一次完整比较。


------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/4 pvoid <fredc...@gmail.com>

陨落雕

unread,
Jan 4, 2010, 1:14:36 AM1/4/10
to TopLanguage
双核?那种玩具机器玩并行化编程完全是浪费时间啊。而且磁盘IO是一方面,还有内存IO。另外,双核的Windows机器玩多进程就是浪费时间和金钱,
Windows的一个进程那么贵。用多线程没什么不好的,别被网上那些rant吓到了。

几方面:看cpu的cache miss怎么样,写操作是怎么样的,有没有读写依赖。Windows注册表应该是带锁的,把要写Windows注册表的
东西放到自己的本地队列里面,结束的时候用一个线程把这两个队列里面的东西写进去就可以了。

On Jan 4, 12:34 am, sagasw <sag...@gmail.com> wrote:
> 磁盘IO只有几个地方,1)解析开始时读取读入所有内容。2)解析出错时写log。
> 1)的时间相比整个解析需要的时间要短很多,基本上不需要优化。2的时间应该也非常短,因为最后写出来的log不过就十几k。
> 如果解析结果成功的话,是不需要写log的。
> 而且为了尽可能减少磁盘操作,也去掉了删除文件这个动作,速度一样没有改进。
>
> 解压cab是我提的一个多余条件,实际上它在这次优化是不需要考虑的一个单独过程。主要操作就是这个

> *"程序解析(动作a)文本文件,判断是否满足一定的条件,然后需要注册一些信息到注册表中(动作b)"*


>
> 现在主流的台式机机型应该都是双核了吧(什么p3
> 600客户那里不可能有的),我的疑问就是,对于双核机器,单进程单线程的应用改成多进程多线程并发,IO很少主要是cpu运算,应该有一定的速度提高,可结果 是非常不明显,
> 准备build一个安装版本,做一次完整比较。
>
> ------------------------------------
> C++, Lua, living in Dalianhttp://sunxiunan.com/http://twitter.com/sagasw
> ------------------------------------
>

> 2010/1/4 pvoid <fredche...@gmail.com>

redsea

unread,
Jan 4, 2010, 1:40:43 AM1/4/10
to TopLanguage
写注册表多吗? 那玩意 io 开销恐怕比写文件还大, 那是一个数据库, 支持 transaction 的.
单进程跑的时候, cpu 是 100% 吗? 如果 cpu 跑不到 100%, 那么就有等 io 的情况.

sagasw schrieb:


> 磁盘IO只有几个地方,1)解析开始时读取读入所有内容。2)解析出错时写log。
> 1)的时间相比整个解析需要的时间要短很多,基本上不需要优化。2的时间应该也非常短,因为最后写出来的log不过就十几k。

有测试短很多吗? 测试是开机之后第一次读取, 还是第二次读取?

> 如果解析结果成功的话,是不需要写log的。
> 而且为了尽可能减少磁盘操作,也去掉了删除文件这个动作,速度一样没有改进。
>
> 解压cab是我提的一个多余条件,实际上它在这次优化是不需要考虑的一个单独过程。主要操作就是这个

> *“程序解析(动作a)文本文件,判断是否满足一定的条件,然后需要注册一些信息到注册表中(动作b)”*


>
> 现在主流的台式机机型应该都是双核了吧(什么p3
> 600客户那里不可能有的),我的疑问就是,对于双核机器,单进程单线程的应用改成多进程多线程并发,IO很少主要是cpu运算,应该有一定的速度提高,可结果是非常不明显,
> 准备build一个安装版本,做一次完整比较。

microsoft 的 gimage 程序, 就是 cpu bound 代码和 io bound 代码在一个线程内串行, 结果 cpu 用不
满, 硬盘也用不满, 速度也不理想, 你的程序不会也是如此吗 ?

sagasw

unread,
Jan 4, 2010, 3:16:52 AM1/4/10
to pon...@googlegroups.com
红海,你牛逼啊,
发现问题果然在注册表上,以前很少碰这个东西,所以没觉得是个问题。

现在的改进方案如下(尝试中):
因为只写string和dword值,所以把所有注册表操作写入一个文件中,然后通过regedit /s xxx.reg导入这个注册表文件。


------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/4 redsea <red...@gmail.com>

jun lin

unread,
Jan 4, 2010, 3:21:23 AM1/4/10
to pon...@googlegroups.com
注册表危险,能不动就不动。。。

2010/1/4 sagasw <sag...@gmail.com>

oliver yang

unread,
Jan 4, 2010, 11:22:17 AM1/4/10
to pon...@googlegroups.com
2010/1/4 sagasw <sag...@gmail.com>:

> 红海,你牛逼啊,
> 发现问题果然在注册表上,以前很少碰这个东西,所以没觉得是个问题。

一方面是经验的问题。

另一方面,做好profiling才是解决问题之道。

performance的问题千奇白怪,做profiling比经验可靠一万倍。

--
Cheers,

Oliver Yang

Twitter: http://twitter.com/yangoliver
Blog: http://blog.csdn.net/yayong
--------------------------------------------------------------------
An OpenSolaris Developer

莫华枫

unread,
Jan 4, 2010, 7:41:21 PM1/4/10
to pon...@googlegroups.com
最近跟着老许做并发,学习到几个要点。
1、系统真正的并发数取决于所涉及的资源数量。增加线程或进程数,并不一定能增加并发数。在一个资源面前,无论多少线程,都变成单线程(排队)。
2、在这种情况下,重叠操作是更好地选择:当线程被资源阻塞后,将执行权切换给其他计算。等到阻塞解除,再回过来继续后续操作。
3、os的线程调度可以起到重叠操作的作用,但代价较大。
4、此时,异步的资源操作有最好的性能。但是,异步代码不是人类所能习惯的。
5、作为折衷,单线程的协作型的调度具有更好的性能,而不破坏现有的编程方式。

2010/1/3 sagasw <sag...@gmail.com>



--
反者道之动,弱者道之用
longsh...@gmail.com
http://blog.csdn.net/longshanks/
wave开通

Kenny Yuan

unread,
Jan 4, 2010, 8:24:09 PM1/4/10
to pon...@googlegroups.com
My comments:

引文其实是在描述资源瓶颈,并给出了一个异步操作资源的方法来(部分)消除瓶颈。

“异步操作资源+并行使用多个资源的实例” 是一种消除此类瓶颈的方法;
直接扩充资源数量也是一种方法(硬件成本不高的时候这么做挺划算的,算是一种“跳出既定框架之外”的思路吧)

在决策时还有一个应该考虑的因素——维护:
1、异步(资源)操作会让后来接手的维护人员抓狂的
2、编写得再好的系统,也(很可能)会由很渣的人来维护,这些人会制造坏东西,并最终在系统内扩散和蔓延
针对这两点情况,在设计系统时就应该想出应对之策。


2010/1/5 莫华枫 <longsh...@gmail.com>



--
Kenny Yuan
C++, UI, LISP, MMA, Psychology and Automobile.
BLOG: CS巴别塔(Computer Science Babel)
URL1: http://csbabel.wordpress.com/
URL2: http://blog.csdn.net/yuankaining/

redsea

unread,
Jan 4, 2010, 8:41:22 PM1/4/10
to TopLanguage
Kenny Yuan schrieb:

> My comments:
>
> 引文其实是在描述资源瓶颈,并给出了一个异步操作资源的方法来(部分)消除瓶颈。
>
> “异步操作资源+并行使用多个资源的实例” 是一种消除此类瓶颈的方法;
> 直接扩充资源数量也是一种方法(硬件成本不高的时候这么做挺划算的,算是一种“跳出既定框架之外”的思路吧)

以前曾经因为硬盘每秒钟读的能力不够, 想过, 用一堆的 usb hub, 接200个 u 盘来增加每秒钟读的能力 :)

sagasw

unread,
Jan 4, 2010, 8:44:47 PM1/4/10
to pon...@googlegroups.com
说到底,问题的原因是对注册表的滥用,现在公司里美国那面的设计人员依然将新的信息不断添加到注册表中。
 
我们这个程序将注册表用于存放配置信息,对于少量信息也许是没问题的,
但是对于大量的注册表写操作(我也是做这次优化才发现竟然有如此多的注册表写操作),这种肯定是有问题的。
在测试Vista迁移的时候就听说过,对注册表的操作比较慢。
 
有了这次优化经验,下次搞定类似问题就容易多了。
如果由我设计,也许使用sqlite或者纯文本式配置文件(xml,lua)应该比较好一些。

------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/5 Kenny Yuan <yuank...@gmail.com>

Kenny Yuan

unread,
Jan 4, 2010, 9:09:38 PM1/4/10
to pon...@googlegroups.com
USB设备的稳定性让人怀疑这种方案能不能行
而且USB设备的多级串联问题很多,200个也快达到设备数量的上限了(256),不知道能不能真的都接上
这么多设备去分本来就不大的总线带宽(480 MBit/sec,实际上至少打8折,打4-6折的下位芯片都挺多的),速度上也不会太强
每秒的IO操作数量经过了几级HUB之后下降得也很厉害
还有一个有意思的现象:在常用的Win平台下,200个U盘是没法同时使用的(没有盘符了,设备会列出,但是驱动器不显示)

SSD倒是能够解决你的问题 :)

2010/1/5 redsea <red...@gmail.com>


以前曾经因为硬盘每秒钟读的能力不够, 想过, 用一堆的 usb hub, 接200个 u 盘来增加每秒钟读的能力 :)

Tinyfool

unread,
Jan 4, 2010, 9:12:27 PM1/4/10
to pon...@googlegroups.com
关键问题是,总线够不够,理论上当然没问题,但是实际上会有哪个硬件可以达到这个需求的要求么?我怀疑

另外,用这么复杂的方法的话,确实不如ssd,或者把缓存做好点之类的

2010/1/5 Kenny Yuan <yuank...@gmail.com>



--
Tinyfool的开发日记 http://www.tinydust.net/dev/
代码中国网 http://www.codechina.org
myTwitter: http://twitter.com/tinyfool

Kenny Yuan

unread,
Jan 4, 2010, 9:12:33 PM1/4/10
to pon...@googlegroups.com
最后做profiling了没有呢?

另:这种程度的速度问题应该反馈给负责设计的人了。本地配置文件挺好的,比如libconfig十分方便

2010/1/5 sagasw <sag...@gmail.com>

Kenny Yuan

unread,
Jan 4, 2010, 9:23:46 PM1/4/10
to pon...@googlegroups.com
某些设计良好的总线协议+设备应该能差不多达到,USB的设备,我个人还没听说过有不打折的,一般还是大折扣

附件是某个差劲的串行信号眼图。


2010/1/5 Tinyfool <tiny...@gmail.com>
eye.png

redsea

unread,
Jan 4, 2010, 9:49:56 PM1/4/10
to TopLanguage
oliver yang schrieb:

> 2010/1/4 sagasw <sag...@gmail.com>:
> > 红海,你牛逼啊,
> > 发现问题果然在注册表上,以前很少碰这个东西,所以没觉得是个问题。
>
> 一方面是经验的问题。
>
> 另一方面,做好profiling才是解决问题之道。

我觉得呢, 已经做好的程序, 分析瓶颈, profiling 是不二之道.

如果还处于设计阶段, 就需要有判断能力了, 哪些地方多半是不值得花力气的, 哪些地方要留好 scale up 能力的, 免得做完了再来改, 就
比较吃力了.

Shuo Chen

unread,
Jan 4, 2010, 9:54:26 PM1/4/10
to TopLanguage
你这示波器采样得有10Gb吧?

On Jan 5, 10:23 am, Kenny Yuan <yuankain...@gmail.com> wrote:
> 某些设计良好的总线协议+设备应该能差不多达到,USB的设备,我个人还没听说过有不打折的,一般还是大折扣
>
> 附件是某个差劲的串行信号眼图。
>

> 2010/1/5 Tinyfool <tinyf...@gmail.com>


>
>
>
> > 关键问题是,总线够不够,理论上当然没问题,但是实际上会有哪个硬件可以达到这个需求的要求么?我怀疑
>
> > 另外,用这么复杂的方法的话,确实不如ssd,或者把缓存做好点之类的
>

> > 2010/1/5 Kenny Yuan <yuankain...@gmail.com>


>
> >> USB设备的稳定性让人怀疑这种方案能不能行
>
> >> 而且USB设备的多级串联问题很多,200个也快达到设备数量的上限了(256),不知道能不能真的都接上
> >> 这么多设备去分本来就不大的总线带宽(480 MBit/sec,实际上至少打8折,打4-6折的下位芯片都挺多的),速度上也不会太强
> >> 每秒的IO操作数量经过了几级HUB之后下降得也很厉害
> >> 还有一个有意思的现象:在常用的Win平台下,200个U盘是没法同时使用的(没有盘符了,设备会列出,但是驱动器不显示)
>
> >> SSD倒是能够解决你的问题 :)
>
> >> 2010/1/5 redsea <red...@gmail.com>
>
> >>> 以前曾经因为硬盘每秒钟读的能力不够, 想过, 用一堆的 usb hub, 接200个 u 盘来增加每秒钟读的能力 :)
>
> >> --
> >> Kenny Yuan
> >> C++, UI, LISP, MMA, Psychology and Automobile.
> >> BLOG: CS巴别塔(Computer Science Babel)
> >> URL1:http://csbabel.wordpress.com/
> >> URL2:http://blog.csdn.net/yuankaining/
>
> > --
> > Tinyfool的开发日记http://www.tinydust.net/dev/

> > 代码中国网http://www.codechina.org


> > myTwitter:http://twitter.com/tinyfool
>
> --
> Kenny Yuan
> C++, UI, LISP, MMA, Psychology and Automobile.
> BLOG: CS巴别塔(Computer Science Babel)
> URL1:http://csbabel.wordpress.com/
> URL2:http://blog.csdn.net/yuankaining/
>

> eye.png
> 93KViewDownload

Tinyfool

unread,
Jan 4, 2010, 9:55:33 PM1/4/10
to pon...@googlegroups.com
程序员用示波器,无敌了…

2010/1/5 Shuo Chen <gian...@gmail.com>

你这示波器采样得有10Gb吧?

On Jan 5, 10:23 am, Kenny Yuan <yuankain...@gmail.com> wrote:
> 某些设计良好的总线协议+设备应该能差不多达到,USB的设备,我个人还没听说过有不打折的,一般还是大折扣
>
> 附件是某个差劲的串行信号眼图。
>

Shuo Chen

unread,
Jan 4, 2010, 10:10:49 PM1/4/10
to TopLanguage
现在一个国产百兆带宽1G采样的双踪彩色数字示波器才3000块钱,可以买一个玩玩。

On Jan 5, 10:55 am, Tinyfool <tinyf...@gmail.com> wrote:
> 程序员用示波器,无敌了...
>
> 2010/1/5 Shuo Chen <giantc...@gmail.com>


>
> > 你这示波器采样得有10Gb吧?
>
> > On Jan 5, 10:23 am, Kenny Yuan <yuankain...@gmail.com> wrote:
> > > 某些设计良好的总线协议+设备应该能差不多达到,USB的设备,我个人还没听说过有不打折的,一般还是大折扣
>
> > > 附件是某个差劲的串行信号眼图。
>
> --

Tinyfool

unread,
Jan 4, 2010, 10:15:58 PM1/4/10
to pon...@googlegroups.com
没钱,而且确实现在用不上

2010/1/5 Shuo Chen <gian...@gmail.com>

redsea

unread,
Jan 4, 2010, 11:15:34 PM1/4/10
to TopLanguage

Kenny Yuan schrieb:


> USB设备的稳定性让人怀疑这种方案能不能行
> 而且USB设备的多级串联问题很多,200个也快达到设备数量的上限了(256),不知道能不能真的都接上
> 这么多设备去分本来就不大的总线带宽(480 MBit/sec,实际上至少打8折,打4-6折的下位芯片都挺多的),速度上也不会太强

主板有好多个 usb 口, 可以每个口接 40 个 :)

当初的需求, 每个记录大概只有20个字节, 但是每秒钟可能有几十万个请求, 内存不够大, 存不下上百G 的数据.

> 每秒的IO操作数量经过了几级HUB之后下降得也很厉害
> 还有一个有意思的现象:在常用的Win平台下,200个U盘是没法同时使用的(没有盘符了,设备会列出,但是驱动器不显示)

当然用 linux, 想着 fs 都不用, 直接在 raw 设备上工作.
记录可能一天只更新一次, 但是要读很多次.

> SSD倒是能够解决你的问题 :)
ssd 的 iops 可能都不够 :)

Kenny Yuan

unread,
Jan 4, 2010, 11:34:03 PM1/4/10
to pon...@googlegroups.com
几十万的话USB肯定不行,USB的IO操作都是论ms的,而且默认root hub只有一个(除非你再外接PCI2USB)

单个Intel的SSD有3万还是5万的IOPS来着?(E,不是M)
PCI Express的SSD能有近10万的IOPS
再加上内存做cache,也差不多了

如果这个都满足不了的话,应该去找用内存做存储设备的厂商来帮忙
但有个问题值得注意:这个问题有没有别的解决方案?一定要这样解决么?(有种坏味道在蔓延)



2010/1/5 redsea <red...@gmail.com>


主板有好多个 usb 口, 可以每个口接 40 个 :)
当初的需求, 每个记录大概只有20个字节, 但是每秒钟可能有几十万个请求, 内存不够大, 存不下上百G 的数据.
当然用 linux, 想着 fs 都不用, 直接在 raw 设备上工作.
记录可能一天只更新一次, 但是要读很多次.


ssd 的 iops 可能都不够 :)

sagasw

unread,
Jan 4, 2010, 11:35:25 PM1/4/10
to pon...@googlegroups.com
直接注释掉使用注册表的函数,(幸好只有一个)
原来用10分钟的,现在也就2分钟,不需要再profiling其他部分了。

redsea

unread,
Jan 4, 2010, 11:44:41 PM1/4/10
to TopLanguage
这是上一个公司的事情了, 后来我离开了, 他们怎么继续做我就不清楚了.

Kenny Yuan schrieb:


> 几十万的话USB肯定不行,USB的IO操作都是论ms的,而且默认root hub只有一个(除非你再外接PCI2USB)

ms 只是 latency 而已吧 ? 几个 ms 的 latency 可以接受, 只要吞吐够就可以了.
硬盘其实是 iops 支持不了这么多的吞吐啊.

> 单个Intel的SSD有3万还是5万的IOPS来着?(E,不是M)
> PCI Express的SSD能有近10万的IOPS
> 再加上内存做cache,也差不多了
>
> 如果这个都满足不了的话,应该去找用内存做存储设备的厂商来帮忙
> 但有个问题值得注意:这个问题有没有别的解决方案?一定要这样解决么?(有种坏味道在蔓延)

本来用 x86 机器, 上 32G 内存做 cache, 后面用 ssd, 应该没有问题的.

只是, 老板提出要用 network processor, 那东西容易卖高价, 那个板子只有 512m 内存, 容量太小了, 存储设备的
iops 不够, 就不行了. 板子还只能做 pcie 的 slave, 不能做 master; 唯一的一个 sata 口好像又不支持
port multiplier, 我只能想出这个主意了.

Kenny Yuan

unread,
Jan 4, 2010, 11:54:52 PM1/4/10
to pon...@googlegroups.com
问题的根源还是BOSS嘛!

小公司的“技术型”老板们,想像力还是蛮丰富的——我也见过不少真敢去想的:
比如:想要LCD的场频达到100万Hz的级别……
再比如:想用Intel PXA芯片实时解压高分视频(如1080P)


2010/1/5 redsea <red...@gmail.com>

Googol Lee

unread,
Jan 5, 2010, 1:12:19 AM1/5/10
to TopLanguage
对的,我记得之前我好像就在TL的哪个帖子里提到过线程/进程应该和资源数量相关,而不是任务数量。

在上个公司写过一些异步的代码,感觉和最早学习写windows的消息循环是一样的,想成一个状态机就简单了。对于有些实在不支持异步的api,再用线
程去包装一下放到异步循环里。

On Jan 5, 8:41 am, 莫华枫 <longshank...@gmail.com> wrote:
> 最近跟着老许 <http://blog.csdn.net/xushiweizh>做并发,学习到几个要点。

> longshank...@gmail.comhttp://blog.csdn.net/longshanks/
> wave开通

Dbger

unread,
Jan 5, 2010, 2:32:20 AM1/5/10
to pon...@googlegroups.com
@sagasw
所以你最后解决了问题,提高了性能,关键不是用了多进程,而是去掉了注册表操作,对不?

对于文件操作,如果只有一个磁盘,而且不是SSD,试图并行操作文件应该会导致性能下降,因为大多数时间花在了disk seek上
对于注册表操作,你是否有注意到这样的下降(如前面同学说的,如果注册表会被lock,各进程相互等待~~~)


技术博客:http://debuggingnow.com
我的豆瓣:http://www.douban.com/people/baiyanhuang/


2010/1/5 Googol Lee <goog...@gmail.com>

张沈鹏

unread,
Jan 5, 2010, 2:34:34 AM1/5/10
to pon...@googlegroups.com
> 当初的需求, 每个记录大概只有20个字节, 但是每秒钟可能有几十万个请求, 内存不够大, 存不下上百G 的数据.


如果考虑dns这种应用

一般域名有十几个字节
www.google.com

ip记录有一条或多条,大部分是ip条,只考虑ipv4,每个ip是4个字节

加起来是20个左右的字节

如果先用完美哈希函数(
就是没有冲突的哈希函数,也就是,函数 H 将 N 个 KEY 值映射到 M 个整数上,
参见 http://blog.csdn.net/chixinmuzi/archive/2007/08/05/1727195.aspx

离线计算域名的并生成hash函数

那么,线上对于大部分域名只需要保存一个char[4] ipv4的数组就可以了(对于多ip的,可以用另外形式保存,并在此作标志位)。

完美哈希函数的缺点是不方便动态生成这个函数,所以需要外加一个缓冲区来应对更改,并定期重新生成。

查询的方式便是

查缓存 -》 计算hash 得到 offset -》 ip_array[offset] -> 返回ip,或继续查找多个ip

这种方式的好处就是在小内存上,缓存到的东西更多。

最后感谢 http://www.douban.com/people/changsheng/ 提供完美哈希函数的思路

redsea

unread,
Jan 5, 2010, 2:46:16 AM1/5/10
to TopLanguage
> 如果先用完美哈希函数(
> 就是没有冲突的哈希函数,也就是,函数 H 将 N 个 KEY 值映射到 M 个整数上,
> 参见 http://blog.csdn.net/chixinmuzi/archive/2007/08/05/1727195.aspx
> )

域名的应用没有办法完美 hash 的, 量太大了, 而且是动态的.

加上要上控制策略, 之前的代码是一遍扫描, 同时针对多个 section 计算出多个 hash 值, 例如 www.google.com, 一
趟扫描, 其实计算了 www, www.google, google.com 几个 hash 值的.

suhua wang

unread,
Jan 5, 2010, 10:37:23 PM1/5/10
to pongba
从描述看,费时间的操作在如下几处:
 1, 文件的读写
 2,解压
 3,文件解析
所以要提高性能,就要从这些方面入手。
首先,大文件的读写肯定是瓶颈,但是硬盘的访问是不能通过简单地增加线程来提高到的,不但不能提高,还会因为增加了寻道时间而降低性能。因此只能考虑减少读写次数。
另外,解压是否可以做到部分部分地解,这样可以解压一部分,分析一部分,而且不需要临时文件了。
最后,到底需不需要多线程呢,要看读写硬盘的时间在整个处理过程中所占的比例了,如果读写硬盘的时间远大于其它的处理,那就没必要多线程了。如果比例不高,那么适当增加线程个数应该还是有一定的提高的。

jiang yu

unread,
Jan 5, 2010, 11:01:47 PM1/5/10
to pon...@googlegroups.com
虽然瓶颈在注册表上,但是这个问题还是有讨论的价值,作为资源,io是独占,显然所有操作io(读和写)应该放在一个线程,然后根据cpu数量开工作线程做解压缩和分析。


2010/1/6 suhua wang <dubi...@gmail.com>

redsea

unread,
Jan 5, 2010, 11:32:24 PM1/5/10
to TopLanguage
注册表的瓶颈其实就是 IO 的瓶颈.

jiang yu schrieb:

sagasw

unread,
Jan 6, 2010, 3:34:45 AM1/6/10
to pon...@googlegroups.com
非常杯具的是,尽管发现了问题,可是不太容易解决问题。

已经根据新的方案完成代码,将注册表写操作写入一个string数组,并且在文件数超过一定时创建一个regedit的进程单独导入。
(regedit /s /c aaa.tmp)

性能有一定的优化,但是只有百分之20左右,不明显,还需要更多努力。

profiling也做了,基本上比较明显能提升性能的地方都改了。

现在的问题是,大家是否有类似的经验,对于注册表的操作,RegXXX与NTXXX的哪个比较快。
有没有人做过类似的大量注册表写操作的程序?该如何优化?

再用伪代码介绍一些程序的运行情况,

void main()
{
    for (int i = 0; i< fileCounts; i++)
    {
           // It will get some information from file.
           // mainly CPU or memory operation.
           ParseFileContent();

           // According to the information we get from previous function,
           // write some key and value under CLSID.
           // If key of previous version file exists, delete it at first.
           Register();
      }
}

fileCounts大约一两万,
ParseFileContent的某些file有些特殊情况,需要做一个完整的对象初始化操作,这个会比较费时间,大约是200ms到800ms左右。
一般都是50ms左右,
Register在原先代码,大概会在CLSID下建立平均6、7个Key(RegCreateKey),下面写大约8、9个Value(RegSetValueEx),value大多为string类型,一两个为dword,无其他类型。



------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/6 redsea <red...@gmail.com>

jun lin

unread,
Jan 6, 2010, 3:58:16 AM1/6/10
to pon...@googlegroups.com
还是请把需求列清楚。
几乎所有问题在把需求列清楚后,就可以直接套现有的解决方案。。。
个人建议把数据流先理清楚,写一下。
不知道为什么要导到注册表里面?

2010/1/6 sagasw <sag...@gmail.com>

sagasw

unread,
Jan 6, 2010, 4:04:27 AM1/6/10
to pon...@googlegroups.com
The application is a legacy one, and I am asked to improve the performance. I can't change the option from registry to other, even I want too. And the key/value should be same as old too. Because it will be used by other client. It is the problem.

could see this post:
http://stackoverflow.com/questions/2011647/how-to-improve-the-performance-of-write-data-into-registry



------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/6 jun lin <linjun...@gmail.com>

sagasw

unread,
Jan 6, 2010, 4:09:44 AM1/6/10
to pon...@googlegroups.com
另外,我不是要实现一个新功能,而是要对一个已有的产品进行性能上的优化,
这意味着:
1,不能改动程序已有的注册表选项,也不能写到文件中、数据库中或者什么云彩中,小程序员承担不了那个责任。
2,不能改动太剧烈,否则意味着引入更多的麻烦,不如不改。


需求很简单,就是要跑的快一些再快一些。
不知我说的那个方面还需要列的更清楚?


------------------------------------
C++, Lua, living in Dalian
http://sunxiunan.com/
http://twitter.com/sagasw
------------------------------------


2010/1/6 jun lin <linjun...@gmail.com>

jun lin

unread,
Jan 6, 2010, 4:11:38 AM1/6/10
to pon...@googlegroups.com
感觉还是一个流处理。。。解包解出数据流。。处理。。。生成需要压入注册表的数据,然后压入注册表。。
然后每个动作做一个线程,然后用管道传数据。
压入注册表的时候,要超过一定数量压一次。

这是我想到的方法。

2010/1/6 sagasw <sag...@gmail.com>

jun lin

unread,
Jan 6, 2010, 4:12:15 AM1/6/10
to pon...@googlegroups.com
恩,具体的时间数据是怎么样的?

2010/1/6 sagasw <sag...@gmail.com>

jun lin

unread,
Jan 6, 2010, 4:16:41 AM1/6/10
to pon...@googlegroups.com
压注册表是否是分批的?如果是分批的,最好改成一次压完。
看了stackoverflow上面,好像是安装程序添加注册表时出现的问题(往注册表加安装文件的列表)。
这些注册表资料,内容是多少M?

2010/1/6 jun lin <linjun...@gmail.com>
Reply all
Reply to author
Forward
0 new messages