批量读取小文件问题

发布于 2022-03-07 04:48:06 字数 256 浏览 909 评论 9

windows机器上存储了大概2亿张小图片,每张170字节。

怎么才能高效的转移这批图片呢?

试过打压缩包,一次打包2000万张图要花5天,如果打包全部图片会直接报错内存不足。

也试着用java读取后图片转成base64,做成大文件再拷贝,但是每次都是大概前3w张图速度很快,1000张图只用100ms不到,3万张图之后任务管理里的磁盘io直接100%,效率直线下降,每1000张图要差不多10秒以上。

大神们有没有什么好办法?求赐教

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

夜司空 2022-03-11 05:24:51

曾经这样把一台满满的服务器大图转小图又续命几年。

这种暴力密集CPU和磁盘操作,多线程可能收益有限。关键是循环列表不要太大。

你如果用文件在这种目录下持续list,还for几下,可能会产生一个几亿的平方立方n次方次导致卡顿,建议:

1. 先建立一个多层次的树形分类规则,例如根据日期分年月日多层,把线性一维海量数据变成树,把每次处理几亿和重复处理,变成每次处理一个小型目录里有限集合。

2. 先写个程序把pic目录下图片每次读到一个就移动到映射的对应目录下去,这样你程序即便运行几万挂了,也是处理了几万张,下次继续处理也会越来越少。

3. 写个对单一目录操作函数, 合并大图,入数据库,转小图,高斯模糊还是进图片搜索索引什么的看自己需求。

4. 写个递归目录操作函数,把3用上,过程写日志,随时把握总体进度情况。

 

 

 

感情旳空白 2022-03-11 04:53:21

任何系统也不可能同时无限制打开文件,一个线程在阻塞环境下也只能做一件事,那就是要根据线程的数量做好规划,你需要有一个专门的线程去获取目录下的文件句柄(不读文件),然后将句柄丢给专门的读取文件的线程,读取文件的线程将内容读取到后给传输线程,传输线程与目标服务器保持连接,收到文件就将信息传输过去。比如你有四核8线程服务器,线程0留给系统,1读目录,234获取文件内容,567负责发送。向你一个for循环套for循环再套for循环,文件句柄就把资源耗光了。

顾挽 2022-03-11 04:49:43

多线程处理,才可以合理利用磁盘IO。度娘搜下多线程copy

瑾兮 2022-03-11 04:28:11

不是合并的文件过大导致的,我把后续处理的代码全到注释了,现在仅仅是读取,当读取到3万左右的时候就开始卡了,和是否生成文件没关系。怀疑是不是java没有释放干净导致的

沦落红尘 2022-03-11 04:18:11

3万张图之后任务管理里的磁盘io直接100%,效率直线下降

那就先每2W图片生成一个文件,然后再把生成的文件合并,一步一步的减少文件数量;

再结合使用下多线程

灵芸 2022-03-11 03:58:02

刚刚又看了一下,io没有占满,是活动时间占满。其实核心就几行代码,仅做了读取为byte,几秒后就会效率骤降。
File[] files_z = new File("pics").listFiles();
for(File file_z : files_z){

    File[] files_x = file_z.listFiles();

     for(File file_x : files_x ){

        FileUtils.readFileToByteArray(file_x);

    }
}

 

虐人心 2022-03-11 03:22:16

大佬,有这种经验吗?

归属感 2022-03-11 03:11:48

回复
在你目前的代码基础上,把3万张图片读出来(每张图片很小),转换base64编码后写到一个文件中(此时还数据还在内存中,并未保存到磁盘中),每3万张做一次flush到磁盘。这样可以减少磁盘写操作,读操作不会影响太多性能的。 我觉得3万张还是有点儿少,一张170个字节,10张还不到2k,3万张最多也就6000k(即6M左右),按照目前的硬件配置,完全可以每读30万张

猫九 2022-03-11 01:11:36

把你code贴出来

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文