{"id":103436,"date":"2020-02-13T07:00:00","date_gmt":"2020-02-13T15:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=103436"},"modified":"2020-09-11T15:24:53","modified_gmt":"2020-09-11T22:24:53","slug":"20200213-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200213-00\/?p=103436","title":{"rendered":"Survey of Windows update formats: The Quality update, which obsoletes all the others"},"content":{"rendered":"<p>We&#8217;ve spent the past few days learning about <a title=\"Survey of Windows update formats: The Full update\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200210-00\/?p=103426\"> Full updates<\/a>, <a title=\"Survey of Windows update formats: The Delta update\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200211-00\/?p=103430\"> Delta updates<\/a>, and <a title=\"Survey of Windows update formats: The Express update\" href=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/20200212-00\/?p=103434\"> Express updates<\/a>. All that was just background information! Finally we can talk about the thing I actually wanted to talk about: The Quality update, which obsoletes them all.<\/p>\n<p>The <b>Quality update<\/b> takes a different approach to patching: Not only does it patch a file forward to the latest version, it also patches the latest version of the file <i>backward<\/i> to the original version.<\/p>\n<table style=\"border-collapse: collapse; text-align: center;\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<th style=\"padding: 3px;\" rowspan=\"2\">Update<\/th>\n<th style=\"padding: 3px; width: 5em;\" rowspan=\"2\">Full file<\/th>\n<th style=\"padding: 3px;\" colspan=\"5\">Patch base<\/th>\n<th style=\"padding: 3px;\" rowspan=\"2\">Reverse<br \/>\npatch<\/th>\n<\/tr>\n<tr>\n<th style=\"padding: 3px; width: 5em;\">M0<\/th>\n<th style=\"padding: 3px; width: 5em;\">M1<\/th>\n<th style=\"padding: 3px; width: 5em;\">M2<\/th>\n<th style=\"padding: 3px; width: 5em;\">M3<\/th>\n<th style=\"padding: 3px; width: 5em;\">M4<\/th>\n<\/tr>\n<tr>\n<th style=\"padding: 0;\">M1<\/th>\n<td style=\"padding: 0;\" valign=\"baseline\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M1<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: solid solid none; border-radius: 4px 4px 0 0; padding: 3px; margin: 3px 3px 0 3px; background-color: #d9ffdf;\">M0\u00a0to\u00a0M1<\/div>\n<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: solid solid none; border-radius: 4px 4px 0 0; padding: 3px; margin: 3px 3px 0 3px; background-color: #d9ffdf;\">M1 to M0<\/div>\n<\/td>\n<\/tr>\n<tr>\n<th style=\"padding: 0;\">M2<\/th>\n<td style=\"padding: 0;\" valign=\"baseline\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M2<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: none solid; padding: 3px; margin: 0 3px; background-color: #d9ffdf;\">M0\u00a0to\u00a0M2<\/div>\n<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M1 to M2<\/span><\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: none solid; padding: 3px; margin: 0 3px; background-color: #d9ffdf;\">M2 to M0<\/div>\n<\/td>\n<\/tr>\n<tr>\n<th style=\"padding: 0;\">M3<\/th>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\">\n<div style=\"border: 1px black; border-style: none solid; padding: 3px; margin: 0 3px; background-color: #d9ffdf;\">\u00a0<\/div>\n<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\">\n<div style=\"border: 1px black; border-style: none solid; padding: 3px; margin: 0 3px; background-color: #d9ffdf;\">\u00a0<\/div>\n<\/td>\n<\/tr>\n<tr>\n<th style=\"padding: 0;\">M4<\/th>\n<td style=\"padding: 0;\" valign=\"baseline\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M4<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: none solid; padding: 3px; margin: 0 3px; background-color: #d9ffdf;\">M0\u00a0to\u00a0M4<\/div>\n<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M1 to M4<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M2 to M4<\/span><\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: none solid; padding: 3px; margin: 0 3px; background-color: #d9ffdf;\">M4 to M0<\/div>\n<\/td>\n<\/tr>\n<tr>\n<th style=\"padding: 0;\">M5<\/th>\n<td style=\"padding: 0;\" valign=\"baseline\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M5<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: none solid solid; border-radius: 0 0 4px 4px; padding: 3px; margin: 0 3px 3px 3px; background-color: #d9ffdf;\">M0\u00a0to\u00a0M5<\/div>\n<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M1 to M5<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M2 to M5<\/span><\/td>\n<td style=\"padding: 0;\">\u00a0<\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\"><span style=\"padding: 3px; color: #bbb; text-decoration: line-through;\">M4 to M5<\/span><\/td>\n<td style=\"padding: 0;\" valign=\"baseline\" nowrap=\"nowrap\">\n<div style=\"border: 1px black; border-style: none solid solid; border-radius: 0 0 4px 4px; padding: 3px; margin: 0 3px 3px 3px; background-color: #d9ffdf;\">M5 to M0<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The Quality update includes only the two sets of patches, one to get from the initial version to the latest, and one to get from the latest version back to the original.<\/p>\n<table style=\"border-collapse: collapse;\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\">\n<tbody>\n<tr>\n<th>Quality update<\/th>\n<th>Contents<\/th>\n<\/tr>\n<tr>\n<th>M1<\/th>\n<td>M0 to M1, M1 to M0<\/td>\n<\/tr>\n<tr>\n<th>M2<\/th>\n<td>M0 to M2, M2 to M0<\/td>\n<\/tr>\n<tr>\n<th>M3<\/th>\n<td>M0 to M2, M2 to M0<\/td>\n<\/tr>\n<tr>\n<th>M4<\/th>\n<td>M0 to M4, M4 to M0<\/td>\n<\/tr>\n<tr>\n<th>M5<\/th>\n<td>M0 to M5, M5 to M0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Note that the M3 Quality update is the same as the M2 Quality update since the file <code>F<\/code> did not change between M2 and M3.<\/p>\n<p>The secret to the Quality update is that the client retains the patches necessary to bring its files back to the M0 version. At the release of M0, this is vacuous: The files are already at their M0 version, so no patches are needed. We&#8217;ll see how this invariant is maintained at each subsequent update.<\/p>\n<p>Applying a Quality update consists of downloading the update, and then for each file in the update, applying <i>two<\/i> sets of patches: First patch the current file <i>backward<\/i> to the original M0 version using the patch cached on the client. Second, patch the M0 file <i>forward<\/i> to the version targeted by the Quality update. The resulting fully-patched file goes onto the system, and the backward patch included in the Quality update is saved on the system in preparation for the next Quality update.<\/p>\n<p>By analogy, it would be as if you wanted to meet with a bunch of friends, but instead of having to give different directions to each friend, you tell everybody, &#8220;Okay, start at the library, and then&#8230;&#8221; You trust that everybody knows how to get to the library, and you give one set of directions that tells how to get to the final destination from the library. You also give directions from the meeting place back to the library, so they are ready for the next time you need to meet somewhere. (Okay, so that&#8217;s not really a good analogy, because your friends probably want to go home, not to the library.)<\/p>\n<p>The total disk space required on the server is (eyeballs <a href=\"https:\/\/techcommunity.microsoft.com\/t5\/Windows-IT-Pro-Blog\/What-s-next-for-Windows-10-and-Windows-Server-quality-updates\/ba-p\/229461\"> the graph in the blog post<\/a>) roughly 250<a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20090611-00\/?p=17933\/\">MB<\/a> for the pair of patches. This is the smallest server footprint of all the patches we&#8217;ve been looking at this week.<\/p>\n<p>Note that the download size of a Quality update is less than double the size of an Express update download. I suspect this is because the reverse patch can take advantage of the bytes in the M0 file that were calculated as part of applying the Quality update. For example, if the reverse patch would have said &#8220;Replace bytes 2000 through 3999 with these following 2000 bytes,&#8221; the information downloaded from the server could say &#8220;Replace bytes 2000 through 3999 with bytes 5000 through 6999 of the M0 file you already have.&#8221; This removes 2000 bytes from the download, and the client can get the 2000 bytes from the M0 file that it had temporarily created as part of applying the Quality update. In that way, what the client really downloads is not so much a reverse patch as it is a <i>template<\/i> for a reverse patch.<\/p>\n<p>Feature summary of Quality updates:<\/p>\n<ul>\n<li>Quality updates can successfully update all customers, since every client knows how to roll back to M0, at which point they can apply the patch in the Quality update to move forward.<\/li>\n<li>Quality updates are about a third the size of a Full update.<\/li>\n<li>Quality updates require very little negotiation with the server. Every customer downloads the same update.<\/li>\n<li>Quality updates are cache-friendly, because every customer downloads the same update. Therefore, caching features like caching proxies, <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows-server\/networking\/branchcache\/branchcache\"> BranchCache<\/a>, and <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/deployment\/update\/waas-delivery-optimization\"> peer-to-peer delivery<\/a> are effective.<\/li>\n<li>Quality updates do not require significant server support. Once the package is negotiated, it is delivered in its entirety.<\/li>\n<\/ul>\n<p>The blog article that announced the change to Quality updates reports <a href=\"https:\/\/techcommunity.microsoft.com\/t5\/Windows-IT-Pro-Blog\/What-s-next-for-Windows-10-and-Windows-Server-quality-updates\/ba-p\/229461\"> a 40% improvement in memory usage on the client compared to Express updates<\/a>, since the client doesn&#8217;t need to do an inventory of all the files on the system.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Supports everything the others do, at a fraction of the price.<\/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":[26],"class_list":["post-103436","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Supports everything the others do, at a fraction of the price.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103436","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=103436"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/103436\/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=103436"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=103436"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=103436"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}