{"id":260120,"date":"2024-09-18T23:21:44","date_gmt":"2024-09-18T23:21:44","guid":{"rendered":"https:\/\/michigandigitalnews.com\/index.php\/2024\/09\/18\/become-a-better-android-developer-with-compiler-explorer\/"},"modified":"2025-06-25T17:11:15","modified_gmt":"2025-06-25T17:11:15","slug":"become-a-better-android-developer-with-compiler-explorer","status":"publish","type":"post","link":"https:\/\/michigandigitalnews.com\/index.php\/2024\/09\/18\/become-a-better-android-developer-with-compiler-explorer\/","title":{"rendered":"become a better Android developer with Compiler Explorer"},"content":{"rendered":"<p> [ad_1]<br \/>\n<\/p>\n<div>\n<meta content=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg6eHy3tppfLFscmsn8p8iHMTYhH__yu1IKO_kr4ce-QNWvtOlfhcY7a8f1NfiuTbHd3ibqfdQ7jhcTY9gHsRHyJp2XibKEGbDOquTUeUg_zJr41AsDZWhUc9WbEXW2Fk2gdH7Yu9dbGHZ9fjTtI2Ffx7E2-p-YrsOn-NjMuma2gOF166Qa8LH8N_VWDZI\/s1600\/0008-AFD-%20Tools%20Banner%20Asset%20_%20Banner%20Design%20_%20Metadata%20Card_meta%20card.png\" name=\"twitter:image\"\/><br \/>\n<img decoding=\"async\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg6eHy3tppfLFscmsn8p8iHMTYhH__yu1IKO_kr4ce-QNWvtOlfhcY7a8f1NfiuTbHd3ibqfdQ7jhcTY9gHsRHyJp2XibKEGbDOquTUeUg_zJr41AsDZWhUc9WbEXW2Fk2gdH7Yu9dbGHZ9fjTtI2Ffx7E2-p-YrsOn-NjMuma2gOF166Qa8LH8N_VWDZI\/s1600\/0008-AFD-%20Tools%20Banner%20Asset%20_%20Banner%20Design%20_%20Metadata%20Card_meta%20card.png\" style=\"display: none;\"\/><\/p>\n<p><em>Posted by Shai Barack \u2013 Android Platform Performance lead<\/em><\/p>\n<p><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg9roV-Qta9lnME3ailZgsr8eVC_lq-BX8RTPQcfW51Y-vMcbvEBFf44_qgVngBX2LLnzr0Fu2Z3hWJJc1ovgsmdFF905VGCst3uopJmHHDw5esD29UMkhLgYn2yl2yE86Hoq-nR3PUxyWHu30kMTBjjfaGIDJet0wIQrB7NPF-H-kZChULzoZhd6Wavos\/s1600\/0008-AFD-%20Tools%20Banner%20Asset%20_%20Banner%20Design%20_banner.png\"><img decoding=\"async\" border=\"0\" data-original-height=\"800\" data-original-width=\"100%\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg9roV-Qta9lnME3ailZgsr8eVC_lq-BX8RTPQcfW51Y-vMcbvEBFf44_qgVngBX2LLnzr0Fu2Z3hWJJc1ovgsmdFF905VGCst3uopJmHHDw5esD29UMkhLgYn2yl2yE86Hoq-nR3PUxyWHu30kMTBjjfaGIDJet0wIQrB7NPF-H-kZChULzoZhd6Wavos\/s1600\/0008-AFD-%20Tools%20Banner%20Asset%20_%20Banner%20Design%20_banner.png\"\/><\/a><\/p>\n<h2 style=\"text-align: left;\"><span style=\"font-size: x-large;\">Introducing Android support in Compiler Explorer<\/span><\/h2>\n<p>In a <a href=\"https:\/\/android-developers.googleblog.com\/2023\/11\/the-secret-to-androids-improved-memory-latest-android-runtime-update.html\" target=\"_blank\" rel=\"noopener\">previous blog post<\/a> you learned how Android engineers continuously improve the Android Runtime (ART) in ways that boost app performance on user devices. These changes to the compiler make system and app code faster or smaller. Developers don\u2019t need to change their code and rebuild their apps to benefit from new optimizations, and users get a better experience. In this blog post I\u2019ll take you inside the compiler with a tool called <a href=\"http:\/\/godbolt.org\" target=\"_blank\" rel=\"noopener\">Compiler Explorer<\/a> and witness some of these optimizations in action.<\/p>\n<p>Compiler Explorer is an interactive website for studying how compilers work. It is an <a href=\"https:\/\/github.com\/compiler-explorer\/compiler-explorer\" target=\"_blank\" rel=\"noopener\">open source project<\/a> that anyone can contribute to. This year, our engineers added support to Compiler Explorer for the Java and Kotlin programming languages on Android.<\/p>\n<p>You can use Compiler Explorer to understand how your source code is translated to assembly language, and how high-level programming language constructs in a language like Kotlin become low-level instructions that run on the processor.<\/p>\n<p>At Google our engineers use this tool to study different coding patterns for efficiency, to see how existing compiler optimizations work, to share new optimization opportunities, and to teach and learn.<br \/>\nLearning is best when it\u2019s done through <b><i>tools, not rules<\/i><\/b>. Instead of teaching developers to memorize different rules for how to write efficient code or what the compiler might or might not optimize, give the engineers the tools to find out for themselves what happens when they write their code in different ways, and let them experiment and learn. Let\u2019s learn together!<\/p>\n<p>Start by going to <a href=\"http:\/\/godbolt.org\" target=\"_blank\" rel=\"noopener\">godbolt.org<\/a>. By default we see C++ sample code, so click the dropdown that says C++ and select Android Java. You should see this <a href=\"https:\/\/godbolt.org\/z\/89f9vWE1q\" target=\"_blank\" rel=\"noopener\">sample code<\/a>:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">Square<\/span> {\n   static <span style=\"color: #b00040;\">int<\/span> <span style=\"color: blue;\">square<\/span>(<span style=\"color: #b00040;\">int<\/span> num) {\n       <span style=\"color: green; font-weight: bold;\">return<\/span> num * num;\n   }\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEi3GmyStlRmroF757mY7gsll-sU4fsvaQu9VBhh0AN8lEbyFlyMJN3SCG7sgHLBLZjUo9r3izPs88uCA7suwl5kmiWiuSfTCc_Mu1PSHVUqtRcfPcgHywu72swwxW1d8FnYkJg61hl-V4aMDf1JlfL4KhUgj_hg3GEA3JXfAuqHoNjc6t2bEnkXhk8wPFo\/s1600\/godbolt.org_z_jGvGEPsMb%20%281%29.png\" target=\"_blank\" rel=\"noopener\"><img fetchpriority=\"high\" decoding=\"async\" alt=\"screenshot of sample code in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEi3GmyStlRmroF757mY7gsll-sU4fsvaQu9VBhh0AN8lEbyFlyMJN3SCG7sgHLBLZjUo9r3izPs88uCA7suwl5kmiWiuSfTCc_Mu1PSHVUqtRcfPcgHywu72swwxW1d8FnYkJg61hl-V4aMDf1JlfL4KhUgj_hg3GEA3JXfAuqHoNjc6t2bEnkXhk8wPFo\/w640-h174\/godbolt.org_z_jGvGEPsMb%20(1).png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>On the left you\u2019ll see a very simple program. You might say that this is a one line program. But this is not a meaningful statement in terms of performance &#8211; how many lines of code there are doesn\u2019t tell us how long this program will take to run, or how much memory will be occupied by the code when the program is loaded.<\/p>\n<p>On the right you\u2019ll see a disassembly of the compiler output. This is expressed in terms of assembly language for the target architecture, where every line is a CPU instruction. Looking at the instructions, we can say that the implementation of the <span style=\"color: #0d904f; font-family: Courier;\">square(int num)<\/span> method consists of 2 instructions in the target architecture. The number and type of instructions give us a better idea for how fast the program is than the number of lines of source code. Since the target architecture is AArch64 aka ARM64, every instruction is 4 bytes, which means that our program\u2019s code occupies 8 bytes in RAM when the program is compiled and loaded.<\/p>\n<p>Let\u2019s take a brief detour and introduce some Android toolchain concepts.<\/p>\n<p><\/p>\n<h3>The Android build toolchain (in brief)<\/h3>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEgQZjdZFK_hfeeuFZeUedM-9aqMBG-WFDlget780ho9FvJ96N5MOKCsAjGCYPZ7NWkIx7KdpZ3yqghwGtpNX96DGbLaMyDrkng9UE0hFyxxEsrd4VDRFcGm15TvaGyiuAF0B8FotPxvpKR0Ulyu-9xiZTvH9g2zSxYR1I8hztFA21Fj9-mJbUDgFg8INEM\/s1600\/Diagram%20for%20Compiler%20Explorer%20blog%20post%20showing%20toolchain.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"a flow diagram of the Android build toolchain\" border=\"0\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEgQZjdZFK_hfeeuFZeUedM-9aqMBG-WFDlget780ho9FvJ96N5MOKCsAjGCYPZ7NWkIx7KdpZ3yqghwGtpNX96DGbLaMyDrkng9UE0hFyxxEsrd4VDRFcGm15TvaGyiuAF0B8FotPxvpKR0Ulyu-9xiZTvH9g2zSxYR1I8hztFA21Fj9-mJbUDgFg8INEM\/s1600\/Diagram%20for%20Compiler%20Explorer%20blog%20post%20showing%20toolchain.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"100%\"\/><\/a><\/div>\n<p><\/image><\/p>\n<p>When you write your Android app, you\u2019re typically writing source code in the Java or Kotlin programming languages. When you build your app in Android Studio, it\u2019s initially compiled by a language-specific compiler into language-agnostic JVM bytecode in a <span style=\"color: #0d904f; font-family: Courier;\">.jar<\/span>. Then the Android build tools transform the <span style=\"color: #0d904f; font-family: Courier;\">.jar<\/span> into <a href=\"https:\/\/source.android.com\/docs\/core\/runtime\/dalvik-bytecode\" target=\"_blank\" rel=\"noopener\">Dalvik bytecode<\/a> in <span style=\"color: #0d904f; font-family: Courier;\">.dex<\/span> files, which is what the <a href=\"https:\/\/source.android.com\/docs\/core\/runtime\" target=\"_blank\" rel=\"noopener\">Android Runtime<\/a> executes on Android devices. Typically developers use <span style=\"color: #0d904f; font-family: Courier;\">d8<\/span> in their Debug builds, and <span style=\"color: #0d904f; font-family: Courier;\">r8<\/span> for <a href=\"https:\/\/developer.android.com\/build\/shrink-code\" target=\"_blank\" rel=\"noopener\">optimized <i>Release builds<\/i><\/a>. The <span style=\"color: #0d904f; font-family: Courier;\">.dex<\/span> files go in the <span style=\"color: #0d904f; font-family: Courier;\">.apk<\/span> that you push to test devices or upload to an app store. Once the <span style=\"color: #0d904f; font-family: Courier;\">.apk<\/span> is installed on the user\u2019s device, an on-device compiler which knows the specific target device architecture can convert the bytecode to instructions for the device\u2019s CPU.<\/p>\n<p>We can use Compiler Explorer to learn how all these tools come together, and to experiment with different inputs and see how they affect the outputs.<\/p>\n<p>Going back to our default view for Android Java, on the left is Java source code and on the right is the disassembly for the on-device compiler <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span>, the very last step in our toolchain diagram. The target architecture is ARM64 as this is the most common CPU architecture in use today by Android devices.<\/p>\n<p>The <a href=\"https:\/\/developer.arm.com\/documentation\/102374\/latest\/\" target=\"_blank\" rel=\"noopener\">ARM64 Instruction Set Architecture<\/a> offers many instructions and extensions, but as you read disassemblies you will find that you only need to memorize a few key instructions. You can look for ARM64 Quick Reference cards online to help you read disassemblies.<\/p>\n<p>At Google we study the output of <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> in Compiler Explorer for different reasons, such as:<\/p>\n<ul>\n<ul>\n<li>Gaining intuition for what optimizations the compiler performs in order to think about how to write more efficient code.<\/li>\n<\/ul>\n<ul>\n<li>Estimating how much memory will be required when a program with this snippet of code is loaded into memory.<\/li>\n<\/ul>\n<ul>\n<li>Identifying optimization opportunities in the compiler &#8211; ways to generate instructions for the same code that are more efficient, resulting in faster execution or in lower memory usage without requiring app developers to change and rebuild their code.<\/li>\n<\/ul>\n<ul>\n<li>Troubleshooting compiler bugs! \ud83d\udc1e<\/li>\n<\/ul>\n<\/ul>\n<p><\/p>\n<h3>Compiler optimizations demystified<\/h3>\n<p>Let\u2019s look at a real example of compiler optimizations in practice. In the <a href=\"https:\/\/android-developers.googleblog.com\/2023\/11\/the-secret-to-androids-improved-memory-latest-android-runtime-update.html\" target=\"_blank\" rel=\"noopener\">previous blog post<\/a> you can read about compiler optimizations that the ART team recently added, such as <i>coalescing returns<\/i>. Now you can see the optimization, with Compiler Explorer!<\/p>\n<p>Let\u2019s load <a href=\"https:\/\/godbolt.org\/z\/695carsYh\" target=\"_blank\" rel=\"noopener\">this example<\/a>:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">CoalescingReturnsDemo<\/span> {\n   String <span style=\"color: blue;\">intToString<\/span>(<span style=\"color: #b00040;\">int<\/span> num) {\n       switch (num) {\n           case <span style=\"color: #666666;\">1<\/span>:\n               <span style=\"color: green; font-weight: bold;\">return<\/span> <span style=\"color: #ba2121;\">\"1\"<\/span>;\n           case <span style=\"color: #666666;\">2<\/span>:\n               <span style=\"color: green; font-weight: bold;\">return<\/span> <span style=\"color: #ba2121;\">\"2\"<\/span>;\n           case <span style=\"color: #666666;\">3<\/span>:\n               <span style=\"color: green; font-weight: bold;\">return<\/span> <span style=\"color: #ba2121;\">\"3\"<\/span>;           \n           <span style=\"color: green; font-weight: bold;\">default<\/span>:\n               <span style=\"color: green; font-weight: bold;\">return<\/span> <span style=\"color: #ba2121;\">\"other\"<\/span>;\n       }\n   }\n}\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhFT1jPAw-ufoFyz5DRSp2jAeUJos6gsC1GJI_-tVmFjY5Ct8hvYD3o9FnUC7ODyeTTkzb7b7N1HSiHgYiLoc8pBaI4D6bIfqZBsa7bV_LKbuFmj21Oi4-Ci-za4szrhTcl5p8reVcW52ZVMdi_n02bL8VtMIhrfYloWSiJ0vjGvw9b5JsNTfh1pk2Y4G0\/s2256\/godbolt.org_z_zjvYvTsT3.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"screenshot of sample code in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhFT1jPAw-ufoFyz5DRSp2jAeUJos6gsC1GJI_-tVmFjY5Ct8hvYD3o9FnUC7ODyeTTkzb7b7N1HSiHgYiLoc8pBaI4D6bIfqZBsa7bV_LKbuFmj21Oi4-Ci-za4szrhTcl5p8reVcW52ZVMdi_n02bL8VtMIhrfYloWSiJ0vjGvw9b5JsNTfh1pk2Y4G0\/s2256\/godbolt.org_z_zjvYvTsT3.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>How would a compiler implement this code in CPU instructions? Every case would be a branch target, with a case body that has some unique instructions (such as referencing the specific string) and some common instructions (such as assigning the string reference to a register and returning to the caller). <i>Coalescing returns<\/i> means that some instructions at the tail of each case body can be shared across all cases. The benefits grow for larger switches, proportional to the number of the cases.<\/p>\n<p>You can see the optimization in action! Simply create two compiler windows, one for <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> from the October 2022 release (the last release before the optimization was added), and another for <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> from the November 2023 release (the first release after the optimization was added). You should see that before the optimization, the size of the method body for <span style=\"color: #0d904f; font-family: Courier;\">intToString<\/span> was 124 bytes. After the optimization, it\u2019s down to just 76 bytes.<\/p>\n<p>This is of course a contrived example for simplicity\u2019s sake. But this pattern is very common in Android code. For instance consider an implementation of <span style=\"font-family: Courier;\"><a href=\"https:\/\/developer.android.com\/reference\/android\/os\/Handler#handleMessage%28android.os.Message%29\" target=\"_blank\" rel=\"noopener\">Handler.handleMessage(Message)<\/a><\/span>, where you might implement a switch statement over the value of <span style=\"font-family: Courier;\"><a href=\"https:\/\/developer.android.com\/reference\/android\/os\/Message#what\" target=\"_blank\" rel=\"noopener\">Message#what<\/a><\/span>.<\/p>\n<p>How does the compiler implement optimizations such as this? Compiler Explorer lets us look inside the compiler\u2019s pipeline of optimization passes. In a compiler window, click <i>Add New &gt; Opt Pipeline<\/i>. A new window will open, showing the High-level Internal Representation (HIR) that the compiler uses for the program, and how it\u2019s transformed at every step.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjBupj21MdD-TzUlhfrb7502StciqEwWWcqY2cF1MqJ5D1SGlJeNpP7ZiBdNb_J8fM5oqNiFo2RBnOnCv4qM7gj2JjZx9_q0Rk9iI97TPVAd3Y50UJqstFoUJ71h3Ai1xg7HOWxYF4mai08zMG9FU2m7RXxZHpEQWK7hm-cTESp8p2hGb6V8z2jll9cqZk\/s1600\/godbolt.org_z_bf96jsj9f.png\" target=\"_blank\" rel=\"noopener\"><img decoding=\"async\" alt=\"screenshot of the high-level internal representation (HIR) the compiler uses for the program in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjBupj21MdD-TzUlhfrb7502StciqEwWWcqY2cF1MqJ5D1SGlJeNpP7ZiBdNb_J8fM5oqNiFo2RBnOnCv4qM7gj2JjZx9_q0Rk9iI97TPVAd3Y50UJqstFoUJ71h3Ai1xg7HOWxYF4mai08zMG9FU2m7RXxZHpEQWK7hm-cTESp8p2hGb6V8z2jll9cqZk\/s1600\/godbolt.org_z_bf96jsj9f.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>If you look at the <span style=\"color: #0d904f; font-family: Courier;\">code_sinking<\/span> pass you will see that the November 2023 compiler replaces <span style=\"color: #0d904f; font-family: Courier;\">Return<\/span> HIR instructions with <span style=\"color: #0d904f; font-family: Courier;\">Goto<\/span> instructions.<\/p>\n<p>Most of the passes are hidden when <i>Filters &gt; Hide Inconsequential Passes<\/i> is checked. You can uncheck this option and see all optimization passes, including ones that did not change the HIR (i.e. have no \u201cdiff\u201d over the HIR).<\/p>\n<p>Let\u2019s study another simple optimization, and look inside the optimization pipeline to see it in action. Consider this code:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">ConstantFoldingDemo<\/span> {\n   static <span style=\"color: #b00040;\">int<\/span> <span style=\"color: blue;\">demo<\/span>(<span style=\"color: #b00040;\">int<\/span> num) {\n       <span style=\"color: #b00040;\">int<\/span> result = num;\n       <span style=\"color: green; font-weight: bold;\">if<\/span> (num == <span style=\"color: #666666;\">2<\/span>) {\n           result = num + <span style=\"color: #666666;\">2<\/span>;\n       }\n       <span style=\"color: green; font-weight: bold;\">return<\/span> result;\n   }\n}\n<\/pre>\n<\/div>\n<p>The above is functionally equivalent to the below:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">ConstantFoldingDemo<\/span> {\n   static <span style=\"color: #b00040;\">int<\/span> <span style=\"color: blue;\">demo<\/span>(<span style=\"color: #b00040;\">int<\/span> num) {\n       <span style=\"color: #b00040;\">int<\/span> result = num;\n       <span style=\"color: green; font-weight: bold;\">if<\/span> (num == <span style=\"color: #666666;\">2<\/span>) {\n           result = <span style=\"color: #666666;\">4<\/span>;\n       }\n       <span style=\"color: green; font-weight: bold;\">return<\/span> result;\n   }\n}\n<\/pre>\n<\/div>\n<p>Can the compiler make this optimization for us? Let\u2019s <a href=\"https:\/\/godbolt.org\/z\/zjx1r4Pvh\" target=\"_blank\" rel=\"noopener\">load it in Compiler Explorer<\/a> and turn to the Opt Pipeline Viewer for answers.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhl-IBHURMBmsLyRTi8bqG2UHpl9SSzgEjLpE5l42Dzdfc1ejl77_k1jxVuXKO2dnuYZX9YhbNCONwsUWN13AqexHMb1MukXzSVSXc0Jda41ZOo9x5byc1rRklf4Qj7p3AcxXZFgqcX9u0Nc09mpQzITxv06ZDLda9eQkoLKxta_1duiRfg-S1mu1NZgkk\/s1600\/godbolt.org_z_zjx1r4Pvh.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" alt=\"screenshot of Opt Pipeline Viewer in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEhl-IBHURMBmsLyRTi8bqG2UHpl9SSzgEjLpE5l42Dzdfc1ejl77_k1jxVuXKO2dnuYZX9YhbNCONwsUWN13AqexHMb1MukXzSVSXc0Jda41ZOo9x5byc1rRklf4Qj7p3AcxXZFgqcX9u0Nc09mpQzITxv06ZDLda9eQkoLKxta_1duiRfg-S1mu1NZgkk\/s1600\/godbolt.org_z_zjx1r4Pvh.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>The disassembly shows us that the compiler never bothers with \u201ctwo plus two\u201d, it knows that if <span style=\"color: #0d904f; font-family: Courier;\">num<\/span> is 2 then <span style=\"color: #0d904f; font-family: Courier;\">result<\/span> needs to be 4. This optimization is called <a href=\"https:\/\/en.wikipedia.org\/wiki\/Constant_folding\" target=\"_blank\" rel=\"noopener\">constant folding<\/a>. Inside the conditional block where we know that <span style=\"color: #0d904f; font-family: Courier;\">num == 2<\/span> we <i>propagate<\/i> the constant <span style=\"color: #0d904f; font-family: Courier;\">2<\/span> into the symbolic name <span style=\"color: #0d904f; font-family: Courier;\">num<\/span>, then <i>fold<\/i> <span style=\"color: #0d904f; font-family: Courier;\">num + 2<\/span> into the constant <span style=\"color: #0d904f; font-family: Courier;\">4<\/span>.<\/p>\n<p>You can see this optimization happening over the compiler\u2019s IR by selecting the <span style=\"color: #0d904f; font-family: Courier;\">constant_folding<\/span> pass in the Opt Pipeline Viewer.<\/p>\n<h3>Kotlin and Java, side by side<\/h3>\n<p>Now that we\u2019ve seen the instructions for Java code, try changing the language to Android Kotlin. You should see this sample code, the Kotlin equivalent of the basic Java sample we\u2019ve seen before:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">fun<\/span> <span style=\"color: blue;\">square<\/span>(num: Int): Int = num * num\n<\/pre>\n<\/div>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEiZwhhCzxk-8E8Ht7cqNEM8Tt1AZnhwIEXJU8guUuIZi3hipe_8XYUebA28vEFdjRl-JAdr3CkIi-lC5U2DgwLjyn6EzBXAwn051NKUXk3H8DqTjNgCmKKwNcRevmIc2jtflWERGYxgxHJ3UsksU_NEMmHhhYulzOF9bZo6MxqLb98hurOAbvLBwfse0FI\/s1600\/godbolt.org_z_GqfEYhEjK.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" alt=\"screenshot of sample code in Kotlin in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEiZwhhCzxk-8E8Ht7cqNEM8Tt1AZnhwIEXJU8guUuIZi3hipe_8XYUebA28vEFdjRl-JAdr3CkIi-lC5U2DgwLjyn6EzBXAwn051NKUXk3H8DqTjNgCmKKwNcRevmIc2jtflWERGYxgxHJ3UsksU_NEMmHhhYulzOF9bZo6MxqLb98hurOAbvLBwfse0FI\/s1600\/godbolt.org_z_GqfEYhEjK.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>You will notice that the source code is different but the sample program is functionally identical, and so is the output from <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span>. Finding the square of a number results in the same instructions, whether you write your source code in Java or in Kotlin.<\/p>\n<p>You can take this opportunity to study interesting language features and discover how they work. For instance, let\u2019s compare Java String concatenation with Kotlin String interpolation.<\/p>\n<p>In Java, you might write your code as follows:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">StringConcatenationDemo<\/span> <span style=\"color: #666666;\">{<\/span>\n   <span style=\"color: #b00040;\">void<\/span> <span style=\"color: blue;\">stringConcatenationDemo<\/span><span style=\"color: #666666;\">(<\/span>String myVal<span style=\"color: #666666;\">)<\/span> <span style=\"color: #666666;\">{<\/span>\n       System<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">out<\/span><span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">println<\/span><span style=\"color: #666666;\">(<\/span><span style=\"color: #ba2121;\">\"The value of myVal is \"<\/span> <span style=\"color: #666666;\">+<\/span> myVal<span style=\"color: #666666;\">);<\/span>\n   <span style=\"color: #666666;\">}<\/span>\n<span style=\"color: #666666;\">}<\/span>\n<\/pre>\n<\/div>\n<p>Let\u2019s find out how Java String concatenation actually works by <a href=\"https:\/\/godbolt.org\/z\/7vqcea8fd\" target=\"_blank\" rel=\"noopener\">trying this example in Compiler Explorer<\/a>.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEiAWpK-SGyrc2k3n-vJdoESPcFyCv8_S8_wBQX9NZDFsJNHEYtcvJjFjbtBcmCNWoOeLnA7gC74EmVfTFU8zrvPO2uofmSW2r5EgKjHsFEBus4tSdwBS8JX6bOfhm1t0jY2CNG5t1rz4ikkOLdadkrkXY89FSttx-dKLqzxGURf4UWId5v5feGbKaMBcN8\/s1600\/godbolt.org_z_7vqcea8fd.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" alt=\"screenshot of sample code in Kotlin in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEiAWpK-SGyrc2k3n-vJdoESPcFyCv8_S8_wBQX9NZDFsJNHEYtcvJjFjbtBcmCNWoOeLnA7gC74EmVfTFU8zrvPO2uofmSW2r5EgKjHsFEBus4tSdwBS8JX6bOfhm1t0jY2CNG5t1rz4ikkOLdadkrkXY89FSttx-dKLqzxGURf4UWId5v5feGbKaMBcN8\/s1600\/godbolt.org_z_7vqcea8fd.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>First you will notice that we changed the output compiler from <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> to <span style=\"color: #0d904f; font-family: Courier;\">d8<\/span>. Reading Dalvik bytecode, which is the output from <span style=\"color: #0d904f; font-family: Courier;\">d8<\/span>, is usually easier than reading the ARM64 instructions that <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> outputs. This is because Dalvik bytecode uses higher level concepts. Indeed you can see the names of types and methods from the source code on the left side reflected in the bytecode on the right side. Try changing the compiler to <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> and back to see the difference.<\/p>\n<p>As you read the <span style=\"color: #0d904f; font-family: Courier;\">d8<\/span> output you may realize that Java String concatenation is actually implemented by rewriting your source code to use a <span style=\"color: #0d904f; font-family: Courier;\">StringBuilder<\/span>. The source code above is rewritten internally by the Java compiler as follows:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\"><span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">StringConcatenationDemo<\/span> <span style=\"color: #666666;\">{<\/span>\n   <span style=\"color: #b00040;\">void<\/span> <span style=\"color: blue;\">stringConcatenationDemo<\/span><span style=\"color: #666666;\">(<\/span>String myVal<span style=\"color: #666666;\">)<\/span> <span style=\"color: #666666;\">{<\/span>\n       StringBuilder sb <span style=\"color: #666666;\">=<\/span> <span style=\"color: green; font-weight: bold;\">new<\/span> StringBuilder<span style=\"color: #666666;\">();<\/span>\n       sb<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">append<\/span><span style=\"color: #666666;\">(<\/span><span style=\"color: #ba2121;\">\"The value of myVal is \"<\/span><span style=\"color: #666666;\">);<\/span>\n       sb<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">append<\/span><span style=\"color: #666666;\">(<\/span>myVal<span style=\"color: #666666;\">);<\/span>\n       System<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">out<\/span><span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">println<\/span><span style=\"color: #666666;\">(<\/span>sb<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">toString<\/span><span style=\"color: #666666;\">());<\/span>\n  <span style=\"color: #666666;\">}<\/span>\n<span style=\"color: #666666;\">}<\/span>\n<\/pre>\n<\/div>\n<p>In Kotlin, we can use String interpolation:<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\">fun <span style=\"color: blue;\">stringInterpolationDemo<\/span><span style=\"color: #666666;\">(<\/span><span style=\"color: #a0a000;\">myVal:<\/span> String<span style=\"color: #666666;\">)<\/span> <span style=\"color: #666666;\">{<\/span>\n   System<span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">out<\/span><span style=\"color: #666666;\">.<\/span><span style=\"color: #7d9029;\">println<\/span><span style=\"color: #666666;\">(<\/span><span style=\"color: #ba2121;\">\"The value of myVal is $myVal\"<\/span><span style=\"color: #666666;\">);<\/span>\n<span style=\"color: #666666;\">}<\/span>\n<\/pre>\n<\/div>\n<p>The Kotlin syntax is easier to read and write, but does this convenience come at a cost? If you try this example in Compiler Explorer, you may find that the Dalvik bytecode output is roughly the same! In this case we see that Kotlin offers an improved syntax, while the compiler emits similar bytecode.<\/p>\n<p>At Google we study examples of language features in Compiler Explorer to learn about how high-level language features are implemented in lower-level terms, and to better inform ourselves on the different tradeoffs that we might make in choosing whether and how to adopt these language features. Recall our learning principle: tools, not rules. Rather than memorizing rules for how you should write your code, use the tools that will help you understand the upsides and downsides of different alternatives, and then make an informed decision.<\/p>\n<h3>What happens when you minify your app?<\/h3>\n<p>Speaking of making informed decisions as an app developer, you should be minifying your apps with R8 when building your Release APK. Minifying generally does three things to optimize your app to make it smaller and faster:<\/p>\n<ul>\n<ul>\n<p>1. <b>Dead code elimination:<\/b> find all the live code (code that is reachable from well-known program entry points), which tells us that the remaining code is not used, and therefore can be removed.<\/p>\n<\/ul>\n<ul>\n<p>2. <b>Bytecode optimization:<\/b> various specialized optimizations that rewrite your app\u2019s bytecode to make it functionally identical but faster and\/or smaller.<\/p>\n<\/ul>\n<ul>\n<p>3. <b>Obfuscation:<\/b> renaming all types, methods, and fields in your program that are not accessed by reflection (and therefore can be safely renamed) from their names in source code (<span style=\"color: #0d904f; font-family: Courier;\">com.example.MyVeryLongFooFactorySingleton<\/span>) to shorter names that fit in less memory (<span style=\"color: #0d904f; font-family: Courier;\">a.b.c<\/span>).<\/p>\n<\/ul>\n<\/ul>\n<p>Let\u2019s see an example of all three benefits! Start by <a href=\"https:\/\/godbolt.org\/z\/hP4n7dq8n\" target=\"_blank\" rel=\"noopener\">loading this view in Compiler Explorer<\/a>.<\/p>\n<p><image\/><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg-lVfEDqLGMJ9vhPcqTA7Aj-YcizLtEYGJtBsPerSfWQIoy1nWDnGg4o0KhdkZpNCp_6-eDpLH9LW4YIjetHseA2NJhwmcaj0BS7DlRyqJbrerCn8Oc01JG8LocV4JKsGtHC5lPTvbBj8qHeWpmz6tYIvJkdTKf_jLA06tjF2xGyZZWw43JgFWMmCxId0\/s1600\/godbolt.org_z_hP4n7dq8n.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" alt=\"screenshot of sample code in Kotlin in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEg-lVfEDqLGMJ9vhPcqTA7Aj-YcizLtEYGJtBsPerSfWQIoy1nWDnGg4o0KhdkZpNCp_6-eDpLH9LW4YIjetHseA2NJhwmcaj0BS7DlRyqJbrerCn8Oc01JG8LocV4JKsGtHC5lPTvbBj8qHeWpmz6tYIvJkdTKf_jLA06tjF2xGyZZWw43JgFWMmCxId0\/s1600\/godbolt.org_z_hP4n7dq8n.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/p>\n<p>First you will notice that we are referencing types from the Android SDK. You can do this in Compiler Explorer by clicking Libraries and adding <i>Android API stubs<\/i>.<\/p>\n<p>Second, you will notice that this view has multiple source files open. The Kotlin source code is in <span style=\"color: #0d904f; font-family: Courier;\">example.kt<\/span>, but there is another file called <span style=\"color: #0d904f; font-family: Courier;\">proguard.cfg<\/span>.<\/p>\n<div style=\"background: rgb(248, 248, 248); border: 0px; overflow: auto; width: auto;\">\n<pre style=\"line-height: 125%; margin: 0px;\">-keep <span style=\"color: green; font-weight: bold;\">class<\/span> <span style=\"color: blue; font-weight: bold;\">MinifyDemo<\/span> {\n   <span style=\"color: green; font-weight: bold;\">public<\/span> <span style=\"color: green; font-weight: bold;\">void<\/span> <span style=\"color: blue;\">goToSite<\/span>(...);\n}\n<\/pre>\n<\/div>\n<p>Looking inside this file, you\u2019ll see directives in the format of Proguard configuration flags, which is the legacy format for configuring what to keep when minifying your app. You can see that we are asking to keep a certain method of <span style=\"color: #0d904f; font-family: Courier;\">MinifyDemo<\/span>. \u201cKeeping\u201d in this context means don\u2019t shrink (we tell the minifier that this code is live). Let\u2019s say we\u2019re developing a library and we\u2019d like to offer our customer a prebuilt <span style=\"color: #0d904f; font-family: Courier;\">.jar<\/span> where they can call this method, so we\u2019re keeping this as part of our API contract.<\/p>\n<p>We set up a view that will let us see the benefits of minifying. On one side you\u2019ll see <span style=\"color: #0d904f; font-family: Courier;\">d8<\/span>, showing the dex code without minification, and on the other side <span style=\"color: #0d904f; font-family: Courier;\">r8<\/span>, showing the dex code with minification. By comparing the two outputs, we can see minification in action:<\/p>\n<ul>\n<ul>\n<p>1. <b>Dead code elimination:<\/b> R8 removed all the logging code, since it never executes (as <span style=\"color: #0d904f; font-family: Courier;\">DEBUG<\/span> is always false). We removed not just the calls to <span style=\"color: #0d904f; font-family: Courier;\">android.util.Log<\/span>, but also the associated strings.<\/p>\n<\/ul>\n<ul>\n<p>2. <b>Bytecode optimization:<\/b> since the specialized methods <span style=\"color: #0d904f; font-family: Courier;\">goToGodbolt<\/span>, <span style=\"color: #0d904f; font-family: Courier;\">goToAndroidDevelopers<\/span>, and <span style=\"color: #0d904f; font-family: Courier;\">goToGoogleIo<\/span> just call <span style=\"color: #0d904f; font-family: Courier;\">goToUrl<\/span> with a hardcoded parameter, R8 inlined the calls to <span style=\"color: #0d904f; font-family: Courier;\">goToUrl<\/span> into the call sites in <span style=\"color: #0d904f; font-family: Courier;\">goToSite<\/span>. This inlining saves us the overhead of defining a method, invoking the method, and returning from the method.<\/p>\n<\/ul>\n<ul>\n<p>3. <b>Obfuscation:<\/b> we told R8 to keep the public method <span style=\"color: #0d904f; font-family: Courier;\">goToSite<\/span>, and it did. R8 also decided to keep the method <span style=\"color: #0d904f; font-family: Courier;\">goToUrl<\/span> as it\u2019s used by <span style=\"color: #0d904f; font-family: Courier;\">goToSite<\/span>, but you\u2019ll notice that R8 renamed that method to <span style=\"color: #0d904f; font-family: Courier;\">a<\/span>. This method\u2019s name is an internal implementation detail, so obfuscating its name saved us a few precious bytes.<\/p>\n<\/ul>\n<\/ul>\n<p>You can use R8 in Compiler Explorer to understand how minification affects your app, and to experiment with different ways to configure R8.<\/p>\n<p>At Google our engineers use R8 in Compiler Explorer to study how minification works on small samples. The authoritative tool for studying how a real app compiles is the <a href=\"https:\/\/developer.android.com\/studio\/debug\/apk-analyzer#view_dex_files\" target=\"_blank\" rel=\"noopener\">APK Analyzer in Android Studio<\/a>, as optimization is a whole-program problem and a snippet might not capture every nuance. But iterating on release builds of a real app is slow, so studying sample code in Compiler Explorer helps our engineers quickly learn and iterate.<\/p>\n<p>Google engineers build very large apps that are used by billions of people on different devices, so they care deeply about these kinds of optimizations, and strive to make the most use out of optimizing tools. But many of our apps are also very large, and so changing the configuration and rebuilding takes a very long time. Our engineers can now use Compiler Explorer to experiment with minification under different configurations and see results in seconds, not minutes.<\/p>\n<p>You may wonder what would happen if we changed our code to rename <span style=\"color: #0d904f; font-family: Courier;\">goToSite<\/span>? Unfortunately our build would break, unless we also renamed the reference to that method in the Proguard flags. Fortunately, R8 now natively supports <a href=\"https:\/\/r8.googlesource.com\/r8\/+\/refs\/heads\/main\/doc\/keepanno-guide.md\" target=\"_blank\" rel=\"noopener\">Keep Annotations<\/a> as an alternative to Proguard flags. We can modify our program to use Keep Annotations:<\/p>\n<div style=\"background: #f8f8f8; overflow:auto;width:auto;border:0;\">\n<pre style=\"margin: 0; line-height: 125%\">@UsedByReflection(kind = KeepItemKind.CLASS_AND_METHODS)\n<span style=\"color: #008000; font-weight: bold\">public<\/span> static <span style=\"color: #008000; font-weight: bold\">void<\/span> <span style=\"color: #0000FF\">goToSite<\/span>(Context context, String site) {\n    ...\n}\n<\/pre>\n<\/div>\n<p>Here is the <a href=\"https:\/\/godbolt.org\/z\/MPeqx7M4M\" target=\"_blank\" rel=\"noopener\">complete example<\/a>. You\u2019ll notice that we removed the <span style=\"color: #0d904f; font-family: Courier;\">proguard.cfg<\/span> file, and under <i>Libraries<\/i> we added \u201cR8 keep-annotations\u201d, which is how we\u2019re importing <span style=\"font-family: Courier;\"><a href=\"https:\/\/storage.googleapis.com\/r8-releases\/raw\/main\/docs\/keepanno\/javadoc\/com\/android\/tools\/r8\/keepanno\/annotations\/UsedByReflection.html\" target=\"_blank\" rel=\"noopener\">@UsedByReflection<\/a><\/span>.<\/p>\n<p>At Google our engineers prefer annotations over flags. Here we\u2019ve seen one benefit of annotations &#8211; keeping the information about the code in one place rather than two makes refactors easier. Another is that the annotations have a self-documenting aspect to them. For instance if this method was kept actually because it\u2019s called from native code, we would annotate it as <span style=\"color: #0d904f; font-family: Courier;\">@UsedByNative<\/span> instead.<\/p>\n<h3>Baseline profiles and you<\/h3>\n<p>Lastly, let\u2019s touch on <a href=\"https:\/\/developer.android.com\/topic\/performance\/baselineprofiles\/overview\" target=\"_blank\" rel=\"noopener\">baseline profiles<\/a>. So far you saw some demos where we looked at dex code, and others where we looked at ARM64 instructions. If you toggle between the different formats you will notice that the high-level dex bytecode is much more compact than low-level CPU instructions. There is an interesting tradeoff to explore here &#8211; whether, and when, to compile bytecode to CPU instructions?<\/p>\n<p>For any program method, the Android Runtime has three <a href=\"https:\/\/source.android.com\/docs\/core\/runtime\/configure#how_art_works\" target=\"_blank\" rel=\"noopener\">compilation options<\/a>:<\/p>\n<ul>\n<ul>\n<p>1. Compile the method Just in Time (<a href=\"https:\/\/source.android.com\/docs\/core\/runtime\/jit-compiler\" target=\"_blank\" rel=\"noopener\">JIT<\/a>).<\/p>\n<\/ul>\n<ul>\n<p>2. Compile the method Ahead of Time (<a href=\"https:\/\/source.android.com\/docs\/core\/runtime#AOT_compilation\" target=\"_blank\" rel=\"noopener\">AOT<\/a>).<\/p>\n<\/ul>\n<ul>\n<p>3. Don\u2019t compile the method at all, instead use a bytecode interpreter.<\/p>\n<\/ul>\n<\/ul>\n<p>Running code in an interpreter is an order of magnitude slower, but doesn\u2019t incur the cost of loading the representation of the method as CPU instructions which as we\u2019ve seen is more verbose. This is best used for \u201ccold\u201d code &#8211; code that runs only once, and is not critical to user interactions.<\/p>\n<p>When ART detects that a method is \u201chot\u201d, it will be JIT-compiled if it\u2019s not already been AOT compiled. JIT compilation accelerates execution times, but pays the one-time cost of compilation during app runtime. This is where baseline profiles come in. Using baseline profiles, you as the app developer can give ART a hint as to which methods are going to be hot or otherwise worth compiling. ART will use that hint before runtime, compiling the code AOT (usually at install time, or when the device is idle) rather than at runtime. This is why <a href=\"https:\/\/android-developers.googleblog.com\/2022\/01\/improving-app-performance-with-baseline.html\" target=\"_blank\" rel=\"noopener\">apps that use Baseline Profiles see faster startup times<\/a>.<\/p>\n<p>With Compiler Explorer we can see Baseline Profiles in action.<\/p>\n<p>Let\u2019s open <a href=\"https:\/\/godbolt.org\/z\/MGKfxh9hE\" target=\"_blank\" rel=\"noopener\">this example<\/a>.<\/p>\n<p><image><\/p>\n<div style=\"text-align: center;\"><a href=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjOn0hsv0Am0aTPdSKLvaDNkpoTC1dj0hSwY7D-Ld7RST_KyW7rjTScxqRwHsCq6oj-ARQHunsPLawKOS3hXdhCKVh7aSxBTfPLXg-ch49NurJCp7x9-SErozEWOlnvwaLBskR4yDO_jC_c8bctNrqveDLGaGYSRvpq6bPLTPmnoGL3zKY4i3Rb2oK4rZ0\/s1600\/godbolt.org_z_hP4n7dq8n.png\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" alt=\"screenshot of sample code in Compiler Explorer\" border=\"0\" height=\"174\" id=\"imgCaption\" src=\"https:\/\/blogger.googleusercontent.com\/img\/b\/R29vZ2xl\/AVvXsEjOn0hsv0Am0aTPdSKLvaDNkpoTC1dj0hSwY7D-Ld7RST_KyW7rjTScxqRwHsCq6oj-ARQHunsPLawKOS3hXdhCKVh7aSxBTfPLXg-ch49NurJCp7x9-SErozEWOlnvwaLBskR4yDO_jC_c8bctNrqveDLGaGYSRvpq6bPLTPmnoGL3zKY4i3Rb2oK4rZ0\/s1600\/godbolt.org_z_hP4n7dq8n.png\" style=\"margin-left: auto; margin-right: auto;\" width=\"640\"\/><\/a><\/div>\n<p><imgcaption><center><em>click to enlarge<\/em><\/center><\/imgcaption><\/image><\/p>\n<p>The Java source code has two method definitions, <span style=\"color: #0d904f; font-family: Courier;\">factorial<\/span> and <span style=\"color: #0d904f; font-family: Courier;\">fibonacci<\/span>. This example is set up with a <a href=\"https:\/\/developer.android.com\/topic\/performance\/baselineprofiles\/manually-create-measure\" target=\"_blank\" rel=\"noopener\">manual baseline profile<\/a>, listed in the file <span style=\"color: #0d904f; font-family: Courier;\">profile.prof.txt<\/span>. You will notice that the profile only references the <span style=\"color: #0d904f; font-family: Courier;\">factorial<\/span> method. Consequently, the <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> output will only show compiled code for <span style=\"color: #0d904f; font-family: Courier;\">factorial<\/span>, while <span style=\"color: #0d904f; font-family: Courier;\">fibonacci<\/span> shows in the output with no instructions and a size of 0 bytes.<\/p>\n<p>In the context of compilation modes, this means that <span style=\"color: #0d904f; font-family: Courier;\">factorial<\/span> is compiled AOT, and <span style=\"color: #0d904f; font-family: Courier;\">fibonacci<\/span> will be compiled JIT or interpreted. This is because we applied a different <a href=\"https:\/\/source.android.com\/docs\/core\/runtime\/configure#compiler_filters\" target=\"_blank\" rel=\"noopener\">compiler filter<\/a> in the profile sample. This is reflected in the <span style=\"color: #0d904f; font-family: Courier;\">dex2oat<\/span> output, which reads: \u201cCompiler filter: speed-profile\u201d (AOT compile only profile code), where previous examples read \u201cCompiler filter: speed\u201d (AOT compile everything).<\/p>\n<h2 style=\"text-align: left;\"><span style=\"font-size: x-large;\">Conclusion<\/span><\/h2>\n<p>Compiler Explorer is a great tool for understanding what happens after you write your source code but before it can run on a target device. The tool is easy to use, interactive, and shareable. Compiler Explorer is best used with sample code, but it goes through the same procedures as building a real app, so you can see the impact of all steps in the toolchain.<\/p>\n<p>By learning how to use tools like this to discover how the compiler works under the hood, rather than memorizing a bunch of rules of optimization best practices, you can make more informed decisions.<\/p>\n<p>Now that you&#8217;ve seen how to use the Java and Kotlin programming languages and the Android toolchain in Compiler Explorer, you can level up your Android development skills.<\/p>\n<p>Lastly, don&#8217;t forget that Compiler Explorer is an open source project on <a href=\"https:\/\/github.com\/compiler-explorer\/compiler-explorer\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>. If there is a feature you&#8217;d like to see then it&#8217;s just a Pull Request away.<\/p>\n<p><em><small>Java and OpenJDK are trademarks or registered trademarks of Oracle and\/or its affiliates.<\/small><\/em><\/p>\n<\/div>\n<p>[ad_2]<br \/>\n<br \/><a href=\"http:\/\/android-developers.googleblog.com\/2024\/09\/become-better-android-developer-compiler-explorer.html\">Source link <\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>[ad_1] Posted by Shai Barack \u2013 Android Platform Performance lead Introducing Android support in Compiler Explorer In a previous blog post you learned how Android<\/p>\n","protected":false},"author":1,"featured_media":260121,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[146],"tags":[],"_links":{"self":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/260120"}],"collection":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/comments?post=260120"}],"version-history":[{"count":0,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/posts\/260120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media\/260121"}],"wp:attachment":[{"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/media?parent=260120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/categories?post=260120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michigandigitalnews.com\/index.php\/wp-json\/wp\/v2\/tags?post=260120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}