DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: cuiqingbo
今日帖子: 20
在线用户: 14
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 21:12:46
标题:
原来不是Pascal慢而是Delphi慢…… 浏览:3595
加入我的收藏
楼主: 在Windows下多线程读文件,一个线程对应一个文件。
看线程编号和日志输出顺序,用到了多线程。
看CPU占用率,对比单线程处理耗时,感觉是个假多线程。
D7和D11都一样。
只在Windows下有这个现象。

在Linux下,D11和其它语言的多线程明显比单线程快一些。

这是个长期困扰我的问题……
我总是觉得这么基础的东西,不应该有问题。
一定是我哪里没理解到,弄错了。

直到今天用Lazarus转换了一个较小的测试项目。代码几乎没变。
多线程正常了!!!

对比如下:
此帖子包含附件:
PNG 图像
大小:463.3K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 21:16:09
1楼: 之前不甘心,用各种语言,不同的机器试过,做了图表。
可以看到在Windows下Delphi单线程多线程是一个速度(误差不计)。

而Linux平台以及其它语言都是多线程快,单线程慢。

因为磁盘很快,所以瓶颈肯定不在读盘。
甚至试过只读不写(避免线程同步影响速度)也是一样的现象。
此帖子包含附件:
PNG 图像
大小:142.0K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 21:19:09
2楼: 1楼换了新机器,所以整体更快一些。
2楼是以前测试的,相对机器稍慢,但不影响对比。

除了读文本文件,没发现Delphi多线程用在其它方面(比如TCP通信)有任何问题。
真是神奇。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 iamdream (银河恒久远,梦想无止境!) ★☆☆☆☆ -
大贡献会员
2022/9/20 22:13:35
3楼: 你用什么方法来读文本文件的?不同方法速度可能相差很大。
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/20 22:21:25
4楼: @ddrfan (若苗瞬)
delphi 多线程下,换内存管理去试,比如tcmalloc,tbbmalloc,估计要快几倍,肯定不会比java慢
比java慢,估计用delphi算法也不对
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 22:32:46
4楼: @3楼

因为是文本按行读,所以之前一直都是用的:
var
  Afile :TextFile;
......
......
AssignFile(Afile,FFileName);
Reset(Afile); 
while not EOF(Afile) do
begin
  Readln(Afile,Aline);
  ......
end;
CloseFile(Afile);
Afile :TextFile;

试过其它的,比如读TFileStream,
以及TStreamReader。
都要更慢一些。

过去也用过映射(忘了怎么写了),
好像试过FileOpen那套的。

最后自己写了一个类,稍微比readln快一点点。
稍快一点点而已(没考虑中文编码),意义其实不大。
代码在这里:
https://blog.csdn.net/ddrfan/article/details/104844512

最后的测试都是用的这个类。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/20 22:42:43
5楼: 用TstringList或TmemoryStream去读,测一下,我觉得delphi不会慢,我认为是算法问题
如果是多线程时,用tcmalloc或tbbmalloc
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 22:49:02
5楼: @hq200306 (200306)

还没考虑过内存管理问题,因为只是些简单的字符串/字符串列表操作。
最主要问题不是慢,而线程和单线程一个速度。

现象是,虽然读取4个文件确实开了4个线程,
但似乎有个瓶颈,就仿佛4个线程需要轮流拿到什么资源才能读文件一样。

从实际速度看,从观察CPU占用率看,都和单线程一样。

仅 Windows+Delphi一个组合。

其它语言(呃包括lazarus+FPC),都可以看出速度,CPU占用率区别。
在Linux下则没有这个问题。

当然,图表中Delphi确实有点慢。
之前我还发过帖子说go快,然后被一顿diss。

因为磁盘足够快,其它正常的项目,文件会更多,
而且客户现场机器配置慢很多,所以多线程这个问题会被放大。

PS:现在测试Lazarus+FPC基本接近go的速度。(1.7秒 vs 1.4秒)
下面是go的:
此帖子包含附件:
PNG 图像
大小:314.2K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/20 22:51:27
6楼: delphi11用的是fastmm4,多线程下无法用到多cpu
你用一下TstringList,估计肯定快
我觉的是选择算法问题
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 22:52:44
6楼: @hq200306 (200306)

TStringList这个数据量读不出来的。

TMemoryStream和TFileStream在读一次的情况下,区别不大,都慢一些。
而且实际数据非常大,多线程同时读,内存不够的。

我也试过其它读的方式,见4楼。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 22:55:54
7楼: 我D7替换过一个新版的borlandmm.dll(是这名字吧),似乎和它无关。
为了测试Linux用的D11.
D7 和 D11 现象一样。。。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/20 23:01:31
8楼: @hq200306 (200306)

你上面说的“delphi11用的是fastmm4,多线程下无法用到多cpu”。
意思是只要多线程中有类似String A=B,就没法用到多CPU?

多CPU还是单个CPU多核心呀?
----------------------------------------------
Bye bye DDRFAN...
作者:
男 bcc2cc (bcc2cc) ▲▲▲▲△ -
普通会员
2022/9/20 23:04:04
8楼: 多线程和单线程速度一样,  

1. 排除硬盘本身瓶颈,  
2. 是否把读操作放在了 Thread的Sync 里面
3. 是否日志输出导致了同步等待

这个不大可能是内存上的问题, 内存分配这些相对于磁盘IO是忽略不计的高速
除非你内存极度缺乏, 导致内存分配本身已经变成了磁盘IO, 本质上还是磁盘瓶颈

虽然我很看不起delphi, 但是这种问题还是很容易规避解决的
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/20 23:10:51
9楼: TmemoryStream,我的笔记本读1.1G文件,第一次1.1秒,第二次读0.5秒,第三次0.27秒,
读350兆,第一次0.22秒,

你那722兆,估计在我笔记本上,估计不到一秒
----------------------------------------------
-
作者:
男 lsuper (lsuper) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 0:35:15
10楼: “对比单线程处理耗时,感觉是个假多线程” 无代码无真相,可以 demo 放出来挑战下?或者自己 aqtime、intel vtune 看下各代码耗时。

多说个:
1、简单看了下这个 ShionTextFileReadBufferSize 才 16k 不科学啊,建议 64m 之类的
2、log 解析算法各种字符搬运,建议 pchar + nrange 指向直接解读,避免频发开辟内存
3、默认的 fastmm4 不是无法用到多 cpu,而是效率不高;不过 delphi memorymanager 足够灵活随便切,譬如楼上的 tcmalloc、tbbmalloc 等
----------------------------------------------
-
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 1:09:25
11楼: 楼主把释放内存的时间不要算到运行时间里,大内存释放经常需要几十秒时间。Lazarus的内存是由内存管理器管理,其实是不释放的。
----------------------------------------------
只有偏执狂才能生存!
作者:
男 hawke2e (hawke2e) ★☆☆☆☆ -
普通会员
2022/9/21 6:46:28
12楼: 楼主反映的问题关键在:
同一套代码,delphi在windows下多线程的速度跟单线程的差不多;而fpc下则多线程要比单线程明显快。
那么,原因只有2个:
要么D在win下的内存管理有问题,要么D在win下相关组件的实现有问题;前者可能性最大。
“我总是觉得这么基础的东西,不应该有问题。”
----------------------------------------------
软件是什么,相信很多人都说不清。
作者:
男 chinaz (有缘人) ★☆☆☆☆ -
神秘会员
2022/9/21 7:51:31
13楼: 楼主,请提供源代码。包括go,辣子,windows的,令如果读取的样本文件太大,请放入百度盘下载。谢谢
----------------------------------------------
一路风雨走过,因为有你们
作者:
男 abencat (远离delphi的人) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 8:31:36
14楼: 换go
----------------------------------------------
delphi爱好者
作者:
男 seefall (Delfy) ★☆☆☆☆ -
普通会员
2022/9/21 8:38:27
15楼: 直接上fastMM5 啊
此帖子包含附件:seefall_202292184118.zip 大小:1.75M
----------------------------------------------
-
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/21 8:53:39
16楼: 我的电脑,在多线程下,fastmm5比delphi自带的fastmm4还慢
----------------------------------------------
-
作者:
男 sail2000 (小帆工作室) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 9:39:31
17楼: 对超过60MB的文件,打死都不读进 Tstream,用CreateFileMapping/MapViewOfFile
----------------------------------------------
delphi 是兴趣,和工作无关,即使它倒闭。又不靠它 delphi 吃饭,怕甚?
作者:
男 kentty (kentty) ★☆☆☆☆ -
普通会员
2022/9/21 11:04:19
18楼: 从LZ截图上来看,每个线程的任务包括了打开文件,逐行读取,分析判断(?),统计结果几个步骤,有没有可能是在分析判断这部分实现出现了瓶颈? 没有参考代码不好判断
----------------------------------------------
-
作者:
男 keymark (嬲) ▲▲▲△△ -
普通会员
2022/9/21 11:17:50
19楼: https://www.esegece.com/community/blog/fastmm4-vs-fastmm5-vs-fastmm4-avx
老外对fastmm进行测试。
----------------------------------------------
[alias]  co = clone --recurse-submodules  up = submodule update --init --recursiveupd = pullinfo = statusrest = reset --hard懒鬼提速https://www.cctry.com/>http://qalculate.github.io/downloads.htmlhttps://www.cctry.com/
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/21 11:50:19
20楼: 还是算法的问题,可优化空间太大了,delphi做好了,和c语言差不多。
比如:
1、多线程下用tcmalloc或tbbmalloc。
2、多线程下string改pchar。
3、逐行读,改较大buffer读。
4、检测线程是否正确使用。

tbb内存管理
https://en.delphipraxis.net/topic/7357-64bit-rtl-patches-with-intel-oneapi-and-tbb/
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 16:39:23
21楼: @hq200306 (200306)
“TmemoryStream,我的笔记本读1.1G文件,第一次1.1秒,第二次读0.5秒,第三次0.27秒,读350兆,第一次0.22秒,”
你是把每一行数据都读出来的么?
或者只是LoadFromFile了?

前者主要是要区分行“\n”所以会变慢不少。

后者仅仅是分配内存和磁盘读取文件的速度。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 16:48:50
22楼: @lsuper (lsuper)
我也想放源码,但虽然是小例子,部分也是客户在用的……
正式的用户数据也不能泄漏。

等有时间造一批脱敏的数据,然后简化一下业务相关的内容。
然后我自己测试如果现象依旧,再找大家帮忙。

这个程序很简单,
1)把多个类似csv格式的文本按行读出来
2)按照分隔符,拆分每行的字段到字符串列表。
3)简单的检查,比如列够不够,号码有86开头就去掉一类。
4) 通过检擦的数据,全部输出到一个文本文件。

没有自己申请内存,释放内存的内存管理……

试的其它语言也一样逻辑。

因为多线程写入一个文件可能有瓶颈。
所以Delphi把步骤4去掉测过,也是单线程/多线程一个速度。

PS:那个16k的buffer如果太大或太小,都会很慢,实测的,不太明白。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 16:51:42
23楼: @hawke2e (hawke2e)
你说的很对,
我主要想表达的并不是Delphi慢,

而是:多线程/单线程一个速度,这才是关键。

限定条件:
1)Windows下。
2)按行读文本文件。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 16:54:43
24楼: @kentty (kentty)
你说得很对。

我可以继续鉴权试试看:分析判断(?)去掉这一步。
统计结果,之前测试已经取消过的。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 16:58:00
25楼: 多谢大家关注。
我还是先弄出各种语言的样例程序。
简化掉业务无关的部分,

把源代码放上来。

确实无马无真相……
按此在新窗口浏览图片
----------------------------------------------
Bye bye DDRFAN...
作者:
男 seefall (Delfy) ★☆☆☆☆ -
普通会员
2022/9/21 17:19:15
26楼: :-)
此帖子包含附件:
JPEG 图像
大小:51.2K
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 17:25:08
27楼: 我也想不管它了……
可是这只是个最简单的例子。

实际有的业务内容复杂得多,解压后上百GB数据,又是几十个文件。
加上现场实施的服务器差得惊人。
我这30秒跑完,他们那2小时,完全hold不住。

记得几年前有个每天需要跑33小时的任务,我不知道每天哪里来33小时。
此帖子包含附件:
JPEG 图像
大小:14.1K
----------------------------------------------
Bye bye DDRFAN...
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 18:05:57
28楼: 楼主的情况,两种可能:
1. 楼主自己的代码,和线程相关部分,哪里有问题?

2. Windows 底下的读文件操作,多半是调用 Windows 的系统提供的什么鬼,和 Delphi 的线程配合,有问题。

但如果用 FPC 在 Windows 底下没有问题,那理论上 Delphi 也不该有问题。

其它的什么内存管理之类的,不会导致 Delphi 的多线程处理和单线程处理一个速度。

我在 Delphi XE 的年代测试过用 Delphi 的并行方法处理图片,在  4 核的 CPU 上,单线程处理的时间,差不多接近使用并行处理的 4 倍。没有完全到 4 但也差不多了。因此,Delphi 的多线程同时处理肯定是会用上所有 CPU 内核的。我做的那个测试,在 WINDOWS 上的测试结果和在手机安卓 APP 上测试的结果是一样的。。
----------------------------------------------
-
作者:
男 wr960204 (武稀松) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 18:18:45
29楼: 有测试代码吗,我觉得可能是你自己的问题。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/21 18:48:53
30楼: @ddrfan (若苗瞬)
多线程/单线程一个速度,这才是关键?

这个问题很简单
1、换内存管理器。
2、不要用string。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 19:19:21
29楼: 本人做了一个测试,读文件,计算 CRC,多线程和单线程顺序处理,速度上,多线程有明显提升。当然提升没有 4 倍那么多。

4个文件,写死文件名。

单线程的结果:
CRC1 = 2658044408; T1 = 157
CRC2 = 1065478231; T2 = 125
CRC3 = 2108868581; T3 = 187
CRC4 = 2294918490; T4 = 141
T 合计: 610;一个一个来,处理完需要 610 毫秒;

TT1 = 506850703
TT11 = 506850984
1 = 281

TT2 = 506850718
TT22 = 506850937
2 = 219

TT3 = 506850750
TT33 = 506851000
3 = 250

TT4 = 506850765
TT44 = 506850953
4 = 188

最小:506850703
最大:506851000
差:297

4 个 Task 来,总时间是 297 毫秒。

这里有点意思的是,每个 Task 里面,单独处理一个文件的时间,比在主线程里面一个文件一个文件处理的时间,变长得很明显。具体原因还没去查。

我这里读文件的方法是:
AssignFile(InFile, Fn);
blockread();

因此,看起来,Delphi 的 AssignFile 打开文件来读,在多线程底下,是没有问题的。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 19:20:14
31楼: 我的测试:Delphi 10.4.2 CE 版,一起都是默认设置,没有更改过 Delphi 的任何设置。是 Debug 模式。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/21 20:18:37
32楼: 有意思的结果来了。

上面的测试,我是使用 TTask 来做的。代码是连续做了 4 个 TTask.Run :

//1;
  Tasks[0] := TTask.Run(
    procedure
    var
      CRC: DWord;
    begin
      TT1 := GetTickCount;
      CRC := Self.GetFileCRC32(MY_PATH + Fn1);
      TT11 := GetTickCount;
      //TT1 := GetTickCount - TT1;
      TThread.Synchronize(nil,
        procedure
        begin
          Self.WriteLog('TT1 = ' + TT1.ToString);
          Self.WriteLog('CRC1 = ' + CRC.ToString);
          Self.WriteLog('');
        end
      )
    end
  );

  //2;
  Tasks[1] := TTask.Run(
    procedure
    var
      CRC: DWord;
    begin
      TT2 := GetTickCount;
      CRC := Self.GetFileCRC32(MY_PATH + Fn2);
      TT22 := GetTickCount;
      //TT2 := GetTickCount - TT2;

      TThread.Synchronize(nil,
        procedure
        begin
          Self.WriteLog('TT2 = ' + TT2.ToString);
          Self.WriteLog('CRC2 = ' + CRC.ToString);
          Self.WriteLog('');
        end
      )
    end
  );

... 底下还有 2 个 TTask.Run;

上面的代码,结果是每个任务花费的时间明显延长。当然,因为任务是并发的,从第一个任务启动到最后一个任务完成,总耗时比单线程一个一个地计算文件的 CRC 还是明显缩短。

但是,我如果用 TThread 类,则每个线程的计算时间,就接近单线程的时候处理一个文件的时间差不多了。当然,因为是并发,总耗时明显缩短。代码:

procedure TMyThread.Execute;
begin
  inherited;

  FTa := GetTickCount;
  Form1.GetFileCRC32(Self.FFn);
  FTb := GetTickCount;

  TThread.Synchronize(Self,
    procedure
    begin
      Form1.WriteLog('TT1 = ' + Self.FTa.ToString);
      Form1.WriteLog('TT2 = ' + Self.FTb.ToString);
      Form1.WriteLog('耗时 = ' + (Self.FTb - Self.FTa).ToString);
      Form1.WriteLog('');
    end
  );
end;

使用线程的代码:

procedure TForm1.Button4Click(Sender: TObject);
var
  Th1, Th2, Th3, Th4: TMyThread;
  T: Cardinal;
begin
  T := GetTickCount;
  Th1 := TMyThread.Create(True);
  Th2 := TMyThread.Create(True);
  Th3 := TMyThread.Create(True);
  Th4 := TMyThread.Create(True);


  Th1.FFn := MY_PATH + Fn1;
  Th2.FFn := MY_PATH + Fn2;
  Th3.FFn := MY_PATH + Fn3;
  Th4.FFn := MY_PATH + Fn4;

  Th1.Start;
  Th2.Start;
  Th3.Start;
  Th4.Start;

  T := GetTickCount - T;
  Memo1.Lines.Add('T = ' + T.ToString);
end

这里,按钮事件,创建4个线程,花费的时间是 0;
然后,每个线程的执行时间是:

TT1 = 509856031
TT2 = 509856156
耗时 = 125

TT1 = 509856031
TT2 = 509856171
耗时 = 140

TT1 = 509856031
TT2 = 509856234
耗时 = 203

TT1 = 509856031
TT2 = 509856265
耗时 = 234

实际上看数据 4 个线程基本上是同时启动的,最长完成时间是 234. 那么,这个也是4个文件完成的总时间:234;

回头看看单线程逐个处理 4 个文件的结果:
CRC1 = 2658044408; T1 = 157
CRC2 = 1065478231; T2 = 125
CRC3 = 2108868581; T3 = 187
CRC4 = 2294918490; T4 = 141
T 合计: 610

这里,用4个线程处理 4 个文件,单个文件的处理时间花费,和一个主线程顺序处理4个文件的单个文件时间花费,基本上差不多,但还是会多一点。但单线程顺序处理的前后总时间就大太多了。

在我的这个例子中,就是 610 / 234 = 2.606837606837607 倍。

那么,使用 Delphi 多线程处理文件,肯定还是比单线程逐个处理,快很多的。我这里只是用了 4 个线程。不知道更多内核的 CPU 用更多线程会如何。

为了避免硬盘瓶颈带来的问题,这里我是把文件放到 SSD 盘上的。没测试机械硬盘会如何。

我的测试文件大小:
1. 44.2 MB
2. 32.7 MB
3. 49.3 MB
4. 36.4 MB

结论:Delphi 程序在 WINDOWS 底下读入文件来处理,多线程是没有问题的,不会有多线程变成多个线程顺序执行的问题,依然可以并发运行。

所以,楼主,一定是你的代码,哪里出了问题。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/21 22:42:53
33楼: 楼上各位好心人
代码在这里:http://bbs.2ccc.com/topic.asp?topicid=640128
一楼附件

按此在新窗口浏览图片
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wk_knife (wk_knife) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 23:25:55
34楼: 我觉得你们要从一个脱离实际问题的高度来思考这个问题。就是其实各语言实现多线程的逻辑是差不多的,所以基本不可能会产生所谓delphi的多线程不起作用的问题,肯定是别的方面的问题导致的。如果只是讨论多线程就可以打住了,如果是想挖出影响速度的因素在哪里,就请继续......

曾经我也读过几个G,最大到100G的文件。不过我那个是通过头部的数据定义,可以计算偏移量读取具体所需的数据。也是期望用多线程加快速度,后来也发现和单线程速度差不多,当年的瓶颈是在磁盘IO上,现在固态是不是应该好些。
----------------------------------------------
-
作者:
男 wk_knife (wk_knife) ★☆☆☆☆ -
盒子活跃会员
2022/9/21 23:32:14
35楼: 之前读过的大文件,最早是存放在磁带上的,后来从磁带过渡到磁盘。现在为了提高读取速度,已经开始使用新的方法管理文件,就是把大文件拆成一堆小文件。把文件索引信息放到一个本地类似sqlite这样的库里。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/22 9:25:07
36楼: @wk_knife (wk_knife)
确实多线程本身没有问题的,
配合String就有问题了。

有好多热心同学在讨论,但没注意这个逻辑:
仅【delphi+win+string+多线程】有问题,其它组合都没问题。

我只是没想到,delphi默认的内存管理,居然有这样的缺陷。
其它语言都没发现这种问题。

你说的通过文件头偏移量seek应该也不会有问题。

有兴趣可以继续看看这贴:http://bbs.2ccc.com/topic.asp?topicid=640128

Blockread,小buffer(100byte)版本,单/多线程速度比例正常。
如果加大buffer,则1秒读完1GB没问题。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 bbnn38 (伟大的咸鱼) ★☆☆☆☆ -
普通会员
2022/9/23 0:11:08
37楼: 留名关注后续。
----------------------------------------------
-
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/23 11:43:17
38楼: 总结了一下:
https://blog.csdn.net/ddrfan/article/details/127003880
----------------------------------------------
Bye bye DDRFAN...
作者:
男 kwer (★★★★★) ★☆☆☆☆ -
普通会员
2022/9/23 13:26:52
39楼: stringlist.loadfromfile() 可以自动分行的,你就不用费劲巴拉的一行一行的搞,一口气就劈下来了。。。就是不知道1G大小文件能不能hold得住?
----------------------------------------------
==========-==========-==========-==========-==========
     多隆, 给我备一匹最快的马, 我有事要走先~~~
==========-==========-==========-==========-==========
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/23 14:05:54
40楼: String 慢,有几个理由:
1. 加载内容到 String,可能需要一些内部的转换。这些转换是需要时间的。总之就是 Unicode 的那一堆问题。

2. 不停地创建,释放 String 也就是要不停的分配内存;这个是非常消耗 CPU 的。尽量不要重新分配内存。

楼上,LoadFromFile 就是全部加载进内存,1G 的文件,估计不行。
----------------------------------------------
-
作者:
男 kwer (★★★★★) ★☆☆☆☆ -
普通会员
2022/9/23 14:19:39
41楼: 我刚试过了32位肯定不行,但是64位没有问题,而且也很快。。。PS:我用lazarus
----------------------------------------------
==========-==========-==========-==========-==========
     多隆, 给我备一匹最快的马, 我有事要走先~~~
==========-==========-==========-==========-==========
作者:
男 wac1104 (火鸟) ★☆☆☆☆ -
普通会员
2022/9/23 14:48:17
42楼: 试试我的csvreader
此帖子包含附件:wac1104_2022923144817.zip 大小:9.0K
----------------------------------------------
火鸟
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/23 14:56:33
43楼: @kwer (★★★★★)
用StringList只能加载比较小的数据,而且慢。
数据量稍大就不行了。

而且文件多了,内存也不够用。

读的方式请参考总结:
https://blog.csdn.net/ddrfan/article/details/127003880

写完后我又测试了tcMalloc,准备再试试tccMalloc。
弄完了我会再更新一下。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 ddrfan (若苗瞬) ▲▲▲▲▲ -
普通会员
2022/9/23 15:04:52
44楼: @wac1104 (火鸟)
多谢!
我再研究一下。

大家别看CSV简单,但实际记录内容中是允许有换行的,
加上有没有字段头,还有容错……

所以很多语言提供的内置方法都不能完全兼容呢。
----------------------------------------------
Bye bye DDRFAN...
作者:
男 wac1104 (火鸟) ★☆☆☆☆ -
普通会员
2022/9/23 15:52:52
45楼: 这种解析,要是需要性能,最好自己解析,写个状态机。
----------------------------------------------
火鸟
作者:
男 hq200306 (200306) ★☆☆☆☆ -
普通会员
2022/9/27 20:12:46
46楼: go语言内存管理用的和tcmalloc相类似的技术,快一点很正常
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2022/9/27 20:48:42
47楼: 其实处理 string 最大的问题是各种编码。Delphi 的 string 在内部把编码搞定了。

假设不考虑编码,就是 ASCII 字符。直接用字节序列,字节一个字节一个字节地用状态机分析,绝对快。

假设是多语言混合的文件,不考虑编码就不行了。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行164.0625毫秒 RSS