复制一个文件需要做的有1-3步:1、在目标位置创建对应的文件名项,因为文件名也是要保存在磁盘上的;2、如果文件有内容,把文件内容写入磁盘,并按照块对齐(512字节-64K不等)3、如果文件有内容,在一个特定的位置把文件内容的块的信息记录下来,标记这些块属于这个文件并且是被使用了。
因为题主问的是1M的文件,所以这三步都是需要的。对于1G的文件,需要的也是这三步,对于1024个1M的文件,需要的是1024×3步。对于磁盘设备有IOps的概念,就是每秒能执行的I/O次数,对于复制1024个1M文件来说,那么至少需要1024*3次I/O,对于1G的文件来说,至少需要3次。所以从次数来说,复制小文件越多,磁盘读写次数越多,虽然有cache等一系列优化的机制,但整体次数还是要高很多的。
并且,磁盘写1字节,和写512字节(一个扇区)的代价是相同的,虽然写入文件名短,但仍然需要写入512字节(一个扇区)。因此写1G文件就至少要比写1024*1M文件多写512K这么多数据。如果说512K这么多数据好像也不太多,但还有一个不可忽略的操作就是比较文件名:复制文件的时候,需要判断是否有重名,复制1个文件,检查1次就可以了,复制1024个文件,就需要检查1024次,并且随着文件的增多,检查的负担也越重(要跟之前的文件都检查一下)。
复制一个文件需要做的有1-3步:1、在目标位置创建对应的文件名项,因为文件名也是要保存在磁盘上的;2、如果文件有内容,把文件内容写入磁盘,并按照块对齐(512字节-64K不等)3、如果文件有内容,在一个特定的位置把文件内容的块的信息记录下来,标记这些块属于这个文件并且是被使用了。
因为题主问的是1M的文件,所以这三步都是需要的。对于1G的文件,需要的也是这三步,对于1024个1M的文件,需要的是1024×3步。对于磁盘设备有IOps的概念,就是每秒能执行的I/O次数,对于复制1024个1M文件来说,那么至少需要1024*3次I/O,对于1G的文件来说,至少需要3次。所以从次数来说,复制小文件越多,磁盘读写次数越多,虽然有cache等一系列优化的机制,但整体次数还是要高很多的。
并且,磁盘写1字节,和写512字节(一个扇区)的代价是相同的,虽然写入文件名短,但仍然需要写入512字节(一个扇区)。因此写1G文件就至少要比写1024*1M文件多写512K这么多数据。如果说512K这么多数据好像也不太多,但还有一个不可忽略的操作就是比较文件名:复制文件的时候,需要判断是否有重名,复制1个文件,检查1次就可以了,复制1024个文件,就需要检查1024次,并且随着文件的增多,检查的负担也越重(要跟之前的文件都检查一下)。
其实这个事情,简单的说,就是 Windows 的文件系统对小文件的优化不到位。原因可能有很多,大家很多人都已经说了,我就不重复。我理解刘贺的意思。不过其实大家也都理解题主说的一定是 Windows。ext4 在这个问题上确实有明显优势,但要认真去研究这个问题其实很难的,原因是:在 Linux 这样的我们能看到源代码并进行分析的系统中,其实这个现象并不特别明显。从纯学术的角度来看,无法推断问题发生的原因。
在 Windows 系统中虽然很容易重现这个现象,但我们无法分析其原因,因为没有源代码。所以这个问题的真正答案,恐怕只有微软的内部人员可以给出。
设你是操作系统开发者,设身处地去想就很容易理解了。比如你知道读硬盘时寻道是很慢的,所以你的读文件操作的实现是预先往前读多比如几百k(虽然用户指定的是几十k),到内存或者硬件(硬盘自带的)cache,如果刚好用户也是想读下几百k,那这时你从内存提交到用户,不用硬盘的机械设施去寻址读入,显然速度就高了……这只是通俗不严谨的例子……
这里面其实有很多层抽象层次和策略,要对体系结构和操作系统有一定思想性的了解才有体会。但再多优化也不外如是基本原理:分层体系,cache和预测策略。






