惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
News and Events Feed by Topic
爱范儿
爱范儿
Apple Machine Learning Research
Apple Machine Learning Research
博客园 - 叶小钗
Last Week in AI
Last Week in AI
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - Franky
人人都是产品经理
人人都是产品经理
The Cloudflare Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 司徒正美
罗磊的独立博客
博客园 - 聂微东
T
Troy Hunt's Blog
美团技术团队
IT之家
IT之家
A
Arctic Wolf
腾讯CDC
雷峰网
雷峰网
SecWiki News
SecWiki News
博客园_首页
L
LINUX DO - 最新话题
Cloudbric
Cloudbric
量子位
N
News and Events Feed by Topic
小众软件
小众软件
C
CXSECURITY Database RSS Feed - CXSecurity.com
Cyberwarzone
Cyberwarzone
J
Java Code Geeks
V
V2EX
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Latest news
Latest news
Webroot Blog
Webroot Blog
F
Fortinet All Blogs
P
Privacy International News Feed
NISL@THU
NISL@THU
Google Online Security Blog
Google Online Security Blog
WordPress大学
WordPress大学
PCI Perspectives
PCI Perspectives
GbyAI
GbyAI
宝玉的分享
宝玉的分享
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
Simon Willison's Weblog
Simon Willison's Weblog
P
Palo Alto Networks Blog
V
Visual Studio Blog

Dropbox Tech Blog

How our universal content processing platform Riviera evolved for AI and beyond How we used DSPy to turn AI evaluations into better responses in Dash chat How Dropbox uses MCP and Dash to close the design-to-code security gap Beyond code generation: rethinking engineering productivity in the age of AI agents Introducing Nova, our internal platform for coding agents Improving storage efficiency in Magic Pocket, our immutable blob store Reducing our monorepo size to improve developer velocity How we optimized Dash's relevance judge with DSPy Using LLMs to amplify human labeling and improve Dash search relevance How low-bit inference enables efficient AI Insights from our executive roundtable on AI and engineering productivity Engineering VP Josh Clemm on how we use knowledge graphs, MCP, and DSPy in Dash Inside the feature store powering real-time AI in Dropbox Dash Building the future: highlights from Dropbox’s 2025 summer intern class Fighting the forces of clock skew when syncing password payloads Introducing Focus, a new open source Gradle plugin Making camera uploads for Android faster and more reliable How Dropbox Replay keeps everyone in sync Why we built a custom Rust library for Capture Detecting memory leaks in Android applications Why we chose Apache Superset as our data exploration platform Revamping the Android testing pipeline at Dropbox Our counterintuitive fix for Android path normalization JQuery to React: How we rewrote the HelloSign Editor How we ensure credible analytics on Dropbox mobile apps Engineering Dropbox Transfer: Making simple even simpler Speeding up a Git monorepo at Dropbox with <200 lines of code Building for reliability at HelloSign Store grand re-opening: loading Android data with coroutines Modernizing our Android build system: Part I, the planning Modernizing our Android build system: Part II, the execution Our journey to type checking 4 million lines of Python The (not so) hidden cost of sharing code between iOS and Android Redux with Code-Splitting and Type Checking The Programmer Mindset: Main Debug Loop On working with designers Incrementally migrating over one million lines of code from Python 2 to Python 3 Crash reporting in desktop Python applications What we learned at our first JS Guild Summit How we rolled out one of the largest Python 3 migrations ever Dropbox Paper: Emojis and Exformation Creating a culture of accessibility Adding IPv6 connectivity support to the Dropbox desktop client Accelerating Iteration Velocity on Dropbox’s Desktop Client, Part 2 Accelerating Iteration Velocity on Dropbox’s Desktop Client, Part 1 DropboxMacUpdate: Making automatic updates on macOS safer and more reliable Annotations on Document Previews Open Sourcing Pytest Tools Open Sourcing Zulip – a Dropbox Hack Week Project Building Carousel, Part III: Drawing Images on Screen The Tech Behind Dropbox’s New User Experience on Mobile (Part 2) Building Dropbox’s New User Experience for Mobile, Part 1 Building Carousel, Part II: Speeding Up the Data Model Building Carousel, Part I: How we made our networked mobile app feel fast and local Scaling MongoDB at Mailbox Welcome Guido! Dropbox dives into CoffeeScript Some love for JavaScript applications Plop: Low-overhead profiling for Python Using the Dropbox API from Haskell A Python Optimization Anecdote Translating Dropbox
How we sped up Dropbox Android app startup by 30%
Marianna Budnikova · 2021-02-10 · via Dropbox Tech Blog

Application startup is the first thing our users experience after they install an app and then again every single time they launch it. A simple and snappy application brings users a lot more joy than an application that has a ton of features but takes an eternity to load. Realizing this, Dropbox Android team has invested in measuring, identifying, and fixing the issues that were affecting our app startup time. We ended up improving our app start time by 30%, and this is the story of how we did it.

Scary climb

Historically at Dropbox we have been tracking app start by measuring how long it took from the moment a user taps our app icon up until the moment the app was fully loaded and ready for user interactions. 

We abstracted away the measurement for app initialization in the following way:

perfMonitor.startScenario(AppColdLaunchScenario.INSTANCE)

// perform the work needed for launching the application

perfMonitor.stopScenario(AppColdLaunchScenario.INSTANCE)

Being a data-driven team, we have been tracking and monitoring the app initialization with the help of graphs accessible to all engineers. The graph below shows app startup p90 measurements from late March to early April 2020.

app startup p90 measurements from late March to early April 2020

As you can see in the graph, the app startup time does not seem to be changing that much. Small fluctuations in app startup that range a couple milliseconds are expected in an application used by millions of users with variety of devices and OS versions. 

However, when we looked at the app startup time from December 2019 to April 2020, we saw a different picture. The app startup time has been creeping up for months as the app evolved and more features got added. However, because our charts were only showing us changes over a two week period, we missed the slow creep of app startup time that was happening over several months.

android p90 app startup time from December 2019 to April 2020

While the discovery of the slowly increasing startup time was accidental, it caused us to dig deeper into the reasons why, as well as make sure that our monitoring, alerting tools, and charts were taking a broader, more cohesive look at our metrics. 

Give me more numbers

Some features in the application can be relatively simple to measure, such as how long an API call to the server takes. While other features, such as app startup, are a lot more complicated to measure. App startup requires many different steps on the device before the main app screen is shown to the user and the application is ready for user interaction. Examining our initialization code, we identified the main events that happen during our app initialization. Here are a few of them:

  1. Run migrations
  2. Load application services
  3. Load initial users

We started our investigation by leveraging the profiling tools in Android Studio to measure performance on our test phones. The problem with profiling the performance with this approach was that our test phones would not give us a statistically significant sampling of how well the app startup is actually doing. Dropbox Android application has over 1 billion installs on Google Play Store, spanning multiple types of devices, some of them old Nexus 5s, and others the newest and greatest Google devices. It would be a fool’s errand to try and profile that many configurations. So we decided to measure the different steps of app startup using scenarios and scenario steps in production.

Here is the updated initialization code where we added logging for the three aforementioned steps: 

perfMonitor.startScenario(AppColdLaunchScenario.INSTANCE)
perfMonitor.startRecordStep(RunMigrationsStep.INSTANCE)

// perform migrations step wrok

perfMonitor.startRecordStep(LoadAppServicesStep.INSTANCE)

// load application services step

perfMonitor.startRecordStep(LoadInitialUsers.INSTANCE)

// perform initial user loading step

perfMonitor.stopScenario(AppColdLaunchScenario.INSTANCE)

With the measurements instrumented in code, we were able to understand what steps in the app’s initialization were contributing the most to the app startup increase.

Performance offenders we found

The below graph shows the overall app startup time from January to October 2020.

android p90 app startup time from the January to October 2020

In May, we introduced measurements for each of the major steps that happen during application initialization. These measurements allowed us to identify and address the largest offenders to the performance of the app startup. 

data graphic showing each of the major steps that happen during android application initialization

The major app startup offenders included Firebase Performance library initialization, feature flag migration, and initial user loading.

Firebase Performance Library

Firebase Performance library is included in Google’s Firebase suite of products to measure and send metrics about the performance of the apps. It provides helpful functionality such as metrics for individual method performance as well as infrastructure to monitor and visualize the performance of different parts of the app. Unfortunately, Firebase Performance library also comes with some hidden costs. Among them are an expensive initialization process and as a result a significant increase in the build times. In our debugging, we discovered that Firebase suite initialization was seven times longer when Firebase Performance tool was enabled. To fix the performance issue, we chose to remove the Firebase Performance tool from the Android Dropbox application. Firebase Performance library is a wonderful tool that allows you to profile very low level performance details such as individual function calls, but since we have not been using these features, we decided that fast app startup outweighed the individual method performance data, and so we removed the reference to that library.

Migrations

There are several internal migrations that run each time the Dropbox application is launched. These can include updating feature flags, database migrations, etc. Unfortunately, we found that some of these migrations were running at every app launch. We didn’t notice the bad performance of these migrations previously, because the application launched quickly on development and test devices. Unfortunately, this migration code performed especially poorly on older versions of the OS and older devices, contributing to increased startup time. To resolve the issue, we began by investigating which migrations were essential on every launch and which migrations could now be removed entirely from the app. We found and removed at least one migration that was very old and therefore no longer needed, helping get our app start time back on track. 

User loading

In the legacy part of our application, we store Dropbox user contacts metadata on the device as JSON blobs. In an ideal world, those JSON blobs should be read and converted into Java objects only once. Unfortunately, the code to extract users was getting called multiple times from different legacy features of the app, and each time, the code would perform expensive JSON parsing to convert user JSON blobs into Java objects. Storing user contacts as JSON was a very outdated design and a part of our monolith legacy code. To get an immediate fix for this issue, we added functionality to cache the parsed user objects during initialization. As we continue working on breaking down the monolith legacy code, a more efficient and modern solution for user contact storage would be to use Room database objects and convert those objects to business entities.

What now?

As a result of removing reference to Firebase Performance, removing expensive migration steps, and caching user loading, we improved the app launch performance of the Dropbox Android application by 30%. Through this work, we have also put together dashboards that will help prevent degradation of the app startup time in the future. 

We also adopted several practices that will hopefully prevent us from making the same performance mistakes. Here are a couple of them:

Measure app startup performance impact when adding third party libraries
With the discovery of how much Firebase Performance library degraded our app startup, we introduced a process for adding third party libraries. Today, we require measuring the application startup time, build time and the APK size of the application before the library can be added and used in our codebase. 

Cache all the things
Since two of the major offenders to the app startup performance had to do with caching, we prefer to cache expensive computations even if it does make the code a bit more complicated. After all, a better user experience is worth a little extra maintenance. 

Conclusion

With more investments into credible analytics and performance measuring, we have become a lot more data-driven as a team which allows us to make larger investments into our code base, such as deprecating legacy C++ code, with a lot more confidence. Today, we monitor several dashboards that that provide us insights on performance of the most critical parts of our applications, and have processes in place to ensure that Dropbox applications continue to be snappy and a delight to our users.

Thanks to Amanda Adams, Angella Derington, Anthony Kosner, Chris Mitchell, David Chang, Eyal Guthmann, Israel Ferrer Camacho, and Mike Nakhimovich for comments and review.