DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: sql2003s
今日帖子: 1
在线用户: 2
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:08:42
标题:
Delphi+Windows+按行读文本文件多线程单线程问题(代码) 浏览:1386
加入我的收藏
楼主: 讨论请看此贴:http://bbs.2ccc.com/topic.asp?topicid=639059

因为不能直接放工程源代码,所以做了简化修改。
代码只改了Delphi / Lazarus,分别单/多线程。
共4个项目目录。

数据是类似CSV格式的文本文件,我拷贝了一下用了6个,总共1GB。
这个文本可以自己造,配合源码呢,#09分割,弄几个字段就可以了。
此帖子包含附件:ddrfan_202292122842.zip 大小:30.8K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 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...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:18:11
2楼: 关注的朋友较多。
请注意一下,主要问题:

四个条件:【Delphi + Windows + 多线程 + 按行读文本文件】。

其它组合均没问题,包括Delphi+Linux(鱼丸粗面?)

保留了一个字符串拆分成字符串列表的处理(否则完全没有处理的过程了)。
去掉这个所谓的负载也可以,会快些,但是不贴近实际情况了。
去掉负载,Delphi也慢,多/单线程也贴近。。。

非常非常希望某位高手看出问题,最希望是我自己的问题。
然后改一下,就让Delphi也能飞快处理。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 22:21:58
3楼: 楼主,你的问题,要一个一个分开确认。

请看你的原帖底下,我做的测试结果,说明: Delphi + Windows + 多线程,读入文件进行一些处理,没有多线程不对的问题。

那么,接下来,如果你读一行,一行,一行,会如何?我不知道。我没有测试。

但是,我基本上可以判断:是你自己的代码的问题。

因为,在 Windows 底下,Delphi 从硬盘读文件并进行处理,多线程是没有问题的。

你最好简化代码到最精简,进行测试。这样才能发现问题在哪里。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:24:20
3楼: Delphi和Lazarus的代码几乎一样。
但是Lazarus好像不支持TTask,所以改回了TThread。
(我刚用上Lazarus的,不太熟,不确定)

不过Delphi下TTask和TThread速度也没区别。

真希望和各位能见面拿电脑交流,而不是打字:)
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:27:01
4楼: @pcplayer (pcplayer)
代码在一楼附件里面,你可以编译看看。
已精简了。

但是大文本文件得自己造一下。
我用的6个文本文件,每个200W行所有,4个字段,用#09分割。
总共1GB左右。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:30:29
5楼: @pcplayer (pcplayer)
我其它项目也用过多线程,包括Delphi,C++,Go。
从现象上有问题的只有

【Delphi + Windows + 多线程 + 按行读文本文件】,是这样的。

甚至速度也是,如果是读数据块就没问题,Delphi挺快的。

按行读文本,一下就慢了。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 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...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:38:30
7楼: 从上面看WSL的Linux下单线程比Windows更慢一些(毕竟算虚拟机)。
但是多线程快得多啊。啊啊啊。。。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 22:46:36
8楼: 你的问题其实要确认很容易。

你先做一个最简单的程序,就是读文件,然后干一个最简单也耗时的事情:写一个循环把文件的每个字节取出来加个1;

这样的代码,你拿到多线程底下,看看是不是有问题。至少我的测试,是没有问题的。我的测试不是简单加1,是做了 CRC 校验运算。

如果你没发现问题。那么,再进一步,把读一个字节的代码换成读一行。

读一行,有两种读法,一个是 ReadLn,一个是你自己一个字节一个字节地读,读到 #13 算一行。你可以分别测试,看看是不是有区别。假设有区别,那是不是 ReadLn 有问题?

不过,我觉得 ReadLn 有问题的可能性不大。

再进一步,把你的解析 CSV 的代码加进去。

这样从最简单开始一步一步来,很容易定位问题。

一上来就一堆复杂代码,问题就不容易定位了。

所以我的测试代码,写得非常简单,多个线程,我就用代码重复写多个,连个循环都没用,就是避免其它代码带来的问题影响测试结果。

我没有大文本文件,所以我也没法帮你测试。但是,你总强调你的测试结果,但你的测试结果都是一大堆各种功能混一起的代码的最终测试结果,那么,没法说究竟哪里有问题,要从里面找出问题来,比较麻烦。

所以,重复一遍:从最简单开始,一步步增加代码,看看究竟到哪里,会出现你说的问题。这是确定问题的最简单有效的方式。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 22:54:12
9楼: @pcplayer (pcplayer)
我附件中的代码是四个项目,从真实项目中简化而来的。
其实不复杂。

1)把文件的每个字节取出来加个1
这步我没有严格做,因为处理文本需要处理一行,所以如果这步多线程没问题,那还是不能解决问题。但我试过读一块数据,直到把文件读完,比读行快很多。
这个我可以马上测试一下。


2)读一行,有两种读法,一个是 ReadLn,一个是你自己一个字节一个字节地读。
这个我做了的,基于上面1的理论,我做了个用读数据块,在自己分行的类,实测比Readln稍快。当然,我觉得快的原因是没有考虑字符编码。
到这一步的时候:
a)多线程和单线程几乎差不多了,
b)Delphi比Lazarus和其它语言慢很多。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 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...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 23:07:34
11楼: 楼主,你的问题其实就是:多线程没对。

究竟哪里没对?你自己没找到问题在哪里。

要找到问题在哪里,就是要简化程序。

至少我的测试,简化到只读入文件并对文件的内容做 CRC 校验,多线程是没有问题的。

如果做 CRC 校验有问题,我会把 CRC 校验的代码都拿掉,就做简单的逐个字节处理,单纯就是为了消耗时间,进行测试。

所以,你不用说那么多,最基础的测试我已经做了,肯定读入文件是没有问题的。剩下的问题,你自己可以测试了。
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/21 23:13:43
12楼: 慢的原因是在线程里用string,

发10兆测试数据上来,我测一下
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 23:18:55
13楼: 我觉得在线程里面用 string 没理由导致多线程和单线程一样。

如果用 string 慢,导致单线程的时间也边长,多线程时间也变长,但多线程和单线程的时间,还是应该有差异才对。
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/21 23:28:32
14楼: delphi自带的内存管理造成有string时CPU没法充分利用的,如果是具体业务,改pchar,换内存管理器
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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/
这可能就是你要的答案
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 23:42:07
16楼: @hq200306 (200306)
业务很多,比较复杂,各种长度不定。
目前是必须用String。

如果必须用String,怎么换内存管理才能解决呢?
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/21 23:44:48
17楼: @hectic (村雨Hectic)
多谢,我研究一下。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 23:53:34
17楼: 关于 String:

1. 我觉得,不应该使用了 String 导致多线程的处理时间和单线程一样。就算 String 带来更多的时间消耗,那多线程仍然应该比单线程省点时间。

2. String 有引用计数和自动内存管理。如果你频繁地使用新的 string 变量,抛弃老的 string 变量,那么,Delphi 内部会频繁地分配内存,消灭内存。这个的确会导致 CPU 的消耗增加,导致处理时间变长。如果对速度有特别要求,这种地方就不要用 string 而是要考虑其它办法。用 string 仅仅是少写一点代码而已。如果用其它办法,比如自己开固定长度的缓冲区这种办法,多写一点代码,也能管理好。只不过需要自己把这些代码封装好,方便整个程序里面需要的地方都能用上。类似的事情我以前干过,我直接封装成了一个类,类里面放数据的地方我自己开缓冲区,开好固定大小不再改变就没有反复释放内存分配内存带来的 CPU 消耗,然后做了类缓冲区,反复使用这个类的对象实例,避免创建和释放带来的 CPU 消耗。
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
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熟,估计能优化出几倍速度
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/22 0:05:56
19楼: 18 楼,目前楼主的问题还不是 string 效率低的问题,而是采用多线程居然没有改善总体时间。这个就是个大问题了。

多线程问题解决了,才能说改善 string 带来的效率低的问题。

查问题,要一个一个来。把所有问题搅合在一起,就没法知道问题具体在哪里。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/22 0:18:52
20楼: @18楼
@19楼

我前面其实写了的,字符串分割去掉后,速度也快不了多少……
留在那里当唯一的负载,贴近真实处理一点,要不然仅剩下读了。
总的来说这个不重要,影响不大。

看我楼上的测试,还真是内存管理问题。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/22 0:27:43
21楼: 楼上,你改了内存管理器,效率是提升了。

但你没说,多线程和单线程是否仍然一样?有没有区别?
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/22 0:39:46
22楼:
看了一下 TStringBuilder 的代码:

TStringBuilder = class
  private type
    TEnumerator = record
    private
      FPtr: PChar;
      FEndPtr: PChar;
    public


说明它内部是用 PChar 并且先分配了一定长度的内存来管理字符串的。
----------------------------------------------
-
作者:
男 letianwuji (大器晚成) ▲▲▲▲△ -
注册会员
2022/9/22 1:22:54
23楼: 问题,干嘛分割???
大文件,用内存映射读,还是狠快的。

想不到这种操作的实际用途。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
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快几倍
----------------------------------------------
-
作者:
男 parhelia (-_-) ★☆☆☆☆ -
注册会员
2022/9/22 8:41:35
25楼: 避免使用AssignFile进行大文件操作,用TStreamReader替代
此帖子包含附件:parhelia_202292284134.zip 大小:556.2K
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/22 9:05:44
27楼: @pcplayer (pcplayer)
21楼
因为修改的选项是多线程相关的,所以没测单线程。
刚才测试了一下,单线程时间基本没变化。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 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...
作者:
男 parhelia (-_-) ★☆☆☆☆ -
注册会员
2022/9/22 9:30:25
29楼: 改好的unEricThread.pas,用TStreamReader替换了AssignFile
此帖子包含附件:parhelia_202292293024.zip 大小:551.9K
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/22 9:51:24
30楼: @parhelia (-_-)
谢谢,我测了一下,确实快很多。

我记得之前测过,不知道哪个版本了,XE8?
当时发现速度并不快,所以后来没有再测,失误了。。。

不过用TStreamReader,还是需要加入fastmm4并修改参数。
否则单线程/多线程还是一个速度——虽然都快了不少。

汗……
----------------------------------------------
Bye bye DDRFAN...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 10:50:36
31楼: 也可以试这个 内存管理,纯pascal
https://github.com/andremussche/scalemm
多线程比fastmm快很多
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 11:37:54
33楼: 如果采用字符指针,时间还会提高很多,delphi的string,太慢了,不适合才多线程上使用。

Delphi的速度和c相当
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 11:48:33
34楼: 我粗看了你的代码,觉得可优化地方太多,速度还能提升一倍以上,估计2秒都不要,肯定不是之前测的20多秒
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 12:08:06
36楼: 1、您可以参考17楼的思路,线程内尽量少用string。
2、按我想法,一个字符指针for循环,所有字符仅遍历一次就能搞定,不需要反复裁剪
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 12:15:37
37楼: 对,软件速度还是算法问题
要相信delphi肯定是比java快
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/22 12:31:50
37楼: 我又看了一下17楼的建议,非常正确,通常我们写C程序就是这么干的。
实际的问题是格式非常多,每种都写一个处理的类太麻烦了。

比如例子中的类csv文件,就可以这么处理,相对简单。
类xml格式就困难一些(不是标准XML)。
某些格式我们不清楚长度,关键词,字段个数等等。
还有一条记录跨行的csv格式,各种工具包括Java都没有成熟的处理类,自己写如果再考虑不用String真的太繁琐了。
而且交给别人的话,担心新人看不懂。。。
具体就不解释了。

毕竟20多年都在做开发工作,大家提出的思路我是能理解的。
不会理解不了String是什么pchar是什么,自动/手动内存分配释放情况。
就像之前谁好心的提醒我,日期型跨平台怎么存一样。相信我嘛,是理解的。

总的来说很感谢大家的帮助。
具体这个问题,知道了是Delphi的内存管理在多线程下有效率问题,就好办多了。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
2022/9/22 12:40:37
38楼: 这边真正的挑战是没人做事。

我更希望把基础工作分下去,自己能多研究优化现有软件架构,多了解开源项目并引入实际应用,多熟悉各种新业务,甚至多到现场去多看看工程在怎么乱用我们的软件。

要阻止产品和工程代替开发进行设计,把不合理的逻辑细节写入技术建议书。
假设送货给客户,那么要求应该是货物完好,及时送达。
而不是说倒立过来,脚夹货物,用手走路,不能坐车,绕市区10圈。

还要阻止市场在开发评估前就签订了合同,再回来告诉我们,怎么做自己想,反正2个月要上线,客户希望之前能看到一个全功能的Demo,方便提修改意见。

退一步。
公司怎么运作我管不了。
至少别让我自己维护全部代码:)

再次感谢大家!!!

吐槽完了,与主题无关:)
----------------------------------------------
Bye bye DDRFAN...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 12:47:56
39楼: 好多年前我用delphi写过三层服务器,大几千在线连接,7、8百并发,大概清楚delphi的性能的,肯定不会比java慢。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/22 14:15:31
41楼: Java 开源的东西多,就越来越多。

Delphi 这个,曾经国外有人问过官方对未来的发展,是否有考虑走开源的道路,官方回答是没考虑这条路。那后果肯定是相关的资源跟不上其它开源项目多了。比如 Python 开源项目也多。
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 14:43:25
42楼: 我的想法
1、delphi在wdinows桌面程序应该没什么问题。
2、delphi开发web是短板。
3、开发安卓,如果把运行效率提高,把apk弄小,那delphi是有生命力的,比如delphi在安卓平台很容易使用jar,几乎无缝。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 14:49:00
43楼: 我十几年前写过三层服务器,几乎就是内存处理,当我看你的代码,我觉可优化空间很大
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲△ -
注册会员
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...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/22 15:15:22
44楼: 1、Windows下delphi写的程序,在debug窗口,看代码对应汇编指令,已经编译的很完美。
2、delphi就前十年做太烂,IDE的bug多,运行库都效率很低,delphi很多自带的库很慢,比如json,慢得令人发指,还好有不少开源库。搞笑是,前几年安卓下的字符串索引和windows不一致,以为emb要把Delphi弄死,还好11版以后注重质量了,算是第二春
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行56.64063毫秒 RSS