<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Lucas Nelaupe on Medium]]></title>
        <description><![CDATA[Stories by Lucas Nelaupe on Medium]]></description>
        <link>https://medium.com/@lucas.nelaupe?source=rss-ae92a46d270b------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/2*Eu-8fbfoX4WJANfXUPkwzg.jpeg</url>
            <title>Stories by Lucas Nelaupe on Medium</title>
            <link>https://medium.com/@lucas.nelaupe?source=rss-ae92a46d270b------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 15 May 2026 15:52:25 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@lucas.nelaupe/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[I Backtested FL0WG0D Options Whale Alerts on X (Twitter)]]></title>
            <link>https://medium.com/@lucas.nelaupe/i-backtested-fl0wg0d-options-whale-alerts-on-x-twitter-b3218b9373ea?source=rss-ae92a46d270b------2</link>
            <guid isPermaLink="false">https://medium.com/p/b3218b9373ea</guid>
            <category><![CDATA[options-trading]]></category>
            <category><![CDATA[finance]]></category>
            <category><![CDATA[data-science]]></category>
            <category><![CDATA[vibe-coding]]></category>
            <category><![CDATA[investing]]></category>
            <dc:creator><![CDATA[Lucas Nelaupe]]></dc:creator>
            <pubDate>Sun, 11 Jan 2026 09:05:14 GMT</pubDate>
            <atom:updated>2026-01-12T15:11:48.989Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*qWwZRZptv92IWp8XiPliBw.png" /></figure><p>In this story, I’ll show how I vibe-coded a Python tool to backtest <a href="https://x.com/FL0WG0D?lang=en"><strong>FL0WG0D</strong></a> whale alerts on X, measure the % In The money (ITM) at expiry, and see whether copying big call-option buys is actually worth it.</p><h3>Market Whales</h3><blockquote>A market whale is a large investor, institution, or entity holding a significant amount of a particular asset (like <a href="https://www.google.com/search?q=stocks&amp;sca_esv=650a666f4569e185&amp;sxsrf=ANbL-n6Zj2CbWme9Ii5xUwR9XxCfuSJyuA%3A1768061527364&amp;ei=V3piaZWDFpmy4-EPhfWowQI&amp;ved=2ahUKEwjJn6-9roGSAxXh-qACHcdrFMUQgK4QegQIARAB&amp;uact=5&amp;oq=what%27s+a+market+whales&amp;gs_lp=Egxnd3Mtd2l6LXNlcnAiFndoYXQncyBhIG1hcmtldCB3aGFsZXMyCBAhGKABGMMESJ0TUABYsRFwA3gBkAEAmAG7AaABpAeqAQQxMS4xuAEDyAEA-AEBmAINoALmBsICBxAjGLACGCfCAggQABgHGAgYHsICCBAAGIAEGKIEwgIFEAAY7wXCAgoQABiwAxjWBBhHwgIGEAAYBxgewgILEAAYgAQYhgMYigXCAgYQABgIGB7CAgoQIRigARjDBBgKwgIIEAAYogQYiQWYAwCIBgGQBgiSBwQxMi4xoAezRbIHAzkuMbgH3wbCBwUxLjcuNcgHIYAIAA&amp;sclient=gws-wiz-serp&amp;mstk=AUtExfDo0pwEWDaCx-Ds2hJLVaDYuV9U2f4LryhW0aqVVqTtDfjHNiMYOyTIkgCmVubVApPSx-Knlvj_jlejZK0znWtRb4VVJkesXVMC_me-bKlDUpySZ00zPFbOvT8L99_IsOo42OiQagNcJwAwZ2xKcO13PcSxI-NZ3PQ9DjLpL5xk188G5k9gSWGrYW8tvuPck8j2_r7EagF6a_8e-ch0yeW7DWeSwWX1lpVVs2T4Av29hXY4QR5WN_d4C5KoxoozwgBqrgZdLrAIZLdxXj223k8x&amp;csui=3">stocks</a> or <a href="https://www.google.com/search?q=cryptocurrency&amp;sca_esv=650a666f4569e185&amp;sxsrf=ANbL-n6Zj2CbWme9Ii5xUwR9XxCfuSJyuA%3A1768061527364&amp;ei=V3piaZWDFpmy4-EPhfWowQI&amp;ved=2ahUKEwjJn6-9roGSAxXh-qACHcdrFMUQgK4QegQIARAC&amp;uact=5&amp;oq=what%27s+a+market+whales&amp;gs_lp=Egxnd3Mtd2l6LXNlcnAiFndoYXQncyBhIG1hcmtldCB3aGFsZXMyCBAhGKABGMMESJ0TUABYsRFwA3gBkAEAmAG7AaABpAeqAQQxMS4xuAEDyAEA-AEBmAINoALmBsICBxAjGLACGCfCAggQABgHGAgYHsICCBAAGIAEGKIEwgIFEAAY7wXCAgoQABiwAxjWBBhHwgIGEAAYBxgewgILEAAYgAQYhgMYigXCAgYQABgIGB7CAgoQIRigARjDBBgKwgIIEAAYogQYiQWYAwCIBgGQBgiSBwQxMi4xoAezRbIHAzkuMbgH3wbCBwUxLjcuNcgHIYAIAA&amp;sclient=gws-wiz-serp&amp;mstk=AUtExfDo0pwEWDaCx-Ds2hJLVaDYuV9U2f4LryhW0aqVVqTtDfjHNiMYOyTIkgCmVubVApPSx-Knlvj_jlejZK0znWtRb4VVJkesXVMC_me-bKlDUpySZ00zPFbOvT8L99_IsOo42OiQagNcJwAwZ2xKcO13PcSxI-NZ3PQ9DjLpL5xk188G5k9gSWGrYW8tvuPck8j2_r7EagF6a_8e-ch0yeW7DWeSwWX1lpVVs2T4Av29hXY4QR5WN_d4C5KoxoozwgBqrgZdLrAIZLdxXj223k8x&amp;csui=3">cryptocurrency</a>), giving them the power to drastically influence prices and market trends with their large trades. Because they possess huge holdings, their buying or selling activity can trigger sharp price movements, creating opportunities or risks for smaller traders, and can affect overall market liquidity and stability.</blockquote><p>A few X accounts track big “whale” options flows like @<a href="https://x.com/unusual_whales">unusual_whales</a>, @<a href="https://x.com/CheddarFlow">CheddarFlow</a> and @<a href="https://x.com/FL0WG0D">FLOWG0D</a>. The logic is simple: if institutions are throwing huge money into calls, maybe they know something you don’t… so why not tail them?</p><p><strong>Disclaimer</strong>: This is <strong>not financial advice</strong>. Nothing here is a recommendation to buy, sell, or hold any asset, and it’s shared for <strong>educational/informational</strong> purposes only. I’m using <strong>FLOWG0D</strong> purely as an example because their tweets are <strong>easy to parse</strong> for the dataset/tooling <strong>not</strong> because of any view on performance, credibility, or investment quality.</p><p><a href="https://x.com/FL0WG0D?lang=en"><strong>FL0WG0D</strong></a> regularly posts on X about unusually large call-option buys. The tweets follow a consistent template so from one post you can pull the ticker (NBIS), the expiry (16 Jan 2026), and the strike ($112). Then, at the close on 16 Jan 2026, you simply check NBIS: above $112 = ITM (In the money), below $112 = OTM (Out of the money).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/824/1*Pq7EtDqMvQlEHr0Lfm7aMg.png" /></figure><h3>Hey chatGPT vibe code the ITM rate tool in python</h3><p>The requirements were simple, and ChatGPT generated the full script: call the X API, parse the tweet text, run OCR on the attached image to grab expiry + strike, then if the option had already expired, pull the ticker’s closing price on that date from Yahoo Finance.</p><p>All I did was create an X API token and copy paste the code. It worked on the first run and exported everything into a clean CSV (built with ChatGPT plus subscription on GPT 5.2 Thinking model).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lgr24seqGv7P33kTyuI2RQ.png" /><figcaption><a href="https://docs.google.com/spreadsheets/d/1ct9CWn9bCfgjnHtAHE5fgg4uk0SXjgfNai2jobssWvM/edit?usp=sharing">RAW DATA</a> LINK</figcaption></figure><h3>Issue with Twitter API rate limit</h3><p>For this solution I’m using the free tier of the twitter API but I can only fetch 100 tweets per month which is not enough data. The second tier allows 15 000 read tweets but costs 200 USD per month !!!!!</p><p>I paid for it and immediately after I realised I could have just tried to scrap the website page for free. 🥴.</p><p>Another problem is the script always starts from the earliest tweet but those options are in the future so you need to wait for the expiry so I (chatGPT) updated (the script to only fetch tweets older than X days.</p><h3>Results: Are the whale alerts actually worth following? (NO)</h3><p><a href="https://docs.google.com/spreadsheets/d/1ct9CWn9bCfgjnHtAHE5fgg4uk0SXjgfNai2jobssWvM/edit?usp=sharing">RAW DATA</a></p><p>The script extracted 747 tweets with Ticker, strike price and expiry date. Since I pulled the most recent tweet, most of the posts (55%) didn’t reach the expiry date yet. Some calls are leap years and will expire in more than 1 year.</p><p><strong>Result: The call options being in the money (ITM) at the expiry date is 29%</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rxB2lHo8SS-ZE-Fkhe77yA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L2idXRCzuri0s4HOeBQnXg.png" /></figure><p><strong>Longer Day to expiry (DTE): more change to expire ITM ? NO</strong></p><p>From the 335 options that had already expired (so we could actually score them), the median DTE was 15 days, with a range from 0DTE to 60DTE. Since I only pulled tweets from the last 3 months, I don’t have much data for very long-dated expiries.</p><p>Next, I broke down ITM rate by DTE to see whether longer time-to-expiry actually improves the odds.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fWForHNvsPqpZ8uZO8f7oA.png" /><figcaption>ITM percentage per DTE</figcaption></figure><p>Since each DTE had a different number of samples, I asked ChatGPT to run a weighted linear regression (<a href="https://en.wikipedia.org/wiki/Weighted_least_squares">WLS</a>) to account for that imbalance.</p><p><strong>Result: </strong>+10 DTE would change ITM rate by about <strong>10 × 0.078% = 0.78%</strong> (less than 1%). Basically following a 0DTE or 60DTE will still give you around 30% ITM rate.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ciHKcHlSJoARVJP8g5L53g.png" /></figure><h3>Limitation and possible next step</h3><p>Even if ~70% of these calls expire worthless, <strong>it doesn’t automatically mean the whales lost money</strong> they most likely have exited earlier for a profit. A better next step would be to track the stock’s return from the tweet date to the option’s expiry, then compare it against a benchmark like the S&amp;P 500 to see whether these picks actually outperform over that window.</p><p>Following charts compare the stock variation between the timewhale open the position and the call expiry.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*hSzHJOXklBmWS7XXBEpvMg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MMNPj-Jp35ujmUWPSvyRXA.png" /></figure><h3>Conclusion</h3><ul><li>Expired calls were ITM ~29%</li><li>Longer DTE barely improved ITM rate</li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b3218b9373ea" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Leaving Grab after 3 years as an Android Engineer: My journey and learnings]]></title>
            <link>https://medium.com/@lucas.nelaupe/leaving-grab-after-3-years-as-an-android-engineer-my-journey-and-learnings-c409d5480bef?source=rss-ae92a46d270b------2</link>
            <guid isPermaLink="false">https://medium.com/p/c409d5480bef</guid>
            <category><![CDATA[software-engineer]]></category>
            <category><![CDATA[android-app-development]]></category>
            <category><![CDATA[process]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[learning]]></category>
            <dc:creator><![CDATA[Lucas Nelaupe]]></dc:creator>
            <pubDate>Fri, 09 Jul 2021 05:56:45 GMT</pubDate>
            <atom:updated>2021-07-09T07:30:29.547Z</atom:updated>
            <content:encoded><![CDATA[<p>In this story, I’ll reflect and provide a retrospective recap on my journey with Grab as an Android Engineer. From my interview until my last day. I’ll also recap my biggest take away and learn from this experience.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*viZrTGRNUXKirAcr" /></figure><p>My journey with Grab started in 2018 when I was looking for new challenges after almost 3 years as an Android (and iOS) engineer in my company. I looked at several tech companies in Singapore since I was already based here. The big names in Singapore with fast growing mobile (IOS / Android) teams at that time were Shopee and Grab. I directly thought that Grab would be a great place to work given how fast they are growing their tech team in Singapore. So I decided … not to apply (yet).</p><h3>Interviewing</h3><p>When you are offered a chance to be interviewed, you definitely don’t want to mess up your chances and come across as unprepared. I sought and found different information about the interview process and what I should focus on in order to maximise my chances at the interview. After 2 months of doing interviews for other companies and learning from their feedback, I decided to apply to Grab even though I didn’t feel fully ready. After 3 rounds, I received an offer and I accepted it.</p><p>Although I don’t recommend doing mock interviews since it’s time consuming and you are wasting interviewer time as well. If you want to prepare for an interview at Grab <a href="https://medium.com/@lucas.nelaupe/cracking-the-interview-for-software-engineer-at-grab-5dd47af292b7">I wrote an article about it</a>.</p><h3>Onboarding: 1st day at Grab</h3><p>There we go, Monday 7th May 2018. 10 am, hangover from the weekend, Marina One tower level 23rd at the Grab’s headquarter with 50 new “Grabbers” (The name given to Grab’s employees) onboarding the same day as me. Yup at that time Grab was onboarding new joiners every Monday by batches of not less than 50 new joiners. Fast growing you said ?</p><p>The onboarding took the entire day. We got an introduction to the company, the business and different verticals in the morning and a “GrabCar’’ immersion in the afternoon. The onboarding involves all full time Grabbers and is not specific to Software Engineers. In the afternoon we went to the office car park where our assigned Grab driver partners were waiting for us. We got to spend 1 hour in a GrabCar with a driver, picking up customers. This experience is essential to get familiar with our Ride-hailing core business and collecting feedback from customers.</p><p><em>Note: This onboarding was in 2018 and has, since then, been updated to include other core verticals like GrabFood.</em></p><p>During the onboarding, I should have normally got contacted by my “GrabBuddy”. A person from your future team who is helping you to get onboarding in the team). Unfortunately my GrabBuddy was attending a conference on the other side of the world in the US. So I had to meet the team and introduce myself. Fortunately the team was very welcoming and I wasn’t the only person joining this team on that day.</p><h3>My focus area at Grab</h3><p>I joined a team called CX (Consumer eXperience) responsible for transforming Grab with multiple services into a “<a href="https://medium.com/@infopulseglobal_9037/introducing-super-app-a-new-approach-to-all-in-one-experience-8a7894e8ddd4">SuperApp</a>”. I stayed in the CX team during my entire journey with Grab, but we had a lot of internal changes and different projects.</p><p>Over 3 years I had to work on several projects. From the new home page to the global search functionality. I also worked on different user centric features to help grab in becoming south-east Asia leading<a href="https://medium.com/@infopulseglobal_9037/introducing-super-app-a-new-approach-to-all-in-one-experience-8a7894e8ddd4"> </a>SuperApp.</p><p>I also worked on Engineering driven projects which include the “App performance project” where we focused on app startup time, memory consumption ,network usage optimization and overall crash rate.</p><h3>Learnings and Takeaways</h3><ul><li><strong>Go bold and learn from your mistakes.</strong> Two bold changes I made caused issues and were not caught before release despite all our safeguard and process in place. This led to releasing <a href="https://en.wikipedia.org/wiki/Hotfix">hotfix</a> 🥴. I wrote and presented a post-mortem with root cause, learning and action items. This helped in closing gaps in our workflow and the same issue will now be caught before landing on production.</li><li><strong>You need to set goals and learn from feedback to grow</strong>. At Grab, you will get to work with your manager to set up personal Objective &amp; Key Results (<a href="https://en.wikipedia.org/wiki/OKR">OKRs</a>) which include growth areas. When you start as a Software engineer, you have mostly 2 career choices: Individual contributor (Engineering branch) or Engineering manager (Management branch). I was unsure on which branch I wanted to grow. By not knowing and deciding on which area I want to grow, I missed some opportunities to learn and grow on different aspects of both branches. In my opinion, it’s better to focus and set goals for a branch. For example: if you’re on the Engineering manager side and later realise that it may not be exactly the career path that you want, the takeaway is that you understand the scope better, and then take action. This is better than never deciding and not growing into your desired career route.</li><li><strong>Feedback is the key to grow for yourself and others. </strong>Grab has a bi-annual performance review. While critics have found this to be time consuming and unproductive, those milestones offer more opportunities for you to provide and receive feedback. It’s important to keep the feedback specific with examples rather than general and meaningless just for the sake of giving feedback. The feedback I have received helps me to improve on my work and collaboration with my peers. While my hard skills were recognised, I had weaknesses in soft skills like communication. I have focused on this area by attending workshops and collecting more feedback for different situations. I have then improved a lot on this area but it’s always a work in progress.</li><li><strong>Interviewing is harder than being interviewed. </strong>I got the opportunity to conduct technical interviews. During my turn at Grab, I made more than 50+ interviews and several candidates received job offers. Assessing candidate technical skills is not something straightforward. I have worked with other interviewers on improving our interview process, simultaneously improving our expectations and having a more fair assessment from an interviewer.</li><li><strong>Learn how to adapt.</strong> When you join a company who onboards 50+ persons every week, you can expect a lot of internal reorg. The first 2 years, our team and projects were changing frequently. However, for the past year (2020–2021), things are more stable (At least for our team) with less frequent internal changes. Things are moving fast at Grab, I learnt how to be less impacted by workflow changes and how to adapt to new projects and new teams.</li><li><strong>Focus on what matters. </strong>A lot of things are happening at the same time at Grab. However, not everything is equally important. I learn how to focus on what matters to me and where I can make the most impact. You can clearly make a huge impact at Grab! All the managers I worked with are very open and supportive of engineering initiatives. I proposed and drove some initiatives (E.g: Dropping support for Jelly Bean and Kitkat) and closed some gaps in our process.</li><li><strong>Process is everything. </strong>Grab has a process for almost everything like making a new release, reacting to production incidents or proposing new ideas through <a href="https://en.wikipedia.org/wiki/Request_for_Comments">RFC</a>. Those processes are what make the company stable and robust. These processes also provide stability and the ability to go bold. I was never scared of making bold changes because I knew that we have many safeguards in place. And eventually if I’m causing some issues that land in production, this creates more opportunity for us to learn from our mistakes with our process related to production incidents. Over 3 years I have identified some gaps in our process and defined new ones that improve our workflow.</li></ul><h3>What’s next</h3><p>Over the last 3 years I got contacted by many different companies. Lately, one company approached me with an opportunity to work on a fast growing and large scale project. I decided to proceed and I cleared all the interviews. I have then resigned from my position at Grab.</p><h3>Conclusion</h3><p>Overall I will keep a positive record from my journey at Grab. I got the opportunity to work on a large scale system with hundreds of other talented developers. I have built strong relationships with some of them and will never forget them. I learned a lot from my peers and was able to make (positive) impact on millions of users and on overall Grab’s process and workflow. I also have a better visibility of my career path and area I have to focus on in order to reach my goal.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c409d5480bef" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How team process can scale to enable seamless remote working]]></title>
            <link>https://medium.com/@lucas.nelaupe/how-team-process-can-scale-to-enable-seamless-remote-working-9a4afdb13a9c?source=rss-ae92a46d270b------2</link>
            <guid isPermaLink="false">https://medium.com/p/9a4afdb13a9c</guid>
            <category><![CDATA[remote-work]]></category>
            <category><![CDATA[remote-working]]></category>
            <category><![CDATA[process]]></category>
            <dc:creator><![CDATA[Lucas Nelaupe]]></dc:creator>
            <pubDate>Sat, 28 Dec 2019 09:37:32 GMT</pubDate>
            <atom:updated>2019-12-28T09:37:32.029Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LzLj-FlOHqXYxBT8K4uuBg.jpeg" /></figure><p>In this article I’ll share my experience of working, time-to-time, remotely. From 1 day (Work from Home) to 1 full month remote in different timezone (7 hours time difference). Working remotely is the <a href="https://remotebliss.com/remote-working-statistics-and-trends/">new trend in tech companies</a>. however it’s not scaling well for all team process.</p><p><strong>Synchronous vs Asynchronous team</strong></p><p>We can split team process into 2 categories: The one with <em>Synchronous</em> and <em>asynchronous</em> process. I’ll go through both with advantage, tradeoff and how is it scaling to enable seamless remote working.</p><p><strong>Synchronous team process</strong></p><p>Having a synchronous process is the default standard in most of the companies. This can be defined by:</p><ul><li>Everyone has to join a meeting at the same time</li><li>Use Slack as instant message service</li></ul><p>However, this process will not be scalable for seamless remote work. Having a scrum meeting every morning at 10am SGT regardless where you are in the world. It can become a nightmare if you are working from with 7 hours time difference.</p><p>Synchronous company process can only have employees working remotely in the same region / timezone</p><p><strong>Asynchronous team process</strong></p><p>This process is the most suitable to enable seamless remote working, wherever you are in the world. It can be defined by</p><ul><li>Asynchronous meeting (Using tools like<a href="https://carrot.io/"> https://carrot.io</a>)</li><li>Communicate with emails</li></ul><p>Asynchronous meeting will scale better for remote employees (No timezone required). However, making alignment can become more complex or take more time. It can add extra idle time and delay to all communications.</p><p>When sending an email you don’t expect to receive a response within the minute unlike when you are sending an instant message (E.g: On slack). Having email as a backbone of communication can scale better and create less frustration during idle time.</p><p><strong>Which process for which team</strong></p><p>Having an asynchronous process will be more suitable if your team has a full time remote member. If you don’t have any, or if it is partial remote, you can probably accommodate with the synchronous process and skip a few of the meetings that are not critical. If your team only has 1 remote member, you can also accommodate and find a middle ground to avoid the tradeoff of being 100% async team.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9a4afdb13a9c" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Cracking the interview for Software Engineer at Grab]]></title>
            <link>https://medium.com/@lucas.nelaupe/cracking-the-interview-for-software-engineer-at-grab-5dd47af292b7?source=rss-ae92a46d270b------2</link>
            <guid isPermaLink="false">https://medium.com/p/5dd47af292b7</guid>
            <category><![CDATA[engineering]]></category>
            <category><![CDATA[grab]]></category>
            <category><![CDATA[algorithms]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[interview]]></category>
            <dc:creator><![CDATA[Lucas Nelaupe]]></dc:creator>
            <pubDate>Mon, 02 Dec 2019 10:00:34 GMT</pubDate>
            <atom:updated>2019-12-02T10:00:34.647Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*rGmTis29Zhx-aUo2" /></figure><p>Working at Grab for 2 years on the Android Passenger App, I had the opportunity to take interviews very quickly. The company is growing insanely fast (<a href="https://grab.careers/">We still have a lot of open positions</a>). I took more than 50 interviews and hired a few of the candidates. Today I’ll share about the interview process at Grab, <em>for mobile engineers</em>, and how to maximise your chances.</p><p><em>This is a personal thought based on my experience and may not reflect your interview experience. Opinions expressed are solely my own and do not express the views or opinions of my employer.</em></p><h3>Interview process</h3><p>Grab’s interview process (For mobile engineers, Android or iOS) is composed of a screening process plus 3 interviews rounds with a total of 5 interviews. This includes 2 back-to-back rounds with engineers, and a final round with an engineering manager.</p><p><strong>Codility Test (1 hour)</strong></p><p>Upon submitting your candidature, a Codility test will be sent to you. It’s mostly some simple algorithm question. Grab receives thousands of candidates and this round will help, <em>in my opinion</em>, filter all non-motivated candidates. Don’t feel offended if you receive this test even for a senior position. If you are willing to spend 1 hour solving some algorithm questions we can proceed forward.</p><p><strong>HR Screening</strong> (30 minutes)</p><p>Similar to the Codility Test, this screening session is a face-to-face (often via Zoom, a web-based video conferencing tool) conversation, designed to help us understand if you match our skill requirements and possess our cultural principles.</p><p><strong>Engineering round</strong> (2 hours)</p><p>During these 2 hours you will meet 2 engineers (1 hour each). They are selected based on availability and experience. It may not reflect the team you will be joining. The 2 rounds should include live coding.</p><ol><li><strong>Engineer A (1 hour) : </strong>Data Structures, Algorithms, Android, OOP</li><li><strong>Engineer B (1 hour) </strong>:<strong> </strong>OOD, Solid principles, Architecture &amp; Design</li></ol><p>I typically get involved at this point, sometimes taking the first part (Data Structure) or the second part (Architecture &amp; Design). This is how I generally structure the interview:</p><ul><li>5 minutes candidate introduction: Past project and problems solved</li><li>15 minutes for general question (Based on topic mentioned above). I can’t disclose the questions 🙊</li><li>30 minutes of problem solving including live coding. This is the most important part of the interview. (I give you some tips below)</li><li>5 minutes of Q&amp;A: Candidate can ask any question and we will answer.</li></ul><p><strong>Final round with Engineering manager (1 hour)</strong></p><p>The last round focuses on technical skills and cultural fit. Final decision is made by the engineering manager.</p><h3>Hiring committee</h3><p>Grab does not have a<em> hiring committee</em> for each candidate. However, if we have opposite feedback about the candidate (e.g. “Strong yes” and “Strong no” given by engineers), everyone involved during the process will join a 30 minute meeting where we discuss and determine the final outcome (“debrief”). We will also decide on the grade issued to the successful candidate (e.g. Junior vs. Senior).</p><h3>Tips for the interview</h3><p><strong>Understand the problem. </strong>During the live coding of the engineering round, make sure you analyse the problem properly. Don’t jump into a solution directly. Every software engineering problem has multiple solutions. Discuss the high level ideas and assumptions of your solutions before working on the implementation. Justify all the choices you are making. And most importantly: Do not make assumptions. Clarify with your interviewer if you are unsure of his/her asks. Think about the Grab scale with millions of users. Make sure your solution will scale for the company.</p><p><strong>Don’t cheat</strong>. If you are doing the interview remotely, do not google the question to answer. I saw this a few times and it’s obvious. If you don’t know the answer just say it. For the Codility round, there are a set of algorithms in place to detect if the candidate is cheating and copy pasted a solution online. <em>More importantly, Grab values Honor as one of its main principles in an employee. So don’t cheat!</em></p><p><strong>Learn about the company and the business</strong>. Try to ask questions in the Q&amp;A session that can reflect your interest in the company.</p><p><strong>Prepare for the interview</strong>. Before jumping into the 2 hours of rounds. You know the main topic. So spend some time to review the basic and make sure it’s fresh in your mind.</p><p><strong>Be in a quiet environment</strong>. Interviews can be done remotely via teleconferencing. However please make sure that you are in a quiet environment, have a decent mic and a stable connection. When the communication is choppy it is hard to get your message across and will reduce your chance of receiving a positive feedback.</p><p><strong>Have a strong reason to join Grab</strong>. My last question is always “Why do you want to leave your current company and why do you want to join Grab?”. DO NOT REPLY<strong>:</strong></p><blockquote>“Because you offer a good package”</blockquote><blockquote>“I saw your office on the internet and it looks nice”</blockquote><blockquote>“I don’t want to, actually”</blockquote><p>Believe it or not, but I really got those answers during an interview.</p><h3>Join Us !</h3><p>Interested in joining the Grab family? Check out <a href="http://grab.careers">http://grab.careers</a> for available roles today!</p><p>If you are about to start your journey with Grab, I wish you all the best!</p><p><strong>Thanks for reading this article. Be sure to click 👏 below to recommend this article if you found it helpful. It would let others get this article in feed and spread the knowledge.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5dd47af292b7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Efficient Android Images]]></title>
            <link>https://medium.com/@lucas.nelaupe/efficient-android-images-d50817346ae?source=rss-ae92a46d270b------2</link>
            <guid isPermaLink="false">https://medium.com/p/d50817346ae</guid>
            <category><![CDATA[efficiency]]></category>
            <category><![CDATA[optimization]]></category>
            <category><![CDATA[bitmap]]></category>
            <category><![CDATA[android-vector-drawable]]></category>
            <category><![CDATA[android]]></category>
            <dc:creator><![CDATA[Lucas Nelaupe]]></dc:creator>
            <pubDate>Mon, 02 Dec 2019 00:44:01 GMT</pubDate>
            <atom:updated>2021-09-24T04:50:47.400Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VSfBoCNkjpEIM_NUzVzOcQ.jpeg" /></figure><p>This article will explain the journey of an image from a developer point of view. Starting when you receive an image from the designer until it’s display in the most optimised way.</p><p><em>This article is following the talk I made during a</em><a href="https://www.meetup.com/kotlinsg/events/259591175/"><em> Singapore Kotlin User group</em></a><em> meetup at Google Singapore. Slides and video are available bellow.</em></p><h3>Before adding an image to your app</h3><p>Before adding your image to your application you can apply some optimisations. There are a bunch of tools available online that can do that. However in most cases it’s a lossy compression. Feel free to use any of those:</p><p><a href="https://pngquant.org/">PNGQuant</a>,<a href="http://www.imagemagick.org/script/index.php"> ImageMagick</a> ,<a href="http://pnggauntlet.com/"> PNGGauntlet</a>,<a href="http://advsys.net/ken/utils.htm"> PNGOut</a>,<a href="http://pmt.sourceforge.net/pngcrush/"> PNGCrush</a>,<a href="http://optipng.sourceforge.net/"> OptiPNG</a>,<a href="http://encode.ru/threads/1260-CryoPNG-short-introduction"> CryoPNG</a>,<a href="http://www.shpakovski.com/png-compressor/"> PNG Compressor</a>,<a href="http://www.imgopt.com/"> Yahoo Smush.it</a>,<a href="http://psydk.org/pngoptimizer"> PNGOptimizer</a>,<a href="http://www.punypng.com/"> PunyPNG</a>,<a href="https://tinypng.com/"> <strong>TinyPNG</strong></a>,<a href="https://github.com/hoehrmann/pngwolf"> PNGWolf</a>,<a href="http://www.advancemame.it/doc-advpng.html"> Advpng</a>,<a href="http://encode.ru/threads/455-Ben-Jos-Walbeehm-s-DeflOpt-what-does-it-actually-do"> DeflOpt</a>,<a href="http://encode.ru/threads/1214-defluff-a-deflate-huffman-optimizer"> Defluff</a>,<a href="http://encode.ru/threads/1313-Huffmix-a-PNGOUT-r-catalyst"> Huffmix</a>,<a href="http://en.css-ig.net/"> TruePNG</a>,<a href="https://sourceforge.net/projects/pngnqs9/"> PNGnq-s9</a>,<a href="https://github.com/pornel/mediancut-posterizer"> Median Cut Posterizer</a>,<a href="http://css-ig.net/scriptpng"> scriptpng</a>,<a href="http://css-ig.net/pngslim"> pngslim</a>,<a href="https://github.com/google/zopfli"> <strong>zopfliPNG</strong></a></p><p><strong>How it works</strong></p><p>All those services are pretty much applying the same algorithm which are doing as follows.</p><ul><li><strong>Reducing Colors: </strong>Reducing the number of unique colors in your image</li><li><strong>Filtering: </strong>Reduce dynamic by how variant adjacent pixel colors are to each other.</li><li><strong>Deflate: </strong>Remove redundant information</li><li><strong>Indexed images: </strong>Chooses the best 256 colors to use, and replaces all your pixels with an index into that color palette.</li></ul><blockquote><em>After optimisation, your image can be reduce from few Mb to few Kb. This will reduce the impact of your image on your APK size.</em></blockquote><h3>Memory footprint for a full screen image</h3><p>Bitmap can be seen as a 2 dimensional array of bit. If we take the case of a full screen image on a Full HD device.The footprint can be calculated this way:</p><ul><li>Screen width = 1920px</li><li>Screen height = 1080px</li><li>Total = 2,073,600px</li></ul><p>If we are drawing a black and white image. We only need 1 bit per pixel. So the memory footprint will be <strong>2,073,600 bit (0.26MB)</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/464/0*qigpm7wzb9ev0Vfh" /><figcaption>Illustration of a bitmap with 1 bit of color precision</figcaption></figure><p>Sadly not all our images are black and white so we need more data to represent the color of each pixel. On Android. We can choose the precision we would like to have.</p><p>Here is a summary table from<a href="https://developer.android.com/reference/android/graphics/Bitmap.Config"> Android documentation</a>. For each precision. I added the total memory footprint for a full HD image.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*tJxz3h8EnEuKIgSg" /></figure><p>I didn’t add the memory footprint when using Hardware. However, it will only use <strong>half of the memory</strong> compared to RGG_8888 for the <strong>exact same result. </strong>The system is storing pixel data in graphics memory instead of Java heap.<a href="https://github.com/bumptech/glide/blob/master/library/src/main/java/com/bumptech/glide/load/DecodeFormat.java#L43"> It’s default settings when loading images with Glide</a>.</p><p>However, hardware bitmap has some tradeoff. It’s only available starting <strong>Android O </strong>so it won’t benefit to old / low end devices. Each image will also consume a<a href="https://github.com/bumptech/glide/blob/e8c841ce4b8214a8765e3303dac6f6fc04775692/library/src/main/java/com/bumptech/glide/load/resource/bitmap/HardwareConfigState.java#L55"> file descriptor (FD) which can lead to crash</a>.</p><h3>Different caching mechanisms</h3><p>2 different caching mechanism can be used for solving 2 different problems. <em>LRUCache</em> and <em>Bitmap Pool.</em></p><p><strong>LRU cache (Least Recently Used)</strong></p><p>LRU cache is useful for images that are <strong>still used</strong>. We can keep a final image and avoid redundant computation in case of resizing for example.</p><p><strong>Bitmap Pool</strong></p><p>Bitmap Pool is for<strong> images that are no longer in use. </strong>The memory space allocated by the previous image can be reuse. The system will draw the new image on top of the old image. Starting SDK 19, Bitmap pool support different images dimensions.</p><blockquote>This two mechanism will help reducing the pressure on the memory. It will reduce the number of garbage collection (GC) or can even help reducing Out Of Memory crash (OOM).</blockquote><h3>In short: Keep it simple and use a library</h3><p>Library like Glide and Fresco implement all those optimisation and that’s the main reason they are so good at it.</p><p><a href="https://github.com/facebook/fresco"><strong>Fresco</strong></a>: #1 choice (Created by Facebook)</p><ul><li>Most advanced but complex APIs</li></ul><p><a href="https://github.com/bumptech/glide"><strong>Glide</strong></a>: Best compromise (<a href="https://developer.android.com/topic/performance/graphics/manage-memory">Recommended by Google</a>)</p><ul><li>LRU cache</li><li>Bitmap pool</li><li>Hardware bitmap / Pixel Color configuration</li><li>Gif support</li></ul><h3>Android Vector Drawable: Differences with SVG and tradeoff</h3><p>SVG support complex capabilities like Blur, filter effects, Embedding other images, Animated gifs and possibility to executing arbitrary javascript. Supporting everything on Android was not suitable for Android.</p><blockquote>Android runs on constrained mobile devices so supporting the entirety of the SVG spec wasn’t a realistic goal. (from:<a href="https://medium.com/androiddevelopers/ab09e41d5c68"> Understanding Android’s vector image format: VectorDrawable</a>) [<a href="https://medium.com/@crafty?source=post_page-----ab09e41d5c68----------------------"> Nick Butcher</a>: Android developer at Google]</blockquote><p><em>Android Vector Drawable </em>can be seen as a simpler version of <em>SVG </em>standard<em>. Only basic operation are supported to draw the images. Here is an example of how Android will interpret those information create the render.</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*jrp5_BHBAtuZ8uhL" /><figcaption>Drawing an Android Vector Drawable</figcaption></figure><ul><li><strong>M</strong> move to</li><li><strong>L</strong> line to</li><li><strong>C</strong> (cubic bezier) curve to</li><li><strong>Z</strong> close (line to first point)</li></ul><h3>Parsing and rendering Android Vector Drawable</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ksO6fOPooK2sXQzf" /><figcaption>Steps to render a vector drawable</figcaption></figure><ol><li><strong>Inflation</strong>: Parse your AVD file into <strong>VectorDrawable</strong> modeling the the paths, groups etc you declare</li><li><strong>Drawing</strong>: These model objects then have to be drawn by executing <strong>Canvas</strong> drawing commands.</li></ol><p>Steps are <strong>proportional to the complexity of the vector</strong> and the type of operations you perform. Drawing stage only needs to be performed once and can then be cached to a Bitmap</p><p><strong>Vectors provide the aforementioned benefits but at the cost of being more expensive to render.</strong></p><h3>Optimising SVG and Android Vector Drawable</h3><p>Before importing SVG to Android to you use <strong><em>Svgo</em></strong>. It can help reduce complexity and remove unnecessary meta information added by editor like photoshop.</p><p>After importing the image, you can use<a href="https://github.com/alexjlockwood/avocado"> <strong>Avocado</strong></a><strong> </strong>to optimise the <em>Android Vector Drawable</em>.</p><p>Note that both library are lossy compression. However from my experience the difference is not noticeable.</p><h3>Common issues with Android Vector Drawable</h3><p>AVD are constraints by 3 rules. On Android, Lint warning are implemented and Android Studio will highlight in the following cases. I strongly suggest to follow and fix those warning otherwise you will increase the memory pressure and it can even lead to crash.</p><ul><li>“android:width” : cannot be larger 200dp</li><li>“android:height” : cannot be higher 200dp</li><li>“android:path”: cannot exceed 1000 chars</li></ul><h3>Learn more about this topic</h3><p>Here I some great resources you can find to want to dig deeper.</p><ul><li><a href="https://medium.com/@duhroach/reducing-png-file-size-8473480d0476">https://medium.com/@duhroach/reducing-png-file-size-8473480d0476</a></li><li><a href="https://medium.com/appnroll-publication/what-is-new-in-android-p-imagedecoder-animatedimagedrawable-a65744bec7c1">https://medium.com/appnroll-publication/what-is-new-in-android-p-imagedecoder-animatedimagedrawable-a65744bec7c1</a></li><li><a href="https://medium.com/androiddevelopers/understanding-androids-vector-image-format-vectordrawable-ab09e41d5c68">https://medium.com/androiddevelopers/understanding-androids-vector-image-format-vectordrawable-ab09e41d5c68</a></li><li><a href="https://medium.com/androiddevelopers/using-vector-assets-in-android-apps-4318fd662eb9">https://medium.com/androiddevelopers/using-vector-assets-in-android-apps-4318fd662eb9</a></li><li><a href="https://medium.com/androiddevelopers/draw-a-path-rendering-android-vectordrawables-89a33b5e5ebf">https://medium.com/androiddevelopers/draw-a-path-rendering-android-vectordrawables-89a33b5e5ebf</a></li></ul><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fspeakerdeck.com%2Fplayer%2F55734d45d67f46f598d7950592932ebb&amp;url=https%3A%2F%2Fspeakerdeck.com%2Flucas34%2Fefficient-android-images&amp;image=https%3A%2F%2Fspeakerd.s3.amazonaws.com%2Fpresentations%2F55734d45d67f46f598d7950592932ebb%2Fslide_0.jpg%3F503880&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=speakerdeck" width="710" height="399" frameborder="0" scrolling="no"><a href="https://medium.com/media/3b37bbb853833c3bc49feb60903faff2/href">https://medium.com/media/3b37bbb853833c3bc49feb60903faff2/href</a></iframe><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FUF69cKSwbZQ%3Ffeature%3Doembed&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DUF69cKSwbZQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FUF69cKSwbZQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/43078328d35dffca7e91955d514d9569/href">https://medium.com/media/43078328d35dffca7e91955d514d9569/href</a></iframe><p><strong>Thanks for reading this article. Be sure to click 👏 below to recommend this article if you found it helpful. It would let others get this article in feed and spread the knowledge.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d50817346ae" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Android App Start explained]]></title>
            <link>https://medium.com/@lucas.nelaupe/android-app-start-explained-6b20d6700238?source=rss-ae92a46d270b------2</link>
            <guid isPermaLink="false">https://medium.com/p/6b20d6700238</guid>
            <category><![CDATA[optimization]]></category>
            <category><![CDATA[application]]></category>
            <category><![CDATA[android]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Lucas Nelaupe]]></dc:creator>
            <pubDate>Fri, 29 Nov 2019 05:31:42 GMT</pubDate>
            <atom:updated>2021-07-10T13:09:38.718Z</atom:updated>
            <content:encoded><![CDATA[<h3>Android App Start Explained</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ZHXXjX-JoFr641Mw3t_wSA.jpeg" /></figure><p>Working on Android App Start optimisation for the past 6 month at Grab (<a href="https://grab.careers/">We are hiring</a>), We did a lot of profiling and we immediately saw a lot of operations are done by the system just before you see the first frame.</p><p>This document will explain the 7 main steps requires to launch any Android App. We will also measure each steps to get the actual cost. We will use <a href="https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.time/-mono-clock/index.html"><em>MonoClock</em></a><em> </em>from Kotlin to measure time delta.</p><p>This will also help you in monitoring our application start performance and detecting performance regression.</p><p>All pieces of code of the article are summarise on a github sample project (Hello world app). <a href="https://github.com/lucas34/Android-AppStart-Breakdown">https://github.com/lucas34/Android-AppStart-Breakdown</a></p><p><em>We will only talk about the Cold App Start flow (app is not in memory). Also, we only focus on the app icon as entry point and not when the application is triggered by a deeplink or a push notification.</em></p><h3>The 7 steps of the Android App Launch</h3><ol><li>createAppContext: Loading the application binary into memory</li><li>makeApplication : Create Application class and init class attributes</li><li>installContentProvider: Instantiate and call onCreate for content providers</li><li>callApplicationOnCreate: call Application onCreate method</li><li>newActivity: Create activity class and init class attributes</li><li>attach: Attach context to the activity</li><li>performOnCreate: call activity.onCreate method</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2y-v3FEqfLyJa7OG8FaptA.png" /><figcaption>The 7 steps of the Android App Start</figcaption></figure><p>Let’s now see in detail all 7 components and how we can measure them.</p><h4><strong>1. createAppContext</strong></h4><p>The very first thing the android system is doing when you tap on the icon is creating Application <a href="https://developer.android.com/guide/components/processes-and-threads">process</a> and the main thread.</p><p>The main operation involved is <em>DexFile.openDexFileNative </em>which<em> </em>will load the application binary (The DEX file to simplify) into memory. This operation is pretty costly <a href="https://youtu.be/RgIxYwKNE88?t=1324">~350ms According to Google</a></p><p>At this point our application is not even created yet so we don’t have control to measure it. However since everything is done in main thread, on the first line of code that will be executed by the system we will get the time since the main thread is alive. This will count all the operations happening before we had control and <em>DEX</em> loading is the main contributor according to the call stack.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XUhn3fIUc4vBx2kDRz1Q8g.png" /></figure><p><strong>2. makeApplication</strong></p><p>Once our application binary is loaded into memory, the system will instantiate the application class and init all the class attributes from top down <em>(Class attributes defined at the top of the class are init before the one at the bottom)</em></p><p>So if we want to measure all the attributes definition we do as follow</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rn2MNoAeI30h172eWIeFzQ.png" /></figure><p>In this case we are measuring the time it takes for <em>MyDatabase</em> and <em>MyNetwork</em> to init. If anyone is adding a new class attribute or create an expensive object (Open the database in the constructor) we will be able to measure automatically.</p><p><strong>3. installContentProvider</strong></p><p>Content providers gets initialised after Application class but before Application.onCreate is called. To measure this we can do as follow</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*V5Cf8RdO-mSa7H44wgWmRg.png" /></figure><p>The delta between the end of the Application class attribute instantiation and the call of onCreate is measuring all content provider creation plus the onCreate call (For content provider).</p><p>Some libraries like Facebook SDK or Firebase use content provider to automatically init their library. This is pretty sneaky since adding a dependency to your project can increase your app start dramatically.</p><p><strong>4. callApplicationOnCreate</strong></p><p>This is the method you should be familiar with. In kotlin we can do this wrapping around the method to measure everything.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*G8WCPVITIoSi3wu5yQGOEA.png" /></figure><p>Code that will be added or modified inside the method will always be tracked and can prevent other dev to accidentally messing up with the measurement. Like for example adding code after we get the time (It happened 😥)</p><p><strong>5. newActivity, 6. attach and 7. performOnCreate</strong></p><p>Last 3 method measurement are pretty similar to the samples I gave before so I won’t explain more. If you want more detail please check the sample github project. (<a href="https://github.com/lucas34/Android-AppStart-Breakdown">https://github.com/lucas34/Android-AppStart-Breakdown</a>)</p><p>Here we go, we have our breakdown for each of the 7 steps with a <em>relatively</em> accurate metric for each of it. We can wrap all the metric under one data class. If we sum-up everything we very pretty close to the <a href="https://developer.android.com/reference/android/os/Process.html#getStartUptimeMillis()">Process elapsed time</a> which is the absolute app startup time</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*k42R42yv8w87FGEvDbN3ew.png" /></figure><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fib9mjzyMtcQ%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dib9mjzyMtcQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fib9mjzyMtcQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/839db25a4bded18c7da515035418b612/href">https://medium.com/media/839db25a4bded18c7da515035418b612/href</a></iframe><p><strong>Thanks for reading this article. Be sure to click 👏 below to recommend this article if you found it helpful. It would let others get this article in feed and spread the knowledge.</strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=6b20d6700238" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>