speice.io/assets/js/d185f613.50112228.js

1 line
9.1 KiB
JavaScript
Raw Permalink Normal View History

"use strict";(self.webpackChunkspeice_io=self.webpackChunkspeice_io||[]).push([["5407"],{83561:function(e,t,n){n.r(t),n.d(t,{assets:function(){return l},contentTitle:function(){return r},default:function(){return d},frontMatter:function(){return s},metadata:function(){return o},toc:function(){return c}});var o=n(19395),a=n(85893),i=n(50065);let s={title:"Allocations in Rust: Compiler optimizations",description:"A lot. The answer is a lot.",date:new Date("2019-02-08T12:00:00.000Z"),last_updated:{date:new Date("2019-02-10T12:00:00.000Z")},tags:[]},r=void 0,l={authorsImageUrls:[]},c=[{value:"The Case of the Disappearing Box",id:"the-case-of-the-disappearing-box",level:2},{value:"Dr. Array or: how I learned to love the optimizer",id:"dr-array-or-how-i-learned-to-love-the-optimizer",level:2}];function h(e){let t={a:"a",code:"code",em:"em",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,i.a)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.p,{children:"Up to this point, we've been discussing memory usage in the Rust language by focusing on simple\nrules that are mostly right for small chunks of code. We've spent time showing how those rules work\nthemselves out in practice, and become familiar with reading the assembly code needed to see each\nmemory type (global, stack, heap) in action."}),"\n",(0,a.jsx)(t.p,{children:"Throughout the series so far, we've put a handicap on the code. In the name of consistent and\nunderstandable results, we've asked the compiler to pretty please leave the training wheels on. Now\nis the time where we throw out all the rules and take off the kid gloves. As it turns out, both the\nRust compiler and the LLVM optimizers are incredibly sophisticated, and we'll step back and let them\ndo their job."}),"\n",(0,a.jsxs)(t.p,{children:["Similar to\n",(0,a.jsx)(t.a,{href:"https://www.youtube.com/watch?v=bSkpMdDe4g4",children:'"What Has My Compiler Done For Me Lately?"'}),", we're\nfocusing on interesting things the Rust language (and LLVM!) can do with memory management. We'll\nstill be looking at assembly code to understand what's going on, but it's important to mention\nagain: ",(0,a.jsxs)(t.strong,{children:["please use automated tools like ",(0,a.jsx)(t.a,{href:"https://crates.io/crates/alloc_counter",children:"alloc-counter"})," to\ndouble-check memory behavior if it's something you care about"]}),". It's far too easy to mis-read\nassembly in large code sections, you should always verify behavior if you care about memory usage."]}),"\n",(0,a.jsxs)(t.p,{children:["The guiding principal as we move forward is this: ",(0,a.jsx)(t.em,{children:"optimizing compilers won't produce worse programs\nthan we started with."})," There won't be any situations where stack allocations get moved to heap\nallocations. There will, however, be an opera of optimization."]}),"\n",(0,a.jsxs)(t.p,{children:[(0,a.jsx)(t.strong,{children:"Update 2019-02-10"}),": When debugging a\n",(0,a.jsx)(t.a,{href:"https://gitlab.com/sio4/code/alloc-counter/issues/1",children:"related issue"}),", it was discovered that the\noriginal code worked because LLVM optimized out the entire function, rather than just the allocation\nsegments. The code has been updated with proper use of\n",(0,a.jsx)(t.a,{href:"https://doc.rust-lang.org/std/ptr/fn.read_volatile.html",children:(0,a.jsx)(t.code,{children:"read_volatile"})}),", and a previous section\non vector capacity has been removed."]}),"\n",(0,a.jsx)(t.h2,{id:"the-case-of-the-disappearing-box",children:"The Case of the Disappearing Box"}),"\n",(0,a.jsxs)(t.p,{children:["Our first optimization comes when LLVM can reason that the lifetime of an object is sufficiently\nshort that heap allocations aren't necessary. In these cases, LLVM will move the allocation to the\nstack instead! The way this interacts with ",(0,a.jsx)(t.code,{children:"#[inline]"})," attributes is a bit opaque, but the important\npart is that LLVM can sometimes do better than the baseline Rust language:"]}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-rust",children:'use std::alloc::{G