{"id":17503,"date":"2020-04-22T12:00:13","date_gmt":"2020-04-22T16:00:13","guid":{"rendered":"https:\/\/blog.logrocket.com\/?p=17503"},"modified":"2024-06-04T17:28:58","modified_gmt":"2024-06-04T21:28:58","slug":"how-to-write-crap-rust-code","status":"publish","type":"post","link":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/","title":{"rendered":"How to write CRaP Rust code"},"content":{"rendered":"<!DOCTYPE html>\n<html><p>We Rustaceans like our code to be CRaP. That is, correct, readable, and performant. The exact phrasing varies; some use interchangeable terms, such as concurrent, clear, rigorous, reusable, productive, parallel, etc. \u2014 you get the idea. No matter what you call it, the principle is crucial to building fast, efficient Rust code, and it can help boost your productivity to boot.<\/p><img loading=\"lazy\" decoding=\"async\" width=\"730\" height=\"487\" src=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png\" class=\"attachment-full size-full wp-post-image\" alt=\"How to Write CRaP Rust Code\" srcset=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png 730w, https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code-300x200.png 300w\" sizes=\"auto, (max-width: 730px) 100vw, 730px\">\n<p><iframe loading=\"lazy\" src=\"https:\/\/open.spotify.com\/embed\/episode\/3ezDGcqiNw7ZTT5MGw1M49\" width=\"100%\" height=\"232\" frameborder=\"0\" allowtransparency=\"true\" allow=\"encrypted-media\"><\/iframe><\/p>\n<p>In this tutorial, we\u2019ll outline a sequence of steps to help you arrive at CRaP code for your next Rust project.<\/p>\n<h2 id=\"whywritecrapcode\">Why write CRaP Rust code?<\/h2>\n<p>In the past year, the Rust compiler has <a href=\"https:\/\/perf.rust-lang.org\/index.html?start=2019-11-10&amp;end=2020-03-21&amp;absolute=true&amp;stat=instructions%3Au\" target=\"_blank\" rel=\"noopener noreferrer\">sped up considerably<\/a> and analysis passes have become more powerful. Yet developers still complain about long compile times, and rightfully so. Long compile times extend the turnaround time and thus hinder productivity.<\/p>\n<p>Code is more often read than written, so it pays to invest in readability. You\u2019ll work a little harder while writing it, but you\u2019ll thank yourself later. Plus, code often needs to be changed, so coding in a way that leaves room for future modifications pays back with interest.<\/p>\n<p>Finally, you always want your code to be safe and sound. When working in Rust, this takes on another meaning: you want as little <code>unsafe<\/code> as possible, and none of it should be unsound, otherwise programs will fare no better than those of our peers using C\/C++.<\/p>\n<p>Of course, you also want your code to run reasonably fast and within resource constraints. For many, bringing those requirements together is their main motivation for using Rust in the first place.<\/p>\n<h2 id=\"firstmakeitwork\">Make it work<\/h2>\n<p>While you\u2019re writing your code, pay attention to the naming of your variables and <a href=\"https:\/\/blog.guillaume-gomez.fr\/articles\/2020-03-12+Guide+on+how+to+write+documentation+for+a+Rust+crate\" target=\"_blank\" rel=\"noopener noreferrer\">document why you\u2019re doing everything<\/a>.&nbsp;Commenting your public interface at an early stage, preferably with doc tests, is also advisable to ensure that your interface is actually usable.<\/p>\n<p>Don\u2019t make things generic until you have at least two use cases that need it. Your compile times will be your reward, and you\u2019ll find that it\u2019s still easy to change afterward.<\/p>\n<p>For example, I recently needed to convert a slice of <code>&amp;[i32]<\/code>s to a <code>Vec&lt;f64&gt;<\/code>.<\/p>\n<pre>\/\/\/ I could have done this, but didn't:\nfn to_f64s&lt;I: Into&lt;f64&gt;&gt;(is: &amp;[I]) -&gt; Vec&lt;f64&gt; { .. }\n\n\/\/ instead I did this:\nfn to_f64s(is: &amp;[i32]) -&gt; Vec&lt;f64&gt; { .. }\n<\/pre>\n<p>Sure, I may need to extend this in the future, but for now, it\u2019s totally clear what the types are, I don\u2019t incur any compile-time for type inference, my IDE will insert the correct types for me without problems, and extending the method to work with other types is still simple, so I lost nothing.<\/p>\n<p>In the same vein, avoid introducing concurrency at this stage unless the design won\u2019t work without it. In most cases, Rust makes this painless enough to do later, and adding it before you know the code is correct will make debugging much harder if it isn\u2019t.<\/p>\n<p>The same applies to <code>unsafe<\/code> \u2014 avoid it unless it would be impossible to implement some function without it. In a way, unsafe code is even worse than concurrent code; it may work for a long time before failing, or it may work on most machine\/operating system\/compiler version combinations. And despite tools like <a href=\"https:\/\/github.com\/rust-lang\/miri\/\" target=\"_blank\" rel=\"noopener noreferrer\">miri<\/a>, it is exceedingly difficult to track down undefined behavior.<\/p>\n<p>Declare your data so that it will be easy to work with. Good data design leads to straightforward code. Avoid fancy algorithms at this stage unless you are confident they\u2019ll improve performance by an order of magnitude and you cannot easily swap them in later (in the latter case, add a <code>\/\/ TODO<\/code> note).<\/p>\n<p>This is beneficial because:<\/p>\n<ul>\n<li>Simple, plain code leaves little room for bugs to hide<\/li>\n<li>It helps you establish a reasonable baseline to test against, provided you did nothing exceptionally suboptimal (I once found an <em>O(n\u2074)<\/em> set union written by a colleague)<\/li>\n<li>It makes it easy to test your optimized versions because you can compare both versions\u2019 output with any input you want<\/li>\n<\/ul>\n<p>Try to avoid needless allocation at this stage, or at least make a <code>\/\/ TODO<\/code> note so you won\u2019t forget to fix it later. Keeping track of the allocations is harder than keeping track on the CPU cycles spent, so it makes sense to monitor it early on. Yes, there are some awesome tools available to help you find where memory is spent, but even those take some time to set up, run, and interpret the results. Reducing allocations can often lead to quick wins.<\/p>\n<pre>\/\/ this `collect here is unnecessary unless `wolverine` has side effects that\n\/\/ may not be reordered with following operations, for example thread starts\nlet intermediate = inputs\n    .iter()\n    .map(|i| wolverine(i))\n    .collect::&lt;Vec&lt;_&gt;&gt;();\nreturn intermediate\n    .iter()\n    .filter_map(|f| deadpool(f))\n    .collect();\n\n\/\/\/ just reduce it to one run:\nreturn inputs\n    .iter()\n    .map(|i| wolverine(i))\n    .filter_map(|f| deadpool(f))\n    .collect();\n<\/pre>\n<p>If you use traits, you should use <a href=\"https:\/\/llogiq.github.io\/2020\/03\/14\/ootb.html\" target=\"_blank\" rel=\"noopener noreferrer\">dynamic dispatch<\/a> at this stage. There\u2019s some overhead, but not too much, and you can change it to static dispatch with monomorphization later when profiling reveals that it makes a difference. This will keep the code lean, compile times short, and instruction caches free for the hottest code.<\/p>\n<pre>\/\/\/ Avoid this for now: This function will be monomorphized\nfn monomorphic&lt;I: std::io::Read&gt;(input: &amp;mut I) -&gt; Config { .. }\n\n\/\/\/ Use a `&amp;dyn` or `&amp;mut dyn` reference instead\nfn dynamic(input: &amp;mut dyn std::io::Read) -&gt; Config { .. }\n<\/pre>\n<p>If you\u2019ve successfully compiled and have some cycles to spare, run <a href=\"https:\/\/rust-lang.github.io\/rust-clippy\/\" target=\"_blank\" rel=\"noopener noreferrer\">Clippy<\/a> and peruse its output. It may show a few false positives, but most lints are in good shape, and the messages will sometimes lead to nice improvements.<\/p>\n<h2 id=\"thenmakeitright\">Make it right<\/h2>\n<p>Now that you have code that works, it\u2019s time to put it to the test. If you can, write doctests for all public methods. <code>#![warn(missing_doc_code_examples)]<\/code> is your friend here.<\/p>\n<p>This is simplified by the fact that we haven\u2019t added any unnecessary abstraction. Don\u2019t change this to make your code \u201ctestable.\u201d If needed, you can have test helper methods that are only compiled with <code>#[cfg(test)]<\/code> so they can be shared among tests.<\/p>\n<p>Larger, more complex usage tests can be put in the <code>examples\/<\/code> directory.<\/p>\n<p>Now is also a good time for a <code>README.md<\/code>, if you haven\u2019t already written one.<\/p>\n<p>Extend your testing toolbox with <a href=\"https:\/\/docs.rs\/quickcheck\" target=\"_blank\" rel=\"noopener noreferrer\">quickcheck<\/a> or <a href=\"https:\/\/altsysrq.github.io\/proptest-book\/intro.html\" target=\"_blank\" rel=\"noopener noreferrer\">proptest<\/a>. These tools enable you to automatically generate random test cases and reduce the test cases once an error is found.<\/p>\n<p>For a more directed, coverage-maximizing approach, the <a href=\"https:\/\/rust-fuzz.github.io\/book\/\" target=\"_blank\" rel=\"noopener noreferrer\">Rust Fuzz Book<\/a> shows how to use <code><a href=\"https:\/\/github.com\/rust-fuzz\/afl.rs\" target=\"_blank\" rel=\"noopener noreferrer\">afl<\/a><\/code> or <code><a href=\"https:\/\/github.com\/rust-fuzz\/cargo-fuzz\" target=\"_blank\" rel=\"noopener noreferrer\">cargo-fuzz<\/a><\/code> to find failing test inputs. This can often uncover problems that quickcheck or proptest fail to see because they only generate random inputs regardless of the code paths taken.<\/p>\n<p>Apart from tests, you can often use the type system to catch classes of possible errors at compile time. For example, if you have a <code>u8<\/code> that should only ever be <code>1<\/code>, <code>2<\/code> or <code>3<\/code>, consider using an <code>enum<\/code> instead. This tactic is often called \u201cmake illegal states unrepresentable,\u201d and Rust\u2019s powerful type system is extraordinarily apt for it.<\/p>\n<p>For an extreme example, my <code><a href=\"https:\/\/docs.rs\/compact-arena\" target=\"_blank\" rel=\"noopener noreferrer\">compact-arena<\/a><\/code> crate uses types and lifetimes to disallow misuse of the indices at compile time.<\/p>\n<p>Finally, give your code a read. Can you find things that stand out? What\u2019s good about the code? What could be improved? While looking over the code, also keep <a href=\"https:\/\/llogiq.github.io\/2017\/06\/01\/perf-pitfalls.html\" target=\"_blank\" rel=\"noopener noreferrer\">performance pitfalls<\/a> in mind.<\/p>\n<p>I personally prefer to work as part of a team best. If you share this trait, make it known. Add a <code>CONTRIBUTING.md<\/code> to your project, invite others to join, and <a href=\"https:\/\/manishearth.github.io\/blog\/2016\/01\/03\/making-your-open-source-project-newcomer-friendly\/\" target=\"_blank\" rel=\"noopener noreferrer\">be welcoming to those who do<\/a>. Keep a list of easy, mentored issues and follow up on them. You can even post them to This Week in Rust\u2019s <a href=\"https:\/\/users.rust-lang.org\/t\/twir-call-for-participation\/4821\" target=\"_blank\" rel=\"noopener noreferrer\">Call for Participation<\/a> list. This often takes a bit of patience upfront but pays back once you\u2019ve attracted loyal and capable co-maintainers to help reduce your workload.<\/p>\n<h2 id=\"finallymakeitfast\">Make it fast<\/h2>\n<p>Now that your program is lean, well-tested, and readable, give it a test run. If it\u2019s fast enough to suit your needs, you\u2019re done. Congratulations! You can skip the rest of this section. Otherwise, read on.<\/p>\n<p>Before you set out to optimize, your first task is to learn what needs optimizing. Humans are famously bad at reasoning about where a program will spend its time.<\/p>\n<p>Learn and work with the tools your system offers. For sampling profilers, the <a href=\"https:\/\/docs.rs\/inferno\" target=\"_blank\" rel=\"noopener noreferrer\">inferno<\/a> docs have very nice directions to get a flamegraph for your code (Kudos to Jon Gjengset). If your application has any sort of concurrency, you may also want to give <a href=\"https:\/\/github.com\/plasma-umass\/coz\" target=\"_blank\" rel=\"noopener noreferrer\">coz<\/a> a try.<\/p>\n<p>If you can run it, <a href=\"https:\/\/valgrind.org\/docs\/manual\/dh-manual.html\" target=\"_blank\" rel=\"noopener noreferrer\">DHAT<\/a> can provide a solid overview of where memory is used. The good thing about excessive memory use is it is often low-hanging fruit for optimization. The bad thing is that you\u2019re unlikely to find them, since you\u2019ve (hopefully) already gotten rid of most of them early on.<\/p>\n<p>Once you understand the hot spots of your code, look for algorithmic improvements first (your <code>TODO<\/code>s might now come in handy). Getting bogged down in the low-level details will be counterproductive if you change the whole thing later. However, be aware that your program will very rarely exhibit asymptotic complexity (in layman\u2019s terms, run on very large inputs), so be aware of that when choosing an algorithm.<\/p>\n<p>If you\u2019ve maxed out your algorithmic options and still need more speed, look into the data layout. Does your <code>HashMap<\/code> have fewer than 50 entries most of the time? Use a <code>Vec&lt;(key, value)&gt;<\/code> instead, especially if you can <code>sort_by_key<\/code> and <code>binary_search_by_key<\/code> it for lookup. If your <code>Vec<\/code>s have mostly one or two elements, perhaps try a <code><a href=\"https:\/\/docs.rs\/smallvec\" target=\"_blank\" rel=\"noopener noreferrer\">SmallVec<\/a><\/code> (or <code><a href=\"https:\/\/docs.rs\/tinyvec\" target=\"_blank\" rel=\"noopener noreferrer\">tinyvec<\/a><\/code> if it gives you the same perf).<\/p>\n<p>At this stage, even the order of the data may make a difference, so if you see certain reads of a struct\u2019s field in your profile, try prepending <code>#[repr(C)]<\/code> to the struct definition and reordering the fields to see if it gains you some performance.<\/p>\n<p>If you\u2019re particularly astute, you will have noticed that we\u2019ve yet to talk about concurrency. This was intentional. It\u2019s often unnecessary to make your program run in parallel, and the wins can be underwhelming, especially if you introduce concurrency without a clear idea of where it would be effective.<\/p>\n<p><a href=\"https:\/\/en.wikipedia.org\/wiki\/Amdahl%27s_law\" target=\"_blank\" rel=\"noopener noreferrer\">Amdahl\u2019s Law<\/a> states that any speedup (<em>s<strong>)<\/strong><\/em> of a part of your code that will take a percentage (<em>p)<\/em> of the total runtime will benefit the total program by the inverse of the sum of <em>1 \u2013 p<\/em> and <em>p\/s<\/em>. So if you speed up a program that takes 30 percent of the runtime by a factor of two, you\u2019ll speed up the whole program by 15 percent.<\/p>\n<p>So now you have hot code that could run on multiple cores. Often that will be loops, so make the outermost parallelizable loop you can find parallel using <a href=\"https:\/\/docs.rs\/rayon\/1.3.0\/rayon\/\" target=\"_blank\" rel=\"noopener noreferrer\">rayon<\/a>. It\u2019s not optimal in all cases, but it offers acceptable overhead for a very easy change to try out if parallel computation really wins.<\/p>\n<p>A word of caution: be wary about the workloads you test. Creating a benchmark that will correctly measure a certain effect on performance is a subtle art. This is outside the scope of this article, but I have wrongly attributed an effect that was, in reality, due to a confounding factor enough times to make me very careful about benchmark design. And that\u2019s no guarantee that I\u2019ll be right with my next benchmark. In any event, the <a href=\"https:\/\/bheisler.github.io\/criterion.rs\/book\/\" target=\"_blank\" rel=\"noopener noreferrer\">Criterion<\/a> benchmark harness can help you follow best practices.<\/p>\n<h2 id=\"knowwhentostop\">Know when to stop<\/h2>\n<p>Optimizing code for performance is often a fun game, but it\u2019s easy to get lost in it. Keep in mind that every optimization comes with increased complexity, loss of readability and maintainability, and an expanded attack surface for bugs, not to mention a strain on your time. So set clear a performance goal and stop once you reach it.<\/p>\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>We Rustaceans like our code to be CRaP. That is, correct, readable, and performant. Learn how investing in the readability of your code upfront can unlock myriad speed, flexibility, and productivity gains.<\/p>\n","protected":false},"author":156415513,"featured_media":17512,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2147999,1],"tags":[2109867,2109784],"class_list":["post-17503","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","category-uncategorized","tag-archive","tag-rust"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.1.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to write CRaP Rust code - LogRocket Blog<\/title>\n<meta name=\"description\" content=\"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.\" \/>\n<meta name=\"robots\" content=\"noindex, follow\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to write CRaP Rust code - LogRocket Blog\" \/>\n<meta property=\"og:description\" content=\"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/\" \/>\n<meta property=\"og:site_name\" content=\"LogRocket Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-04-22T16:00:13+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-04T21:28:58+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png\" \/>\n\t<meta property=\"og:image:width\" content=\"730\" \/>\n\t<meta property=\"og:image:height\" content=\"487\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Andre Bogus\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Andre Bogus\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/\",\"url\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/\",\"name\":\"How to write CRaP Rust code - LogRocket Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.logrocket.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png\",\"datePublished\":\"2020-04-22T16:00:13+00:00\",\"dateModified\":\"2024-06-04T21:28:58+00:00\",\"author\":{\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/042877f0a0b7a33665f692b86bac11e4\"},\"description\":\"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#primaryimage\",\"url\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png\",\"contentUrl\":\"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png\",\"width\":730,\"height\":487,\"caption\":\"How to Write CRaP Rust Code\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.logrocket.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to write CRaP Rust code\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.logrocket.com\/#website\",\"url\":\"https:\/\/blog.logrocket.com\/\",\"name\":\"LogRocket Blog\",\"description\":\"Resources to Help Product Teams Ship Amazing Digital Experiences\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.logrocket.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/042877f0a0b7a33665f692b86bac11e4\",\"name\":\"Andre Bogus\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.logrocket.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/57dccbd97de38c028dcc32d7e9eb6efe91102d83e9bee6cefb3eb088a25d2637?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/57dccbd97de38c028dcc32d7e9eb6efe91102d83e9bee6cefb3eb088a25d2637?s=96&d=mm&r=g\",\"caption\":\"Andre Bogus\"},\"description\":\"Andre \\\"llogiq\\\" Bogus is a Rust contributor and Clippy maintainer. A musician-turned-programmer, he has worked in many fields, from voice acting and teaching, to programming and managing software projects. He enjoys learning new things and telling others about them.\",\"url\":\"https:\/\/blog.logrocket.com\/author\/andrebogus\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to write CRaP Rust code - LogRocket Blog","description":"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.","robots":{"index":"noindex","follow":"follow"},"og_locale":"en_US","og_type":"article","og_title":"How to write CRaP Rust code - LogRocket Blog","og_description":"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.","og_url":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/","og_site_name":"LogRocket Blog","article_published_time":"2020-04-22T16:00:13+00:00","article_modified_time":"2024-06-04T21:28:58+00:00","og_image":[{"width":730,"height":487,"url":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png","type":"image\/png"}],"author":"Andre Bogus","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Andre Bogus","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/","url":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/","name":"How to write CRaP Rust code - LogRocket Blog","isPartOf":{"@id":"https:\/\/blog.logrocket.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#primaryimage"},"image":{"@id":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#primaryimage"},"thumbnailUrl":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png","datePublished":"2020-04-22T16:00:13+00:00","dateModified":"2024-06-04T21:28:58+00:00","author":{"@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/042877f0a0b7a33665f692b86bac11e4"},"description":"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.","breadcrumb":{"@id":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#primaryimage","url":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png","contentUrl":"https:\/\/blog.logrocket.com\/wp-content\/uploads\/2020\/04\/how-to-write-crap-rust-code.png","width":730,"height":487,"caption":"How to Write CRaP Rust Code"},{"@type":"BreadcrumbList","@id":"https:\/\/blog.logrocket.com\/how-to-write-crap-rust-code\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.logrocket.com\/"},{"@type":"ListItem","position":2,"name":"How to write CRaP Rust code"}]},{"@type":"WebSite","@id":"https:\/\/blog.logrocket.com\/#website","url":"https:\/\/blog.logrocket.com\/","name":"LogRocket Blog","description":"Resources to Help Product Teams Ship Amazing Digital Experiences","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.logrocket.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/042877f0a0b7a33665f692b86bac11e4","name":"Andre Bogus","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.logrocket.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/57dccbd97de38c028dcc32d7e9eb6efe91102d83e9bee6cefb3eb088a25d2637?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/57dccbd97de38c028dcc32d7e9eb6efe91102d83e9bee6cefb3eb088a25d2637?s=96&d=mm&r=g","caption":"Andre Bogus"},"description":"Andre \"llogiq\" Bogus is a Rust contributor and Clippy maintainer. A musician-turned-programmer, he has worked in many fields, from voice acting and teaching, to programming and managing software projects. He enjoys learning new things and telling others about them.","url":"https:\/\/blog.logrocket.com\/author\/andrebogus\/"}]}},"yoast_description":"Learn how to reduce compile times, improve readability, and boost performance by writing CRaP \u2014 that is, correct, readable, and performant \u2014 Rust code.","_links":{"self":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/17503","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/users\/156415513"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/comments?post=17503"}],"version-history":[{"count":12,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/17503\/revisions"}],"predecessor-version":[{"id":66020,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/posts\/17503\/revisions\/66020"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/media\/17512"}],"wp:attachment":[{"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/media?parent=17503"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/categories?post=17503"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.logrocket.com\/wp-json\/wp\/v2\/tags?post=17503"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}