{"id":104093,"date":"2020-08-19T07:00:00","date_gmt":"2020-08-19T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=104093"},"modified":"2020-09-09T06:12:37","modified_gmt":"2020-09-09T13:12:37","slug":"20200819-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200819-00\/?p=104093","title":{"rendered":"On using FILE_FLAG_WRITE_THROUGH and FILE_FLAG_NO_BUFFERING for memory-mapped files"},"content":{"rendered":"<p>A customer wanted to use the <code>FILE_<\/code><code>FLAG_<\/code><code>WRITE_<\/code><code>THROUGH<\/code> and <code>FILE_<\/code><code>FLAG_<\/code><code>NO_<\/code><code>BUFFERING<\/code> flags for a memory-mapped file, based on this guidance in the documentation for <code>Create\u00adFile<\/code>:<\/p>\n<blockquote class=\"q\">\n<p>For this reason, the <b>FILE_FLAG_WRITE_THROUGH<\/b> flag is often used with the <b>FILE_FLAG_NO_BUFFERING<\/b> flag as a replacement for calling the FlushFileBuffers function after each write, which can cause unnecessary performance penalties. Using these flags together avoids those penalties.<\/p>\n<\/blockquote>\n<p>The customer was concerned whether this combination of flags will affect data consistency.<\/p>\n<p>Actually, the customer&#8217;s problems with data consistency started even before they got around to worrying about these flags.<\/p>\n<p>Since they are using a memory-mapped file, they don&#8217;t have any direct control over when the memory gets written to disk. Page from memory-mapped files are written to disk at the operating system&#8217;s discretion. Therefore, if they write information into two pages of a memory-mapped file, the pages can be written to disk in any order.<\/p>\n<p>Since they&#8217;re asking about data consistency, they must be worried about power loss or system crashes before the data can be written to disk. And since the pages can be written in either order, all four outcomes of two dirty pages are possible.<\/p>\n<table class=\"cp3\" style=\"border-collapse: collapse; text-align: center;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Page 1 written to disk<\/th>\n<th>Page 2 written to disk<\/th>\n<\/tr>\n<tr>\n<td>No<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>Yes<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>No<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>So much for data consistency.<\/p>\n<p>Setting those flags on a memory-mapped file controls <i>how<\/i> the operating system writes the memory to disk, but it doesn&#8217;t provide any control over <i>when<\/i> the memory is written to disk. And without that control, you don&#8217;t really have data consistency.<\/p>\n<p>Usually, when designing a system for consistency, you have a specific order in which data needs to be written to the disk. For example, you might decide to write the new data to the disk, and then once that&#8217;s safe, you write new metadata (say, by updating an index) that causes the new data to become the active values, and the old data to be ignored. Those are the writes that would be able to take advantage of the write-through and buffering flags.<\/p>\n<p><b>Bonus chatter<\/b>: Using <code>FILE_<wbr \/>FLAG_<wbr \/>NO_<wbr \/>BUFFERING<\/code> with a memory-mapped file doesn&#8217;t really serve any purpose. The &#8220;no buffering&#8221; flag means that the writes go straight to the disk without being cached in memory. But the whole point of a memory-mapped file is to be cached in memory!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>You&#8217;re trying to control I\/O you didn&#8217;t issue.<\/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-104093","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>You&#8217;re trying to control I\/O you didn&#8217;t issue.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104093","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=104093"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/104093\/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=104093"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=104093"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=104093"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}