{"id":250,"date":"2008-12-01T19:40:09","date_gmt":"2008-12-02T02:40:09","guid":{"rendered":"http:\/\/eriknovales.com\/blog\/index.php\/2008\/12\/01\/optimization-tradeoffs\/"},"modified":"2008-12-01T19:40:09","modified_gmt":"2008-12-02T02:40:09","slug":"optimization-tradeoffs","status":"publish","type":"post","link":"https:\/\/eriknovales.com\/?p=250","title":{"rendered":"Optimization Tradeoffs"},"content":{"rendered":"<p>This <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx\" target=\"_blank\" rel=\"noopener noreferrer\">recent post by Raymond Chen<\/a> highlights some interesting memory optimization scenarios, and the wide-ranging impact of size optimizations. A quick summary:<\/p>\n<ul>\n<li>Changing a structure definition such that a bunch of Win32 BOOLs use one bit each saves memory in the struct, because BOOL is typedef\u00e2\u20ac\u2122d as an INT.<\/li>\n<li>Accessing the bitfield data members requires additional work (a couple of shifts, in the example). This chews up a little time, and some additional memory for the expanded code. The break-even point for overall reduced memory usage depends on the number of struct instances and the number of locations in the code that access the data.<\/li>\n<li>Packing data members in this fashion also prevents you from setting a data breakpoint on a particular packed flag or value.<\/li>\n<li>The atomic read\/write operations work on words, making it more cumbersome to manipulate the packed values safely in a multithreaded environment.<\/li>\n<\/ul>\n<p>Changing data members to bitfields has other effects, as well:<\/p>\n<ul>\n<li>When making this change, you might do a quick grep on your code (as part of your cost-benefit analysis) to see where the data member is touched. \u00e2\u20ac\u0153Ah ha,\u00e2\u20ac\u009d you say, \u00e2\u20ac\u0153it\u00e2\u20ac\u2122s only touched in one or two places! This change is a no-brainer!\u00e2\u20ac\u009d Of course, if those one or two places are part of inlined functions, the impact of the higher instruction count might be much larger than you think. It\u00e2\u20ac\u2122s important to dig a little deeper than a quick grep when making these sorts of changes, to make sure you aren\u00e2\u20ac\u2122t psyching yourself out. (And, of course, being able to provide concrete before-and-after measurements is also of paramount importance.)<\/li>\n<li>Depending on your <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms253935(VS.80).aspx\" target=\"_blank\" rel=\"noopener noreferrer\">struct packing size<\/a>, you might not see any benefit to bitfield optimization unless you reduce the struct\u00e2\u20ac\u2122s size below the next lower multiple of the packing size.<\/li>\n<li>One potential <em>positive<\/em> effect is that reducing the size of your structs may help with cache utilization \u00e2\u20ac\u201c if you can cram more data into the cache, the added cost of accessing the packed data may be offset.<\/li>\n<\/ul>\n<p>The take-away from this exercise is that it\u00e2\u20ac\u2122s important to consider <em>many<\/em> different factors and effects when optimizing. Most of the real-world cases where I made these optimizations were situations where the struct in question had hundreds, or thousands, of instances, and the tradeoff was definitely a win, but it\u00e2\u20ac\u2122s still worth taking a moment to think about all of the consequences of such a change.<\/p>\n<p>The comments on the post are amusing, running the gamut from \u00e2\u20ac\u0153completely missing the point\u00e2\u20ac\u009d (those who say you should <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9146764\" target=\"_blank\" rel=\"noopener noreferrer\">always<\/a>\/<a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9145821\" target=\"_blank\" rel=\"noopener noreferrer\">never<\/a> use bitfields \u00e2\u20ac\u201c there are <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9145266\" target=\"_blank\" rel=\"noopener noreferrer\">many<\/a> of these <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9145333\" target=\"_blank\" rel=\"noopener noreferrer\">comments<\/a>), to those bringing up <em>even more<\/em> valid considerations (such as how <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9157501\" target=\"_blank\" rel=\"noopener noreferrer\">bitfield layout is implementation-dependent behavior<\/a>, and how <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9152034\" target=\"_blank\" rel=\"noopener noreferrer\">trying to map bitfields to hardware structures<\/a> is a potential endianness minefield). There\u00e2\u20ac\u2122s also <a href=\"http:\/\/blogs.msdn.com\/oldnewthing\/archive\/2008\/11\/26\/9143050.aspx#9146306\" target=\"_blank\" rel=\"noopener noreferrer\">one rather insightful observation<\/a> that made me laugh:<\/p>\n<blockquote>\n<p>I must say: assembly language has no code of honor. Anything goes so long as it works.<\/p>\n<\/blockquote>\n<p>So true.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This recent post by Raymond Chen highlights some interesting memory optimization scenarios, and the wide-ranging impact of size optimizations. A quick summary: Changing a structure definition such that a bunch of Win32 BOOLs use one bit each saves memory in the struct, because BOOL is typedef\u00e2\u20ac\u2122d as an INT. Accessing the bitfield data members requires [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[7],"tags":[],"class_list":["post-250","post","type-post","status-publish","format-standard","hentry","category-development"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/eriknovales.com\/index.php?rest_route=\/wp\/v2\/posts\/250","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eriknovales.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eriknovales.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eriknovales.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eriknovales.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=250"}],"version-history":[{"count":0,"href":"https:\/\/eriknovales.com\/index.php?rest_route=\/wp\/v2\/posts\/250\/revisions"}],"wp:attachment":[{"href":"https:\/\/eriknovales.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=250"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eriknovales.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=250"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eriknovales.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=250"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}