node.js - 为什么在本地节点上使用 createReadStream(文件读取)时以随机速度完成读取?
问题描述
我正在使用createReadStream
api 从文件中读取大量数据。有时阅读需要 7 秒,有时阅读需要 30 秒。我想了解为什么在某些情况下读取具有相同数据的相同文件需要更多时间,而在少数情况下需要更少时间。为什么它不是固定时间,因为我正在读取具有相同数据的相同文件?
解决方案
以下是一些可能的原因:
1.磁盘缓存。 操作系统有一个磁盘缓存,并在它知道可以安全使用缓存时使用它。这通常会使某些数据的第一次读取速度变慢(因为它是直接从磁盘读取的),而稍后读取相同数据的速度会更快(如果操作系统认为它可以成功缓存并且不会太大而无法缓存并且它保持不变)在缓存中)。
2. Nodejs 事件循环的不可预测性。 读取大量数据必然需要读取文件的很多块,每一个读取操作都会经过nodejs事件循环。如果还有其他事件也被插入到事件循环中,则与磁盘读取相关的事件有时可能不得不等待轮到它们。
3.垃圾收集器的不可预测性。 如果您正在处理大量数据(即使不是一次全部在内存中),您可能会在 nodejs 堆中创建大量对象,其中许多对象需要进行垃圾回收。最终,垃圾收集器将不得不运行,并且可能会在您的代码执行中引入一些暂停。如果在操作期间多次发生这种情况,这可能会变得很明显。
4. 磁盘繁忙程度的可变性。 磁盘读/写磁头(假设这是一个旋转磁盘并且操作系统正在从实际磁盘读取)一次只能在一个磁道上。如果它正忙于读取操作系统要求它读取的其他内容,您的请求可能必须等待一些先前的请求完成。这通常不会增加很多秒,但它可能会导致一些变化。作为最坏情况的一个示例,操作系统可能正在您的硬盘驱动器上运行碎片整理操作,您的磁盘操作必须与该操作交错。
5. 操作系统/CPU 繁忙度。 如果操作系统或 CPU 忙于做其他事情,您的应用程序可能无法获得完整的运行周期。
6、Nodejs线程池忙。 Nodejs 使用默认大小为 4 的线程池进行磁盘操作。如果您碰巧同时有多个磁盘操作(或其他使用线程池的操作)在运行并最大化线程池,那么您的操作可能必须等待某个先前的操作完成,然后才能分配一个线程到运行您的磁盘操作。线程池的大小是可定制的,但使其大于您拥有的实际 CPU 内核的数量可能没有帮助。
推荐阅读
- sql-server - 无法从 AspNetCore 应用程序连接 Docker MsSql
- rx-java2 - 阻塞 RxAndroidBle 写操作
- python - 使用内置 inception 脚本将图像目录转换为 tfrecords
- kdb - 在上一个查询完成之前停止进程运行的最佳方法是什么?
- sharepoint - 更改所有 SharePoint Online 对象中的网站 URL
- php - 问题自动加载类 PHP Slim 框架
- json - 为什么我的程序不使用 Python3 从 url 中检索图像?
- python - OpenCV-错误检测
- mongoose - 即使我使用 addToSet,mongoose unique 在对象的子项中也不起作用
- java - 如何在 Android 设备上为相机应用创建裁剪框?