{"id":9573,"date":"2011-09-22T07:00:00","date_gmt":"2011-09-22T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2011\/09\/22\/why-does-my-single-byte-write-take-forever\/"},"modified":"2011-09-22T07:00:00","modified_gmt":"2011-09-22T07:00:00","slug":"why-does-my-single-byte-write-take-forever","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20110922-00\/?p=9573","title":{"rendered":"Why does my single-byte write take forever?"},"content":{"rendered":"<p>\nA customer found that a single-byte write was taking several seconds,\neven though the write was to a file on the local hard drive that was\nfully spun-up.\nHere&#8217;s the pseudocode:\n<\/p>\n<pre>\n\/\/ Create a new file - returns quickly\nhFile = CreateFile(..., CREATE_NEW, ...);\n\/\/ make the file 1<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2009\/06\/11\/9725386.aspx\">GB<\/a>\nSetFilePointer(hFile, 1024*1024*1024, NULL, FILE_BEGIN);\nSetEndOfFile(hFile);\n\/\/ Write 1 byte into the middle of the file\nSetFilePointer(hFile, 512*1024*1024, NULL, FILE_BEGIN);\nBYTE b = 42;\n\/ this write call takes several seconds!\nWriteFile(hFile, &amp;b, &amp;nBytesWritten, NULL);\n<\/pre>\n<p>\nThe customer experimented with using asynchronous I\/O,\nbut it didn&#8217;t help.\nThe write still took a long time.\nEven using <code>FILE_FLAG_NO_BUFFERING<\/code>\n(and\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2010\/04\/14\/9995509.aspx\">\nwriting full sectors, naturally<\/a>)\ndidn&#8217;t help.\n<\/p>\n<p>\nThe reason is that on NTFS, extending a file reserves disk space but\ndoes not zero out the data.\nInstead, NTFS keeps track of the &#8220;last byte written&#8221;,\ntechnically known as the\n<i>valid data length<\/i>,\nand only zeroes out up to that point.\nThe data past the valid data length\nare logically zero but are not\nphysically zero on disk.\nWhen you write to a point past the current valid data length,\nall the bytes between the valid data length and the start of\nyour write need to be zeroed out before the new valid data length\ncan be set to the end of your write operation.\n(You can manipulate the valid data length directly with\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/aa365544.aspx\">\nthe <code>Set&shy;File&shy;Valid&shy;Data<\/code> function<\/a>,\nbut be very careful since it comes with serious security implications.)\n<\/p>\n<p>\nTwo solutions were proposed to the customer.\n<\/p>\n<p>\nOption&nbsp;1 is to force the file to be zeroed out immediately\nafter setting the end of file by writing a zero byte to the end.\nThis front-loads the cost so that it doesn&#8217;t get imposed on\nsubsequent writes at seemingly random points.\n<\/p>\n<p>\nOption&nbsp;2 is to\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/aa365564.aspx\">\nmake the file sparse<\/a>.\nMark the file as sparse with the\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/aa364596.aspx\">\n<code>FSCTL_SET_SPARSE<\/code> control code<\/a>,\nand\nimmediately after setting the end of file,\nuse\n<a HREF=\"http:\/\/msdn.microsoft.com\/library\/aa364597.aspx\">\nthe <code>FSCTL_SET_ZERO_DATA<\/code> control code<\/a>\nto make the entire file sparse.\nThis logically fills the file with zeroes without committing physical\ndisk space.\nAnywhere you actually write gets converted from &#8220;sparse&#8221; to &#8220;real&#8221;.\nThis does open the possibility that a later write into the middle\nof the file will encounter a disk-full error,\nso it&#8217;s not a &#8220;just do this and you won&#8217;t have to worry about\nanything&#8221; solution,\nand depending on how randomly you convert the file from &#8220;sparse&#8221;\nto &#8220;real&#8221;, the file may end up more fragmented than it would have\nbeen if you had &#8220;kept it real&#8221; the whole time.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A customer found that a single-byte write was taking several seconds, even though the write was to a file on the local hard drive that was fully spun-up. Here&#8217;s the pseudocode: \/\/ Create a new file &#8211; returns quickly hFile = CreateFile(&#8230;, CREATE_NEW, &#8230;); \/\/ make the file 1GB SetFilePointer(hFile, 1024*1024*1024, NULL, FILE_BEGIN); SetEndOfFile(hFile); \/\/ [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-9573","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>A customer found that a single-byte write was taking several seconds, even though the write was to a file on the local hard drive that was fully spun-up. Here&#8217;s the pseudocode: \/\/ Create a new file &#8211; returns quickly hFile = CreateFile(&#8230;, CREATE_NEW, &#8230;); \/\/ make the file 1GB SetFilePointer(hFile, 1024*1024*1024, NULL, FILE_BEGIN); SetEndOfFile(hFile); \/\/ [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/9573","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=9573"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/9573\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=9573"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=9573"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=9573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}