磁盘上有一个 100GB 的文件,里面每一行是一个 URL。
请写一个程序计算出现次数最多的 top 100 的 URL,以及它们分别出现的次数。
要求:程序使用最大内存 1GB,速度越快越好。
1.读取文件,对每一行url用hash函数计算分类。这里将文件分成499份(本机系统允许的打开文件的最大数量约为500个,选择了一个尽可能大的质数)。
2.对每一份文件分别选取出现次数最多的100条URL,再从这些URL中选取出现次数最大的100条。使用二叉堆进行选取。
C/C++
1.使用C风格的输入输出函数,加快文件读写速度。
2.使用线程并行处理分离后的小文件,加快处理速度。
系统:Windows10
CPU:AMD Ryzen 5 4600H 3.00 GHZ,8核
编译相关:g++ (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0,使用O2优化。
共三份样本。
第一份为用爬虫爬到的80k条URL,检测程序成功运行。
第二份用第一份中的80k条URL重复输入生成40G文件。读取和分块时间约为8分钟,总时长约为10分钟。
第三份为随机生成的长度在10-110之间的字符串文件,文件大小为40G。读取和分块时间约为8分钟,总时长约为20分钟。
在数据集中时,读取时间占比较长;在数据分散时,最后需要的计算时间更长。
能找到其他类似的项目,感觉有些可以尝试的点。
1.尝试用双缓存等方式,让读写并行运行。尝试过简单的线程方法但效果不理想。读取数据时没利用好内存,可以多做些尝试。
2.最后合并堆时限制结果大小为100个,加快运算速度。虽然我觉得导致延时的关键不在这里,但可以尝试。
3.内存测试。Windows下不方便做这一项。估算一下,如果文件被均匀拆分,每个文件约200MB。计算最多的URL时开启了四个线程,每个线程需要的内存大概也是200MB,理论上不会出问题。不过缺乏测试。