|
|
导航: |
论坛 -> DELPHI技术
斑竹:liumazi,sephil |
|
作者: |
|
2022/9/21 22:08:42 |
标题: |
Delphi+Windows+按行读文本文件多线程单线程问题(代码) |
浏览:3406 |
|
加入我的收藏 |
楼主: |
讨论请看此贴:http://bbs.2ccc.com/topic.asp?topicid=639059
因为不能直接放工程源代码,所以做了简化修改。 代码只改了Delphi / Lazarus,分别单/多线程。 共4个项目目录。
数据是类似CSV格式的文本文件,我拷贝了一下用了6个,总共1GB。 这个文本可以自己造,配合源码呢,#09分割,弄几个字段就可以了。
----------------------------------------------
Bye bye DDRFAN... |
作者: |
|
2022/9/21 22:11:21 |
1楼: |
我这测试结果如下: D单:27.39 秒 D多:25.98 秒 L单:14.81 秒 L多:4.73 秒
打印如下:
2022-09-21 21:57:24.343 开始Delphi单线程 #0:开始解析【SPR01.log】... #0:完成1374096有效记录,0错误记录,0忽略记录. #1:开始解析【SPR02.log】... #1:完成1492456有效记录,0错误记录,0忽略记录. #2:开始解析【SPR03.log】... #2:完成2289329有效记录,0错误记录,0忽略记录. #3:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #3:完成2289324有效记录,0错误记录,0忽略记录. #4:开始解析【SPR04.log】... #4:完成2289329有效记录,0错误记录,0忽略记录. #5:开始解析【SPR05.log】... #5:完成1492456有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 27.39 秒 2022-09-21 21:57:51.733
2022-09-21 21:56:42.154 开始Delphi多线程 #1:开始解析【SPR01.log】... #2:开始解析【SPR02.log】... #4:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #3:开始解析【SPR03.log】... #5:开始解析【SPR04.log】... #6:开始解析【SPR05.log】... #6:完成1492456有效记录,0错误记录,0忽略记录. #2:完成1492456有效记录,0错误记录,0忽略记录. #1:完成1374096有效记录,0错误记录,0忽略记录. #5:完成2289329有效记录,0错误记录,0忽略记录. #4:完成2289324有效记录,0错误记录,0忽略记录. #3:完成2289329有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 25.98 秒 2022-09-21 21:57:08.135
2022-09-21 21:53:31.627 开始Lazarus单线程 #0:开始解析【SPR01.log】... #0:完成1374096有效记录,0错误记录,0忽略记录. #1:开始解析【SPR02.log】... #1:完成1492456有效记录,0错误记录,0忽略记录. #2:开始解析【SPR03.log】... #2:完成2289329有效记录,0错误记录,0忽略记录. #3:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #3:完成2289324有效记录,0错误记录,0忽略记录. #4:开始解析【SPR04.log】... #4:完成2289329有效记录,0错误记录,0忽略记录. #5:开始解析【SPR05.log】... #5:完成1492456有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条 时长: 14.81 秒 2022-09-21 21:53:46.433
2022-09-21 21:53:01.667 开始Lazarus多线程 #6:开始解析【SPR01.log】... #1:开始解析【SPR05.log】... #4:开始解析【SPR03.log】... #3:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #2:开始解析【SPR04.log】... #5:开始解析【SPR02.log】... #6:完成1374096有效记录,0错误记录,0忽略记录 #1:完成1492456有效记录,0错误记录,0忽略记录 #5:完成1492456有效记录,0错误记录,0忽略记录 #2:完成2289329有效记录,0错误记录,0忽略记录 #4:完成2289329有效记录,0错误记录,0忽略记录 #3:完成2289324有效记录,0错误记录,0忽略记录 解析SUBS表【11226990】条 时长: 4.73 秒 2022-09-21 21:53:06.392
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:18:11 |
2楼: |
关注的朋友较多。 请注意一下,主要问题:
四个条件:【Delphi + Windows + 多线程 + 按行读文本文件】。
其它组合均没问题,包括Delphi+Linux(鱼丸粗面?)
保留了一个字符串拆分成字符串列表的处理(否则完全没有处理的过程了)。 去掉这个所谓的负载也可以,会快些,但是不贴近实际情况了。 去掉负载,Delphi也慢,多/单线程也贴近。。。
非常非常希望某位高手看出问题,最希望是我自己的问题。 然后改一下,就让Delphi也能飞快处理。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:21:58 |
3楼: |
楼主,你的问题,要一个一个分开确认。
请看你的原帖底下,我做的测试结果,说明: Delphi + Windows + 多线程,读入文件进行一些处理,没有多线程不对的问题。
那么,接下来,如果你读一行,一行,一行,会如何?我不知道。我没有测试。
但是,我基本上可以判断:是你自己的代码的问题。
因为,在 Windows 底下,Delphi 从硬盘读文件并进行处理,多线程是没有问题的。
你最好简化代码到最精简,进行测试。这样才能发现问题在哪里。
----------------------------------------------
-
|
作者: |
|
2022/9/21 22:24:20 |
3楼: |
Delphi和Lazarus的代码几乎一样。 但是Lazarus好像不支持TTask,所以改回了TThread。 (我刚用上Lazarus的,不太熟,不确定)
不过Delphi下TTask和TThread速度也没区别。
真希望和各位能见面拿电脑交流,而不是打字:)
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:27:01 |
4楼: |
@pcplayer (pcplayer) 代码在一楼附件里面,你可以编译看看。 已精简了。
但是大文本文件得自己造一下。 我用的6个文本文件,每个200W行所有,4个字段,用#09分割。 总共1GB左右。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:30:29 |
5楼: |
@pcplayer (pcplayer) 我其它项目也用过多线程,包括Delphi,C++,Go。 从现象上有问题的只有
【Delphi + Windows + 多线程 + 按行读文本文件】,是这样的。
甚至速度也是,如果是读数据块就没问题,Delphi挺快的。
按行读文本,一下就慢了。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:36:45 |
6楼: |
同样Delphi程序一行没改,WSL的Ubuntu下运行这样:
$shion@shionwsl ~> /mnt/d/xxxxxx/ZPEricPCC.rhel.exe ~/br4 ~/br2 2022-09-21 22:34:13.141 开始Delphi多线程 #1:开始解析【SPR03.log】... #2:开始解析【SPR01.log】... #5:开始解析【SPR04.log】... #4:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #6:开始解析【SPR02.log】... #3:开始解析【SPR05.log】... #2:完成1374096有效记录,0错误记录,0忽略记录. #6:完成1492456有效记录,0错误记录,0忽略记录. #3:完成1492456有效记录,0错误记录,0忽略记录. #5:完成2289329有效记录,0错误记录,0忽略记录. #1:完成2289329有效记录,0错误记录,0忽略记录. #4:完成2289324有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 11.15 秒 2022-09-21 22:34:24.286
$shion@shionwsl ~> /mnt/d/xxxxxx/ZPEricPCC.rhel.exe ~/br4 ~/br2 2022-09-21 22:34:46.683 开始Delphi单线程 #0:开始解析【SPR03.log】... #0:完成2289329有效记录,0错误记录,0忽略记录. #1:开始解析【SPR01.log】... #1:完成1374096有效记录,0错误记录,0忽略记录. #2:开始解析【SPR05.log】... #2:完成1492456有效记录,0错误记录,0忽略记录. #3:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #3:完成2289324有效记录,0错误记录,0忽略记录. #4:开始解析【SPR04.log】... #4:完成2289329有效记录,0错误记录,0忽略记录. #5:开始解析【SPR02.log】... #5:完成1492456有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 36.45 秒 2022-09-21 22:35:23.132 $shion@shionwsl ~>
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:38:30 |
7楼: |
从上面看WSL的Linux下单线程比Windows更慢一些(毕竟算虚拟机)。 但是多线程快得多啊。啊啊啊。。。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 22:46:36 |
8楼: |
你的问题其实要确认很容易。
你先做一个最简单的程序,就是读文件,然后干一个最简单也耗时的事情:写一个循环把文件的每个字节取出来加个1;
这样的代码,你拿到多线程底下,看看是不是有问题。至少我的测试,是没有问题的。我的测试不是简单加1,是做了 CRC 校验运算。
如果你没发现问题。那么,再进一步,把读一个字节的代码换成读一行。
读一行,有两种读法,一个是 ReadLn,一个是你自己一个字节一个字节地读,读到 #13 算一行。你可以分别测试,看看是不是有区别。假设有区别,那是不是 ReadLn 有问题?
不过,我觉得 ReadLn 有问题的可能性不大。
再进一步,把你的解析 CSV 的代码加进去。
这样从最简单开始一步一步来,很容易定位问题。
一上来就一堆复杂代码,问题就不容易定位了。
所以我的测试代码,写得非常简单,多个线程,我就用代码重复写多个,连个循环都没用,就是避免其它代码带来的问题影响测试结果。
我没有大文本文件,所以我也没法帮你测试。但是,你总强调你的测试结果,但你的测试结果都是一大堆各种功能混一起的代码的最终测试结果,那么,没法说究竟哪里有问题,要从里面找出问题来,比较麻烦。
所以,重复一遍:从最简单开始,一步步增加代码,看看究竟到哪里,会出现你说的问题。这是确定问题的最简单有效的方式。
----------------------------------------------
-
|
作者: |
|
2022/9/21 22:54:12 |
9楼: |
@pcplayer (pcplayer) 我附件中的代码是四个项目,从真实项目中简化而来的。 其实不复杂。
1)把文件的每个字节取出来加个1 这步我没有严格做,因为处理文本需要处理一行,所以如果这步多线程没问题,那还是不能解决问题。但我试过读一块数据,直到把文件读完,比读行快很多。 这个我可以马上测试一下。
2)读一行,有两种读法,一个是 ReadLn,一个是你自己一个字节一个字节地读。 这个我做了的,基于上面1的理论,我做了个用读数据块,在自己分行的类,实测比Readln稍快。当然,我觉得快的原因是没有考虑字符编码。 到这一步的时候: a)多线程和单线程几乎差不多了, b)Delphi比Lazarus和其它语言慢很多。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 23:04:00 |
10楼: |
@pcplayer (pcplayer) 还有你在另一帖里提到的,多线程每个线程都比单线程处理慢一些。 这个是正常的,CPU多线程最高睿频低很多(基本上是个下降曲线) 比如我的这个笔记本,1core最高睿频5Ghz, 2core就4.9Ghz 全核心8core睿频只有4.1Ghz。。。
所以4个线程处理四个文件,并不能比1个线程快4倍。 这个正常。
但是如果4个线程只快了十分之一,那就不正常了。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 23:07:34 |
11楼: |
楼主,你的问题其实就是:多线程没对。
究竟哪里没对?你自己没找到问题在哪里。
要找到问题在哪里,就是要简化程序。
至少我的测试,简化到只读入文件并对文件的内容做 CRC 校验,多线程是没有问题的。
如果做 CRC 校验有问题,我会把 CRC 校验的代码都拿掉,就做简单的逐个字节处理,单纯就是为了消耗时间,进行测试。
所以,你不用说那么多,最基础的测试我已经做了,肯定读入文件是没有问题的。剩下的问题,你自己可以测试了。
----------------------------------------------
-
|
作者: |
|
2022/9/21 23:13:43 |
12楼: |
慢的原因是在线程里用string,
发10兆测试数据上来,我测一下
----------------------------------------------
-
|
作者: |
|
2022/9/21 23:18:55 |
13楼: |
我觉得在线程里面用 string 没理由导致多线程和单线程一样。
如果用 string 慢,导致单线程的时间也边长,多线程时间也变长,但多线程和单线程的时间,还是应该有差异才对。
----------------------------------------------
-
|
作者: |
|
2022/9/21 23:28:32 |
14楼: |
delphi自带的内存管理造成有string时CPU没法充分利用的,如果是具体业务,改pchar,换内存管理器
----------------------------------------------
-
|
作者: |
|
2022/9/21 23:39:40 |
15楼: |
@pcplayer (pcplayer) 已经很简化了。 我试了一下Blockread,一次读1000字节都太快完成。 改成一次读100. 基本应该算正常的速度,和单/多线程的比例。
开始Delphi多线程 #0:开始解析【SPR01.log】... #1:开始解析【SPR02.log】... #2:开始解析【SPR03.log】... #3:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #4:开始解析【SPR04.log】... #5:开始解析【SPR05.log】... #0:完成139619991字节. #1:完成151637720字节. #5:完成151637720字节. #2:完成232958362字节. #3:完成232957852字节. #4:完成232958362字节. 解析SUBS表【1141770007】条! 解析成功! 时长: 4.88 秒 2022-09-21 23:36:32.243
2022-09-21 23:36:02.471 开始Delphi单线程 #0:开始解析【SPR01.log】... #0:完成139619991字节. #1:开始解析【SPR02.log】... #1:完成151637720字节. #2:开始解析【SPR03.log】... #2:完成232958362字节. #3:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #3:完成232957852字节. #4:开始解析【SPR04.log】... #4:完成232958362字节. #5:开始解析【SPR05.log】... #5:完成151637720字节. 解析SUBS表【1141770007】条! 解析成功! 时长: 16.23 秒 2022-09-21 23:36:18.703
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
hectic (村雨Hectic) |
▲▲▲▲▲ |
-
|
普通会员 |
|
2022/9/21 23:40:36 |
16楼: |
https://www.delphitools.info/2013/11/05/multi-threaded-string-building-in-delphi/ 这可能就是你要的答案
----------------------------------------------
-
|
作者: |
|
2022/9/21 23:42:07 |
16楼: |
@hq200306 (200306) 业务很多,比较复杂,各种长度不定。 目前是必须用String。
如果必须用String,怎么换内存管理才能解决呢?
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 23:44:48 |
17楼: |
@hectic (村雨Hectic) 多谢,我研究一下。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/21 23:53:34 |
17楼: |
关于 String:
1. 我觉得,不应该使用了 String 导致多线程的处理时间和单线程一样。就算 String 带来更多的时间消耗,那多线程仍然应该比单线程省点时间。
2. String 有引用计数和自动内存管理。如果你频繁地使用新的 string 变量,抛弃老的 string 变量,那么,Delphi 内部会频繁地分配内存,消灭内存。这个的确会导致 CPU 的消耗增加,导致处理时间变长。如果对速度有特别要求,这种地方就不要用 string 而是要考虑其它办法。用 string 仅仅是少写一点代码而已。如果用其它办法,比如自己开固定长度的缓冲区这种办法,多写一点代码,也能管理好。只不过需要自己把这些代码封装好,方便整个程序里面需要的地方都能用上。类似的事情我以前干过,我直接封装成了一个类,类里面放数据的地方我自己开缓冲区,开好固定大小不再改变就没有反复释放内存分配内存带来的 CPU 消耗,然后做了类缓冲区,反复使用这个类的对象实例,避免创建和释放带来的 CPU 消耗。
----------------------------------------------
-
|
作者: |
|
2022/9/22 0:01:33 |
18楼: |
1、逐行读肯定是没效率的。
2、这个函数在多线耗时,你要去了解string, procedure StrToStrings(S, Sep: string; const List: TStringList; const AllowEmptyString: Boolean; const NeedTrim: Boolean); overload;
如果你对熟悉pchar熟,估计能优化出几倍速度
----------------------------------------------
-
|
作者: |
|
2022/9/22 0:05:56 |
19楼: |
18 楼,目前楼主的问题还不是 string 效率低的问题,而是采用多线程居然没有改善总体时间。这个就是个大问题了。
多线程问题解决了,才能说改善 string 带来的效率低的问题。
查问题,要一个一个来。把所有问题搅合在一起,就没法知道问题具体在哪里。
----------------------------------------------
-
|
作者: |
|
2022/9/22 0:16:02 |
18楼: |
呃,真的是内存管理问题呀……
下载了并引用了fastmm4。 FastMM4Options.inc中开启了NeverSleepOnThreadContention。 速度快了很多。 还是刚才的测试程序。
原来:
2022-09-22 00:11:22.681 开始Delphi多线程 #1:开始解析【SPR01.log】... #2:开始解析【SPR02.log】... #3:开始解析【SPR03.log】... #4:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #5:开始解析【SPR04.log】... #6:开始解析【SPR05.log】... #1:完成1374096有效记录,0错误记录,0忽略记录. #2:完成1492456有效记录,0错误记录,0忽略记录. #6:完成1492456有效记录,0错误记录,0忽略记录. #3:完成2289329有效记录,0错误记录,0忽略记录. #4:完成2289324有效记录,0错误记录,0忽略记录. #5:完成2289329有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 27.51 秒 2022-09-22 00:11:50.191
变成了:
2022-09-22 00:12:43.585 开始Delphi多线程 #1:开始解析【SPR01.log】... #2:开始解析【SPR02.log】... #3:开始解析【SPR03.log】... #4:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #5:开始解析【SPR04.log】... #6:开始解析【SPR05.log】... #1:完成1374096有效记录,0错误记录,0忽略记录. #2:完成1492456有效记录,0错误记录,0忽略记录. #6:完成1492456有效记录,0错误记录,0忽略记录. #4:完成2289324有效记录,0错误记录,0忽略记录. #3:完成2289329有效记录,0错误记录,0忽略记录. #5:完成2289329有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 10.99 秒 2022-09-22 00:12:54.572
准备继续研究。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 0:18:52 |
20楼: |
@18楼 @19楼
我前面其实写了的,字符串分割去掉后,速度也快不了多少…… 留在那里当唯一的负载,贴近真实处理一点,要不然仅剩下读了。 总的来说这个不重要,影响不大。
看我楼上的测试,还真是内存管理问题。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 0:27:43 |
21楼: |
楼上,你改了内存管理器,效率是提升了。
但你没说,多线程和单线程是否仍然一样?有没有区别?
----------------------------------------------
-
|
作者: |
|
2022/9/22 0:39:46 |
22楼: |
看了一下 TStringBuilder 的代码:
TStringBuilder = class private type TEnumerator = record private FPtr: PChar; FEndPtr: PChar; public
说明它内部是用 PChar 并且先分配了一定长度的内存来管理字符串的。
----------------------------------------------
-
|
作者: |
|
2022/9/22 1:22:54 |
23楼: |
问题,干嘛分割??? 大文件,用内存映射读,还是狠快的。
想不到这种操作的实际用途。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
|
作者: |
|
2022/9/22 7:41:11 |
24楼: |
还是方法的问题, 比如: 1、多线程下用tcmalloc或tbbmalloc。 2、多线程下string改pchar。 3、逐行读,改较大buffer读。 4、检测线程是否正确使用。
tbb内存管理 https://en.delphipraxis.net/topic/7357-64bit-rtl-patches-with-intel-oneapi-and-tbb/
如果会字符指针,估计这测试时间将会是2、3秒左右,不是25秒,也不是10秒,还有很大优化空间
delphi做好了基本上和C做的东西差不多,肯定比java快几倍
----------------------------------------------
-
|
作者: |
|
2022/9/22 8:41:35 |
25楼: |
避免使用AssignFile进行大文件操作,用TStreamReader替代
----------------------------------------------
-
|
作者: |
|
2022/9/22 8:56:37 |
26楼: |
@parhelia (-_-)
25楼。
TStreamReader之前也测试过。 呃只有程序,没代码啊,有没有内存管理方面的优化。
用你的附件结果如下,能看看代码么。
2022-09-22 08:53:42.422 开始Delphi多线程 #1:开始解析【SPR01.log】... #2:开始解析【SPR02.log】... #3:开始解析【SPR03.log】... #4:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #5:开始解析【SPR04.log】... #6:开始解析【SPR05.log】... #1:完成1374096有效记录,0错误记录,0忽略记录. #6:完成1492456有效记录,0错误记录,0忽略记录. #2:完成1492456有效记录,0错误记录,0忽略记录. #5:完成2289329有效记录,0错误记录,0忽略记录. #3:完成2289329有效记录,0错误记录,0忽略记录. #4:完成2289324有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 15.54 秒 2022-09-22 08:53:57.963
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 9:05:44 |
27楼: |
@pcplayer (pcplayer) 21楼 因为修改的选项是多线程相关的,所以没测单线程。 刚才测试了一下,单线程时间基本没变化。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 9:16:03 |
28楼: |
@hq200306 (200306) 24楼,多谢啊。
pchar肯定能理解,很多地方也用了的,相当于c的char *。 Delphi新版都是双字节,得用pAnsiChar, 就像AnsiString现在和String已经不一样了(D7一样的)。
例子虽然简单,但实际有很多业务,各不相同,用固定分配和指针不方便。具体就不描述了,可以参考把C++程序用纯C重写,个人感觉很麻烦的。
线程的使用应该没问题,如果线程有问题,那么在其它组合下(比如Linux,比如逐行文本改成读块)应该也有问题。
以前没有研究过Delphi内存管理,现在准备根据各位提到的了解一下。 目前看来是这方面引起的。 只是没想到,居然这里有问题。。。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 9:30:25 |
29楼: |
改好的unEricThread.pas,用TStreamReader替换了AssignFile
----------------------------------------------
-
|
作者: |
|
2022/9/22 9:51:24 |
30楼: |
@parhelia (-_-) 谢谢,我测了一下,确实快很多。
我记得之前测过,不知道哪个版本了,XE8? 当时发现速度并不快,所以后来没有再测,失误了。。。
不过用TStreamReader,还是需要加入fastmm4并修改参数。 否则单线程/多线程还是一个速度——虽然都快了不少。
汗……
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 10:50:36 |
31楼: |
也可以试这个 内存管理,纯pascal https://github.com/andremussche/scalemm 多线程比fastmm快很多
----------------------------------------------
-
|
作者: |
|
2022/9/22 11:25:40 |
32楼: |
@hq200306 (200306) 多谢!!! 试了一下,确实快多了。 不用改代码了:)
2022-09-22 11:24:26.094 开始Delphi多线程(ScaleMM2) #1:开始解析【SPR01.log】... #2:开始解析【SPR02 - Copy.log】... #3:开始解析【SPR02.log】... #4:开始解析【SPR03 - Copy.log】... #5:开始解析【SPR03.log】... #6:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #1:完成1374096有效记录,0错误记录,0忽略记录. #3:完成1492456有效记录,0错误记录,0忽略记录. #2:完成1492456有效记录,0错误记录,0忽略记录. #5:完成2289329有效记录,0错误记录,0忽略记录. #4:完成2289329有效记录,0错误记录,0忽略记录. #6:完成2289324有效记录,0错误记录,0忽略记录. 解析SUBS表【11226990】条! 解析成功! 时长: 2.83 秒 2022-09-22 11:24:28.926
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 11:37:54 |
33楼: |
如果采用字符指针,时间还会提高很多,delphi的string,太慢了,不适合才多线程上使用。
Delphi的速度和c相当
----------------------------------------------
-
|
作者: |
|
2022/9/22 11:48:33 |
34楼: |
我粗看了你的代码,觉得可优化地方太多,速度还能提升一倍以上,估计2秒都不要,肯定不是之前测的20多秒
----------------------------------------------
-
|
作者: |
|
2022/9/22 11:59:44 |
35楼: |
@hq200306 (200306) 谢谢:)
不知道你指的是哪部分代码呢?
我感觉StrToStrings()可以优化,是从JCL里面拷贝出来的,稍微修改了一下。
具体业务部分已经简化删掉了,只剩下下面部分。 这里似乎看不出能怎么改。 指针操作太难兼顾各种格式了。
while not aFile.EndOfStream do begin Aline := aFile.ReadLine; Inc(FCount); try //当作处理过程留下这句,其它的已去掉。 StrToStrings(Aline,#09,aValueList); ......
你有什么思路,可以大概说说,也好启发我一下。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 12:08:06 |
36楼: |
1、您可以参考17楼的思路,线程内尽量少用string。 2、按我想法,一个字符指针for循环,所有字符仅遍历一次就能搞定,不需要反复裁剪
----------------------------------------------
-
|
作者: |
|
2022/9/22 12:09:23 |
36楼: |
如果只针对这一种简单的情况,我大概这么想的。
1)Blockread,读入buffer。
2)从buffer中判断一行结束(#10)(buffer大些,至少足够读完一行) 还可以设置AltBuffer轮流读,减少移动buffer中的剩余数据。
3)在一行内判断分割符#09,用4个pchar分别指向字符串首位,并将#09变为#00,这样就得到了4个分割好的字符串。
4)后面的处理类似,比如判断字段1是否86开头,如果86开头就将pchar后移2位。如果没找够4个字段则后续pchar设为nil。
5)将检验过的内容写入结果文件,不转换成String,直接BlockWrite。
这样就避开了StrToStrings,也不在转换任何String了。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 12:15:37 |
37楼: |
对,软件速度还是算法问题 要相信delphi肯定是比java快
----------------------------------------------
-
|
作者: |
|
2022/9/22 12:31:50 |
37楼: |
我又看了一下17楼的建议,非常正确,通常我们写C程序就是这么干的。 实际的问题是格式非常多,每种都写一个处理的类太麻烦了。
比如例子中的类csv文件,就可以这么处理,相对简单。 类xml格式就困难一些(不是标准XML)。 某些格式我们不清楚长度,关键词,字段个数等等。 还有一条记录跨行的csv格式,各种工具包括Java都没有成熟的处理类,自己写如果再考虑不用String真的太繁琐了。 而且交给别人的话,担心新人看不懂。。。 具体就不解释了。
毕竟20多年都在做开发工作,大家提出的思路我是能理解的。 不会理解不了String是什么pchar是什么,自动/手动内存分配释放情况。 就像之前谁好心的提醒我,日期型跨平台怎么存一样。相信我嘛,是理解的。
总的来说很感谢大家的帮助。 具体这个问题,知道了是Delphi的内存管理在多线程下有效率问题,就好办多了。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 12:40:37 |
38楼: |
这边真正的挑战是没人做事。
我更希望把基础工作分下去,自己能多研究优化现有软件架构,多了解开源项目并引入实际应用,多熟悉各种新业务,甚至多到现场去多看看工程在怎么乱用我们的软件。
要阻止产品和工程代替开发进行设计,把不合理的逻辑细节写入技术建议书。 假设送货给客户,那么要求应该是货物完好,及时送达。 而不是说倒立过来,脚夹货物,用手走路,不能坐车,绕市区10圈。
还要阻止市场在开发评估前就签订了合同,再回来告诉我们,怎么做自己想,反正2个月要上线,客户希望之前能看到一个全功能的Demo,方便提修改意见。
退一步。 公司怎么运作我管不了。 至少别让我自己维护全部代码:)
再次感谢大家!!!
吐槽完了,与主题无关:)
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 12:47:56 |
39楼: |
好多年前我用delphi写过三层服务器,大几千在线连接,7、8百并发,大概清楚delphi的性能的,肯定不会比java慢。
----------------------------------------------
-
|
作者: |
|
2022/9/22 13:19:41 |
40楼: |
整体效率Delphi肯定不比java慢。 上面对比慢也是特定的场景,而且当时并不知道Delphi的String是这样……
当年很多东西用Delphi写,是用Delphi和C++做过效率比较才决定的。
但是Java优点是方便: 比如连接FTP/SFTP/SSH,Delphi可以做,也有很多控件,但是每种功能不同,版本新旧,有没有继续在维护,是否免*费使用,都搞不清楚。 而且遇到一些特殊的地方(比如要求键盘交互),则很难实现。 比如可能全国几百台服务器都OK,用了10年了,突然有一台服务器和别的不一样,就是连不上。 而用Java只需要import阿帕奇的包,任何问题都可以等新版。
比如连接数据库,用Java不像Delphi,我不用了解PostgreSQL协议分什么v2,v3。 随便换个库,import包改下驱动,连接字符串就OK。 Delphi连openGauss,只能当作PG连,bug还解决不了。 但是Java居然有专门的包。
在Linux下解压7z怎么搞,用Java我完全不用懂原理,import了包就可以用。
用Java就像拥有全*套的工具。 放在20年前,正好是Delphi7的特点。
举个java不好的例子: Java是虚拟机,如果程序跑起来之前,我不知道可能只会用到1MB内存,还是得用32GB内存。我就没法设置参数,基本也就无解了。效率不是低一点,也许低到得无限等待。也许等到GC比例到98%再报错?。。。
每种语言都有优缺点,有各自出现的原因,历史问题。
再比如Go(之前提Go,咱论坛好些人不开心呢) Go确实快,但现在已经开始骂Go的泛型了。 也许再过10年20年,Go也会变得更加怪异,再没那么快……也许……
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 14:15:31 |
41楼: |
Java 开源的东西多,就越来越多。
Delphi 这个,曾经国外有人问过官方对未来的发展,是否有考虑走开源的道路,官方回答是没考虑这条路。那后果肯定是相关的资源跟不上其它开源项目多了。比如 Python 开源项目也多。
----------------------------------------------
-
|
作者: |
|
2022/9/22 14:43:25 |
42楼: |
我的想法 1、delphi在wdinows桌面程序应该没什么问题。 2、delphi开发web是短板。 3、开发安卓,如果把运行效率提高,把apk弄小,那delphi是有生命力的,比如delphi在安卓平台很容易使用jar,几乎无缝。
----------------------------------------------
-
|
作者: |
|
2022/9/22 14:44:46 |
42楼: |
@hq200306 (200306)
除了打印到屏幕,全部没用String,又快了好多。 我准备改正式程序了……
2022-09-22 14:42:43.944 开始Delphi多线程 #0:开始解析【SPR01.log】... #1:开始解析【SPR02 - Copy.log】... #2:开始解析【SPR02.log】... #3:开始解析【SPR03 - Copy.log】... #4:开始解析【SPR03.log】... #5:开始解析【SPR03_A_20340232_2020_10_14_00.log】... #2:完成1492456条. #0:完成1374096条. #1:完成1492456条. #5:完成2289324条. #4:完成2289329条. #3:完成2289329条. 解析SUBS表【11226990】条! 解析成功! 时长: 0.43 秒 2022-09-22 14:42:44.370
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 14:49:00 |
43楼: |
我十几年前写过三层服务器,几乎就是内存处理,当我看你的代码,我觉可优化空间很大
----------------------------------------------
-
|
作者: |
|
2022/9/22 15:00:23 |
43楼: |
我问这个问题的时候,有人回答用Go……
其实2-3年前,这部分类似的程序确实已经改成Go版本了。 不考虑效率的程序都改成了Java版本。 界面当然也都是Java的WEB。
只有C++那边倒是铁打不动,唯一问题是人走了,只能自己维护。 不仅有VS还有QT的。。。
为啥都不用了还是想搞清楚Delphi版本到底什么问题呢…… 应该是舍不得吧。
就连我们产品的一个WEB,我都用unigui做了一个Delphi版本(非全功能)。 来diss年轻的Java WEB开发同事:)
可惜公司不再走Delphi线路了(买了2套依然年年收律师函)。 所以后续不会有基于Delphi开发的商业产品。 老的软件也仅仅是维护了。
Delphi只有舍不得和兴趣了。
----------------------------------------------
Bye bye DDRFAN...
|
作者: |
|
2022/9/22 15:15:22 |
44楼: |
1、Windows下delphi写的程序,在debug窗口,看代码对应汇编指令,已经编译的很完美。 2、delphi就前十年做太烂,IDE的bug多,运行库都效率很低,delphi很多自带的库很慢,比如json,慢得令人发指,还好有不少开源库。搞笑是,前几年安卓下的字符串索引和windows不一致,以为emb要把Delphi弄死,还好11版以后注重质量了,算是第二春
----------------------------------------------
-
|
|