使用NTFS压缩写入文件比写入未压缩文件需要更多时间

时间:2015-07-28 11:47:12

标签: c# compression ntfs

描述here如何压缩文件,但该文件已经存在。

我稍微调整了一下,所以我现在尝试在创建文件流后立即创建一个文件上设置了NTFS压缩属性的文件,然后将数据添加到文件中。

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Diagnostics;

namespace Compress {
    class Program {
        [DllImport("kernel32.dll")]
        public static extern int DeviceIoControl(IntPtr hDevice, int
        dwIoControlCode, ref short lpInBuffer, int nInBufferSize, IntPtr
        lpOutBuffer, int nOutBufferSize, ref int lpBytesReturned, IntPtr
        lpOverlapped);
    static void Main(string[] args) {

        string fileName = @"D:\temp\t.txt";
        int lpBytesReturned = 0;
        int FSCTL_SET_COMPRESSION = 0x9C040;
        short COMPRESSION_FORMAT_DEFAULT = 1;

        byte[] data = new byte[4096];
        for (int i = 0; i < 4096; i++) {
            data[i] = 42;
        }

        Stopwatch timer = Stopwatch.StartNew();

        FileStream f = File.Open(fileName, System.IO.FileMode.OpenOrCreate,
            System.IO.FileAccess.ReadWrite, System.IO.FileShare.None);

        int result = DeviceIoControl(f.Handle, FSCTL_SET_COMPRESSION,
            ref COMPRESSION_FORMAT_DEFAULT, 2 /*sizeof(short)*/, IntPtr.Zero, 0,
            ref lpBytesReturned, IntPtr.Zero);


        for (int i = 0; i < 100000; i++) {
            f.Write(data, 0, data.Length);
        }

        f.Close();

        timer.Stop();

            Console.WriteLine("Time to write file = " + timer.ElapsedMilliseconds);
        }
    }
}

所以,我每次都在写大约4KB的数据。在我的系统上,这需要大约650毫秒。如果我删除了DeviceIoControl函数调用并运行相同的测试,那么它会快一点并且运行大约550毫秒(平均几次运行)。

根据this blog,我希望压缩会创建更少量的数据进行存储。

  

NTFS通过将数据流划分为CU来压缩文件(这类似于稀疏文件的工作方式)。当创建或改变流内容时,数据流中的每个CU被单独压缩。如果压缩导致一个或多个集群减少,则压缩单元将以其压缩格式写入磁盘。

几个问题:

什么可以解释我通过NTFS压缩存储数据时的时间增加?我没有注意到两次测试运行之间的CPU使用率(通过任务管理器)发生了实质性变化(两种情况下CPU稳定在5%)

压缩量也很小,文件大小为390MB,但磁盘大小只减少到259MB。考虑到数据是完全冗余的,为什么压缩量如此之低?

2 个答案:

答案 0 :(得分:0)

我无法确定你到底在做什么,但听起来你正在追加一个现有的压缩文件,一次4K。最重要的是,如果你只是让压缩机4K工作,你就不能期望太多的压缩。压缩取决于要压缩的历史和统计数据,并且需要的不仅仅是利用重复字符串和偏置频率分布。

如果您一次编写整个文件,您可能会看到更有效的压缩。

答案 1 :(得分:0)

我认为您的测试有点混乱 - 如果您想要可重复的结果,请使用FileMode.Create并让它每次都重建该文件。就目前而言,您在每次运行时都会添加到文件中。谁知道你有多少运行数据:-) FileMode.Create将创建该文件,或截断它(如果它存在)。我敢打赌,在您修复之后,您的压缩比会更合理。

压缩开销需要时间 - 即使数据非常流畅。你的数字对我来说看起来很合理 - CPU似乎永远不会被赋予任务,因为它正在做着“艰苦的工作”#34;每次同步 I / O请求只能压缩一次 - 因此CPU增加的开销根本不会使仪表倾斜很多 - 因为它在大多数I / O作业中展开。

此外 - NTFS压缩导致文件非常碎片 - 对于大文件尤其如此 - 并且不推荐使用。你最终得到一个类似稀疏的文件......一个会报告比实际用于存储文件的空间更多的文件。操作系统可以将类似稀疏的群集用于其他文件 - 但是大小报告会混乱。查看this维基百科文章(在文件压缩标题下)。