{"id":1028,"date":"2020-06-22T00:00:00","date_gmt":"2020-06-22T00:00:00","guid":{"rendered":"https:\/\/en.pingcap.com\/blog\/rust-huge-compilation-units\/"},"modified":"2024-06-03T06:11:43","modified_gmt":"2024-06-03T13:11:43","slug":"rust-huge-compilation-units","status":"publish","type":"post","link":"https:\/\/www.pingcap.com\/ko\/blog\/rust-huge-compilation-units\/","title":{"rendered":"Rust&#8217;s Huge Compilation Units"},"content":{"rendered":"<p>The Rust programming language compiles fast software slowly.<\/p>\n\n\n\n<p>In this series we explore Rust&#8217;s compile times within the context of TiKV, the key-value store behind the <a href=\"\/ko\/tidb\/\">\ud2f0DB<\/a> database.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Rust_Compile-time_Adventures_with_TiKV_Episode_3\"><\/span>Rust Compile-time Adventures with TiKV: Episode 3<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Lately we&#8217;re exploring how Rust&#8217;s designs discourage fast compilation. In <a href=\"https:\/\/www.pingcap.com\/ko\/blog\/generics-and-compile-time-in-rust\/\">Generics and Compile-Time in Rust<\/a> we discussed the difficult compile-time tradeoffs required to implement generics.<\/p>\n\n\n\n<p>This time we&#8217;re going to talk about compilation units.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Compilation_units\"><\/span>Compilation units<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A <em>compilation unit<\/em> is the basic unit of work that a language&#8217;s compiler operates on. In C and C++ the compilation unit is a source file. In Java it is a source file. In Rust the compilation unit is a <em>crate<\/em>, which is composed of many files.<\/p>\n\n\n\n<p>The size of compilation units incur a number of tradeoffs. Larger compilation units take longer to analyze, translate, and optimize than smaller compilation units. And in general, when a change is made to a single compilation unit, the whole compilation unit must be recompiled.<\/p>\n\n\n\n<p>More, smaller crates improve the <em>perception<\/em> of compile time, if not the total compile time, because a single change may force less of the project to be recompiled. This benefits the &#8220;partial recompilation&#8221; use cases. A project with more crates though may do more work on a full recompile due to a variety of factors, which I will summarize at the end of this post.<\/p>\n\n\n\n<p>Rust crates don&#8217;t have to be large, but there are a variety of factors that encourage them to be. The first is simply the relative complexity of adding new crates to a Rust project vs. adding a new module to a crate. New Rust projects tend to turn into monoliths unless given special attention to abstraction boundaries.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Dependency_graphs_and_unstirring_spaghetti\"><\/span>Dependency graphs and unstirring spaghetti<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Within a crate, there are no fundamental restrictions on module interdependencies, though there are language features that allow some amount of information-hiding within a crate. The big advantage and risk of having modules coexist in the same crate is that they can be <em>mutually dependent<\/em>, two modules both depending on names exported from the other. Here&#8217;s an example similar to many encountered in TiKV, in which <code>engine<\/code> imports (&#8220;uses&#8221;) <code>network::Message<\/code> \uadf8\ub9ac\uace0 <code>network<\/code> imports <code>storage::Engine<\/code>.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mod storage {\n  use network::Message;\n\n  pub struct Engine;\n\n  impl Engine {\n    pub fn handle_message(&amp;self, msg: Message) -&gt; Result&lt;()&gt; { ... }\n  }\n}\n\nmod network {\n  use storage::Engine;\n\n  pub enum Message { ... }\n\n  struct Server {\n    engine: Engine,\n  }\n\n  impl Server {\n    fn handle_message(&amp;self, msg: Message) -&gt; Result&lt;()&gt; {\n      ...\n\n      self.engine.handle_message(msg)?;\n\n      ...\n    }\n  }\n}\n<\/code><\/pre>\n\n\n\n<p>Modules with mutual dependencies are useful for reducing cognitive complexity simply because they break up code into smaller units. As an abstraction boundary though they are deceptive: they are not truly independent, and cannot be trivially reduced further into separate crates.<\/p>\n\n\n\n<p>And that is because <em>dependencies between crates must form a directed acyclic graph (a DAG)<\/em>; they do not support mutual dependencies.<\/p>\n\n\n\n<p>Rust crates being daggish are mostly due to fundamental reasons of type checking and architectural complexity. If crates allowed for mutual dependencies then they would no longer be self-contained compilation units.<\/p>\n\n\n\n<p>In preparation for this blog I asked a few people if they could recall the reasons why Rust crates must form a DAG, and Graydon gave a typically thorough and authoritative answer:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: Prohibits mutual recursion between definitions across crates, allowing both an obvious deterministic bottom-up build schedule without needing to do some fixpoint iteration or separate declarations from definitions<br>and enables phases that need to traverse a complete definition, like typechecking, to happen crate-at-a-time (enabling <em>some<\/em> degree of incrementality \/ parallelism).<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: (once you know you&#8217;ve seen all the cycles in a recursive type you can check it for finiteness and then stop expanding it at any boxed variants &#8212; even if they cross crates &#8212; and put a lazy \/ placeholder definition in those boxed edges; but you need to know those variants don&#8217;t cycle back!)<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: (I do not know if rustc does anything like this anymore)<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: cyclicality concerns are even worse with higher order modules, which I was spending quite a lot of time studying when working on the early design. most systems I&#8217;ve seen require you to paint some kind of a boundary around a group of mutually-recursive definitions to be able to resolve them, so the crate seemed like a natural unit for that.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: then there is also the issue of versioning, which I think was pretty heavy in my mind (especially after the experience with monotone and git): a lot of versioning questions don&#8217;t really make sense without acyclic-by-construction references. Like if A 1.0 depends on B 1.0 which depends on A 2.0 you, again, need to do something weird and fixpointy and potentially quite arbitrary and hard to explain to anyone in order to resolve those dependencies.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: also recall we wanted to be able to do hot code loading early on, which means that much like version-resolving, compiling or linking, your really in a much simpler place if there&#8217;s a natural topological order to which things you have to load or unload. you can decide whether a crate is still live just by reference-counting, no need to go figure out cyclical dependencies and break them in some random order, etc.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: I&#8217;m not sure which if any of these was the dominant concern. If I had to guess I&#8217;d say avoiding problems with separate compilation of recursive definitions and managing code versioning. recall the language in the manual \/ the rationale for crates: &#8220;units of compilation and versioning&#8221;. Those were the consideration for their existence as separate from modules. Modules get to be recursive. Crates, no. Because of things to do with &#8220;compilation and versioning&#8221;.<\/p>\n<\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>graydon: I cannot make a simple argument about this because I&#8217;m still not smart enough about module systems \u2014 the full thing is laid out in <a href=\"https:\/\/people.mpi-sws.org\/~dreyer\/thesis\/main.pdf\">dreyer&#8217;s thesis<\/a> and discussed in shorter <a href=\"http:\/\/macqueenfest.cs.uchicago.edu\/slides\/dreyer.pdf\">slide-deck form here<\/a> \u2014 but suffice to say that recursive modules make it possible to see the &#8220;same&#8221; opaque type through two paths that should probably be considered equal but aren&#8217;t easily determined to be so, I think in part due to the mix of opacity that modules provide and the fact that you have to partly look through that opacity to resolve recursion. so anyway I decided this was probably getting into &#8220;research&#8221; and I should just avoid the problem space, go with acyclic modules.<\/p>\n<\/blockquote>\n\n\n\n<p>Although driven by fundamental constraints, the hard daggishness of crates is useful for a number of reasons: it enforces careful abstractions, defines units of <em>parallel<\/em> compilation, defines basically sensible codegen units, and dramatically reduces language and compiler complexity (even as the compiler likely moves toward whole-program, demand-driven, compilation in the future).<\/p>\n\n\n\n<p>Note the emphasis on <em>parallelism<\/em>. The crate DAG is the simplest source of compile-time parallelism Rust has access to. Cargo today will use the DAG to automatically divide work into parallel compilation jobs.<\/p>\n\n\n\n<p>So it&#8217;s quite desirable for Rust code to be broken into crates that form a <em>wide<\/em> DAG.<\/p>\n\n\n\n<p>In my experience though projects tend to start in a single crate, without great attention to their internal dependency graph, and once compilation time becomes an issue, they have already created a spaghetti dependency graph that is difficult to refactor into smaller crates.<\/p>\n\n\n\n<p>It happened to Servo, and it has also been my experience on TiKV, where I have made multiple aborted attempts to extract various modules from the main program, in long sequences of commits that untangle internal dependencies. I suspect that avoiding problematic monoliths is something that Rust devs learn with experience, but it is a repeating phenomenon in large Rust projects.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div style=\"--ub-icon-rotation:rotate(0deg);--ub-icon-size:40px;--ub-icon-justification:center;--ub-icon-border-top:  undefined;--ub-icon-border-right:  undefined;--ub-icon-border-bottom:  undefined;--ub-icon-border-left:  undefined\" class=\"wp-block-ub-icon\" id=\"ub-icon-\"><div class=\"ub_icon\"><div class=\"ub_icon_wrapper\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewbox=\"0 0 24 24\" aria-hidden=\"true\"><path d=\"M6.6 6L5.4 7l4.5 5-4.5 5 1.1 1 5.5-6-5.4-6zm6 0l-1.1 1 4.5 5-4.5 5 1.1 1 5.5-6-5.5-6z\"><\/path><\/svg><\/div><\/div><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Trait_coherence_and_the_orphan_rule\"><\/span>Trait coherence and the orphan rule<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>Rust&#8217;s trait system further makes it challenging to use crates as abstraction boundaries because of a thing call the <em>orphan rule<\/em>.<\/p>\n\n\n\n<p>Traits are the most common tool for creating abstractions in Rust. They are powerful, but like much of Rust&#8217;s power, it comes with a tradeoff.<\/p>\n\n\n\n<p>The <a href=\"https:\/\/smallcultfollowing.com\/babysteps\/blog\/2015\/01\/14\/little-orphan-impls\/\">orphan rule<\/a> helps maintain <a href=\"https:\/\/doc.rust-lang.org\/reference\/items\/implementations.html#trait-implementation-coherence\">trait coherence<\/a>, and exists to ensure that the Rust compiler never encounters two implementations of a trait for the same type. If it were to encounter two such implementations then it would need to resolve the conflict while ensuring that the result is sound.<\/p>\n\n\n\n<p>What the orphan rule says, essentially, is that for any <code>impl<\/code>, either the <em>trait<\/em> must be defined in the current crate, or the <em>type<\/em> must be defined in the current crate.<\/p>\n\n\n\n<p>This can create a tight coupling between abstractions in Rust, discouraging decomposition into crates \u2014 sometimes the amount of ceremony, boilerplate and creativity it takes to obey Rust&#8217;s coherence rules, while also maintaining principled abstraction boundaries, doesn&#8217;t feel worth the effort, so it doesn&#8217;t happen.<\/p>\n\n\n\n<p>This results in large crates which increase partial rebuild time.<\/p>\n\n\n\n<p>This subject deserves more examples and a stronger argument, but I haven&#8217;t the enthusiasm for it now.<\/p>\n\n\n\n<p>Haskell&#8217;s type classes, on which Rust&#8217;s traits are based, do not have an orphan rule. I do not know the extent of problems this causes in practice for Haskell. At the time of Rust&#8217;s design, it was thought to be problematic enough to correct.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Internal_parallelism\"><\/span>Internal parallelism<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>As crates are the main unit of parallelism in compilation pipeline, in theory it is desirable to have a wide crate DAG with roughly equally-complex crates, such that the compiler can be using all the machines cores all the time. In practice though there are almost always bottlenecks where there is only one compiler instance running, working on a single crate.<\/p>\n\n\n\n<p>So in addition to <code>cargo<\/code>s parallel crate compilation, <code>rustc<\/code> itself is parallel over a single crate. It wasn&#8217;t designed to be parallel though, so its parallelism is limited and hard-won.<\/p>\n\n\n\n<p>Today the only real internal parallelism in <code>rustc<\/code> is the use of <a href=\"https:\/\/doc.rust-lang.org\/rustc\/codegen-options\/index.html\"><em>codegen units<\/em><\/a>, by which <code>rustc<\/code> automatically divides a crate into multiple LLVM modules during translation. By doing this it can perform code generation in parallel. Like a crate, a Rust codegen-unit is also a compilation unit, but it is an LLVM compilation unit.<\/p>\n\n\n\n<p>Combined with <a href=\"https:\/\/rust-lang.github.io\/rustc-guide\/queries\/incremental-compilation.html\"><em>incremental compilation<\/em><\/a>, it can avoid re-translating codegen units which have not changed from run to run, decreasing partial rebuild time. Unfortunately, the impact of codegen units and incremental compilation on both compile-time and run-time performance is hard to predict: improving rebuild time depends on <code>rustc<\/code> successfully dividing a crate into independent units that are unlikely to force each other to recompile when changed, and it&#8217;s not obvious how humans should write their code to help <code>rustc<\/code> in this task; and arbitrarily dividing up a crate into codegen units creates arbitrary barriers to inlining, causing unexpected de-optimizations.<\/p>\n\n\n\n<p>The rest of the compiler&#8217;s work is completely serial, though soon it should <a href=\"https:\/\/internals.rust-lang.org\/t\/help-test-parallel-rustc\/11503\/14\">perform some analysis in parallel<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Large vs. small crates<\/h3>\n\n\n\n<p>The compilation properties affected by compilation unit size is large, and I&#8217;ve given up trying to explain them all coherently. Here&#8217;s a list of some of them.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><p>Compilation unit parallelism \u2014 as discussed, parallelising compilation units is trivial.<\/p><\/li>\n\n\n\n<li><p>Inlining and optimization \u2014 inlining happens at the compilation unit level, and inlining is the key to unlocking optimization, so larger compilation units are better optimized. This story is complicated though by link-time-optimization (LTO).<\/p><\/li>\n\n\n\n<li><p>Optimization complexity \u2014 optimization tends to have superlinear complexity in code size, so bigger compilation units increase compilation time non-linearly.<\/p><\/li>\n\n\n\n<li><p>Downstream monomorphization \u2014 generics are only translated once they are instantiated, so even if all crates are perfectly equally sized for parallel compilation, their generic types will not be translated until later stages in the crate graph. This can result in the &#8220;final&#8221; crate having a disproportionate amount of translation compared to the others.<\/p><\/li>\n\n\n\n<li><p>Generic duplication \u2014 generics are translated in the crate which instantiates them, so more crates that use the same generics means more translation time.<\/p><\/li>\n\n\n\n<li><p>Link-time optimization (LTO) \u2014 release builds tend to have a final &#8220;link-time optimization&#8221; step that performs optimizations across multiple code units, and it is extremely expensive.<\/p><\/li>\n\n\n\n<li><p>Saving and restoring metadata \u2014 Rust needs to save and load metadata about each crate and each dependency, each time it is run, so more crates means more redundant loading.<\/p><\/li>\n\n\n\n<li><p>Parallel &#8220;codegen units&#8221; \u2014 <code>rustc<\/code> can automatically split its LLVM IR into multiple compilation units, called &#8220;codegen units&#8221;. The degree to which it is effective at this depends a lot on how a crate&#8217;s internal dependencies are organized and the compiler&#8217;s ability to understand them. This can result in faster partial recompilation, at the expense of optimization, since inlining opportunities are lost.<\/p><\/li>\n\n\n\n<li><p>Compiler-internal parallelism \u2014 Parts of <code>rustc<\/code> itself are parallel. That internal parallelism has its own unpredictable bottlenecks and unpredictable interactions with external build-system parallelism.<\/p><\/li>\n<\/ul>\n\n\n\n<p>Unfortunately, because of all these variables, it&#8217;s not at all obvious for any given project what the impact of refactoring into smaller crates is going to be. Anticipated wins due to increased parallelism are often erased by other factors such as downstream monomorphization, generic duplication, and LTO.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"In_the_next_episode_of_Rust_Compile-time_Adventures_with_TiKV\"><\/span>In the next episode of Rust Compile-time Adventures with TiKV<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>In the next episode of this series we&#8217;ll wrap up this exploration of the reason&#8217;s for Rust&#8217;s slow compile times with <a href=\"https:\/\/www.pingcap.com\/ko\/blog\/reasons-rust-compiles-slowly\/\">a few smaller slow-compilation tidbits<\/a>.<\/p>\n\n\n\n<p>Then maybe we&#8217;ll move on to something new, like techniques for speeding up Rust builds.<\/p>\n\n\n\n<p>Stay Rusty, friends.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Thanks\"><\/span>Thanks<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p>A number of people helped with this blog series. Thanks especially to Graydon Hoare for the feedback, and Calvin Weng for proofreading and editing.<\/p>","protected":false},"excerpt":{"rendered":"<p>The third episode of the Rust Compile Time series discusses why Rust&#8217;s compilation units are so big and how that affects compile times.<\/p>","protected":false},"author":43,"featured_media":446,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"ub_ctt_via":"","footnotes":""},"categories":[6],"tags":[23,22],"class_list":["post-1028","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","tag-rust","tag-tikv"],"acf":[],"featured_image_src":"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg","author_info":{"display_name":"Brian Anderson","author_link":"https:\/\/www.pingcap.com\/ko\/blog\/author\/brian-anderson\/"},"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.9 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Rust&#039;s Huge Compilation Units | TiDB<\/title>\n<meta name=\"description\" content=\"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post &quot;Rust&#039;s Huge Compilation Units&quot; here.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.pingcap.com\/ko\/blog\/rust-huge-compilation-units\/\" \/>\n<meta property=\"og:locale\" content=\"ko_KR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Rust&#039;s Huge Compilation Units | TiDB\" \/>\n<meta property=\"og:description\" content=\"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post &quot;Rust&#039;s Huge Compilation Units&quot; here.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.pingcap.com\/ko\/blog\/rust-huge-compilation-units\/\" \/>\n<meta property=\"og:site_name\" content=\"TiDB\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/facebook.com\/pingcap2015\" \/>\n<meta property=\"article:published_time\" content=\"2020-06-22T00:00:00+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-03T13:11:43+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2000\" \/>\n\t<meta property=\"og:image:height\" content=\"667\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Brian Anderson\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@PingCAP\" \/>\n<meta name=\"twitter:site\" content=\"@PingCAP\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Brian Anderson\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10\ubd84\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/\"},\"author\":{\"name\":\"Brian Anderson\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/6883a92f64d13c80ee57193b8c291a1c\"},\"headline\":\"Rust&#8217;s Huge Compilation Units\",\"datePublished\":\"2020-06-22T00:00:00+00:00\",\"dateModified\":\"2024-06-03T13:11:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/\"},\"wordCount\":2181,\"publisher\":{\"@id\":\"https:\/\/www.pingcap.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg\",\"keywords\":[\"Rust\",\"TiKV\"],\"articleSection\":[\"Engineering\"],\"inLanguage\":\"ko-KR\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/\",\"url\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/\",\"name\":\"Rust's Huge Compilation Units | TiDB\",\"isPartOf\":{\"@id\":\"https:\/\/www.pingcap.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg\",\"datePublished\":\"2020-06-22T00:00:00+00:00\",\"dateModified\":\"2024-06-03T13:11:43+00:00\",\"description\":\"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \\\"Rust's Huge Compilation Units\\\" here.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#breadcrumb\"},\"inLanguage\":\"ko-KR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage\",\"url\":\"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg\",\"width\":2000,\"height\":667},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.pingcap.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Rust&#8217;s Huge Compilation Units\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.pingcap.com\/#website\",\"url\":\"https:\/\/www.pingcap.com\/\",\"name\":\"TiDB\",\"description\":\"TiDB | SQL at Scale\",\"publisher\":{\"@id\":\"https:\/\/www.pingcap.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.pingcap.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"ko-KR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.pingcap.com\/#organization\",\"name\":\"PingCAP\",\"url\":\"https:\/\/www.pingcap.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png\",\"width\":811,\"height\":232,\"caption\":\"PingCAP\"},\"image\":{\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/facebook.com\/pingcap2015\",\"https:\/\/x.com\/PingCAP\",\"https:\/\/linkedin.com\/company\/pingcap\",\"https:\/\/youtube.com\/channel\/UCuq4puT32DzHKT5rU1IZpIA\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/6883a92f64d13c80ee57193b8c291a1c\",\"name\":\"Brian Anderson\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"ko-KR\",\"@id\":\"https:\/\/www.pingcap.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg\",\"contentUrl\":\"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg\",\"caption\":\"Brian Anderson\"},\"description\":\"Senior Database Engineer\",\"url\":\"https:\/\/www.pingcap.com\/ko\/blog\/author\/brian-anderson\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Rust's Huge Compilation Units | TiDB","description":"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \"Rust's Huge Compilation Units\" here.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.pingcap.com\/ko\/blog\/rust-huge-compilation-units\/","og_locale":"ko_KR","og_type":"article","og_title":"Rust's Huge Compilation Units | TiDB","og_description":"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \"Rust's Huge Compilation Units\" here.","og_url":"https:\/\/www.pingcap.com\/ko\/blog\/rust-huge-compilation-units\/","og_site_name":"TiDB","article_publisher":"https:\/\/facebook.com\/pingcap2015","article_published_time":"2020-06-22T00:00:00+00:00","article_modified_time":"2024-06-03T13:11:43+00:00","og_image":[{"width":2000,"height":667,"url":"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg","type":"image\/jpeg"}],"author":"Brian Anderson","twitter_card":"summary_large_image","twitter_creator":"@PingCAP","twitter_site":"@PingCAP","twitter_misc":{"Written by":"Brian Anderson","Est. reading time":"10\ubd84"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#article","isPartOf":{"@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/"},"author":{"name":"Brian Anderson","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/6883a92f64d13c80ee57193b8c291a1c"},"headline":"Rust&#8217;s Huge Compilation Units","datePublished":"2020-06-22T00:00:00+00:00","dateModified":"2024-06-03T13:11:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/"},"wordCount":2181,"publisher":{"@id":"https:\/\/www.pingcap.com\/#organization"},"image":{"@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage"},"thumbnailUrl":"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg","keywords":["Rust","TiKV"],"articleSection":["Engineering"],"inLanguage":"ko-KR"},{"@type":"WebPage","@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/","url":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/","name":"Rust's Huge Compilation Units | TiDB","isPartOf":{"@id":"https:\/\/www.pingcap.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage"},"image":{"@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage"},"thumbnailUrl":"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg","datePublished":"2020-06-22T00:00:00+00:00","dateModified":"2024-06-03T13:11:43+00:00","description":"Learn about the benefits of TiDB and the TiDB Cloud solutions from PingCAP. Read our latest post \"Rust's Huge Compilation Units\" here.","breadcrumb":{"@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#breadcrumb"},"inLanguage":"ko-KR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/"]}]},{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#primaryimage","url":"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg","contentUrl":"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg","width":2000,"height":667},{"@type":"BreadcrumbList","@id":"https:\/\/www.pingcap.com\/blog\/rust-huge-compilation-units\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.pingcap.com\/"},{"@type":"ListItem","position":2,"name":"Rust&#8217;s Huge Compilation Units"}]},{"@type":"WebSite","@id":"https:\/\/www.pingcap.com\/#website","url":"https:\/\/www.pingcap.com\/","name":"\ud2f0DB","description":"TiDB | SQL at Scale","publisher":{"@id":"https:\/\/www.pingcap.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.pingcap.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"ko-KR"},{"@type":"Organization","@id":"https:\/\/www.pingcap.com\/#organization","name":"PingCAP","url":"https:\/\/www.pingcap.com\/","logo":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/","url":"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png","contentUrl":"https:\/\/static.pingcap.com\/files\/2021\/11\/pingcap-logo.png","width":811,"height":232,"caption":"PingCAP"},"image":{"@id":"https:\/\/www.pingcap.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/facebook.com\/pingcap2015","https:\/\/x.com\/PingCAP","https:\/\/linkedin.com\/company\/pingcap","https:\/\/youtube.com\/channel\/UCuq4puT32DzHKT5rU1IZpIA"]},{"@type":"Person","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/6883a92f64d13c80ee57193b8c291a1c","name":"Brian Anderson","image":{"@type":"ImageObject","inLanguage":"ko-KR","@id":"https:\/\/www.pingcap.com\/#\/schema\/person\/image\/","url":"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg","contentUrl":"https:\/\/static.pingcap.com\/files\/2022\/10\/17234942\/avatar.jpg","caption":"Brian Anderson"},"description":"Senior Database Engineer","url":"https:\/\/www.pingcap.com\/ko\/blog\/author\/brian-anderson\/"}]}},"grav_blocks":false,"card_markup":"<a class=\"card-resource bg-white\" href=\"https:\/\/www.pingcap.com\/ko\/blog\/rust-huge-compilation-units\/\"><div class=\"card-resource__image-container\"><img class=\"card-resource__image\" alt=\"rust-compile-time-adventures.png\" src=\"https:\/\/static.pingcap.com\/files\/2020\/06\/rust-compile-time-adventures.jpg\" loading=\"lazy\" width=2000 height=667 \/><\/div><div class=\"card-resource__content-container\"><div class=\"card-resource__content-head\"><div class=\"card-resource__category\">Engineering<\/div><\/div><h5 class=\"card-resource__title\">Rust&#8217;s Huge Compilation Units<\/h5><\/div><\/a>","_links":{"self":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/1028","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/users\/43"}],"replies":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/comments?post=1028"}],"version-history":[{"count":5,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/1028\/revisions"}],"predecessor-version":[{"id":17450,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/posts\/1028\/revisions\/17450"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/media\/446"}],"wp:attachment":[{"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/media?parent=1028"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/categories?post=1028"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.pingcap.com\/ko\/wp-json\/wp\/v2\/tags?post=1028"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}