I've an application which writes a single file of size 1 TB on a NTFS volume. The writes to this are not done sequentially. There are multiple threads which writes to different offset of the file. It is guaranteed that all the regions in file will be written by the application. In this, if a thread tries to write at some offset which is closer to the end of file (say at 900 GB offset), the program gets stuck for a while. This is because windows tries to backfill zeros in all the "unwritten" area of the file before that.
As a workaround of this problem, I marked the file as sparse before doing any writes using IOCTL call -https://learn.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_set_sparse
After this, there is no backfill of zeros done by windows and the program runs faster. But, with using sparse file and random writes, there is a lot of fragmentation. On running contig for this file, I'm getting 1085463 fragments. But on some runs, the number of fragments becomes more than 1.5 million and file sync call fails with this error - "The requested operation could not be completed due to a file system limitation"
Contig v1.83 - Contig
Copyright (C) 2001-2023 Mark Russinovich
Sysinternals
D:\data\db1.mdf is in 1085463 fragments
Summary:
Number of files processed: 1
Number unsuccessfully procesed: 0
Average fragmentation : 1.08546e+06 frags/file
PS C:\Users\Administrator\Downloads\Contig>
The application is doing writes of 512 KB size. Assuming each write call is out of order and creates a new fragment, it is possible that after 512KB*1500000 = 732 GB file writes, the limit is reached.
Is there a way I can tell windows to preallocate space for spare file so that there is less fragmentation?
Or if not with sparse file, is it possible to do random writes on a non-sparse file without backfilling zeros?