12 ms·
How Discord achieves native iOS performance with React Native
- reimertz 7y agoI almost got an tear in my eye reading this, being heavily invested in React-Native and the worries I’ve felt since Airbnb abandoned the ship. I’ve always loved the framework and the beauty of being able to write native , cross-platform applications as a web developer. And what they are doing right now, trying to get rid of the js-thread bottleneck in 2020 excites me a lot! > “While it was closed it always had a spinning animation in the background chewing away at CPU — death by the smallest cut!” I spent an entire day doing the same! I had a spinner running in the background that ate 30% of my battery! I felt so stupid back then. :) Thanks Discord for sharing this, the community really appreciates it!
- londons_explore 7y agoA spinner running in the background consuming CPU is two bugs... The non-obvious one is why is the framework consuming any CPU time at all on something not visible? When an element tries to animate, and the whole element is covered/offscreen, the framework should simply pause the animation. When the element becomes visible again, it's simple to calculate how long the element has been invisible, and fast-forward the animation to that frame.
- dep_b 7y agoIf a UITableView is not visible it doesn't render anything at all. Which is a real gotcha if you didn't know that through a UI bug your height got set to 0 ;)
- reimertz 7y agoMaybe you created your own spinner, swapping between 100 cute pngs...?
- ericlewis 7y agoI’ve seen this happen especially with Lottie. And what basically happens here is the actual drawing isn’t actually handled by react-native since the library is itself a native view to either platform. Therefore, react-native has no idea it’s wasting any resources because it’s not technically “in charge” of what exactly the native view itself is doing. It certain scenarios where it might be “covered up”, such as all JavaScript based views (which are essentially just UIViews in iOS) then iOS itself also doesn’t know to stop this animation either (view compositing is quite popular). However, if using something like native navigation, where view controllers and their life cycle get handled by iOS then it will correctly end an animation. I have no idea if this is true for Android. But I have witnessed it on iOS and fixed this issue in react-native apps on quite a few occasions. The ultimate downside to frameworks like this is they imo, don’t know enough about the content they’re showing to make great choices for users. But at the same time, it’s not fully desirable to attempt to assume. That’s the platforms job. And that’s an obvious catch-22. How should you know this if you aren’t a native app builder?
- obmelvin 7y ago> How should you know this if you aren’t a native app builder? My impression has been that to use RN well you need to mostly think like and have the knowledge of someone who is a native app developer. You just get some benefit of sharing UI across platforms, but still need to do many things you would for native. I haven't used RN, just saw my friend who uses give a talk on it. So I certainly may not understand exactly how much native code you can or can't write while also using RN.
- mrkcsc 7y agoThe strongest RN teams and engineers I've seen tend to be those that either already have or are willing to acquire knowledge about how native app development works under the hood. It greatly augments your ability to write elegant solutions to hard problems. Some argue this is a large cost to bear - however I'd say it's one that is very reasonable to acquire. Having experience and knowledge in several languages/frameworks helps make one stronger engineer.
- tinus_hn 7y agoOn Mac OS iTunes and Finder manage to waste a lot of CPU spinning spinners while running g their backups. Apparently either it isn’t that easy or it’s easy to do wrong.
- dancemethis1 7y agoDon't thank people actively working on proprietary software bent on hindering people's rights to privacy and freedom.
- mrkcsc 7y agoThanks for the read, and the support!
- bsaul 7y agoI recently tried to start a react native / typescript project, but the ecosystem confused me a lot. The various different tool recommended to create a project, some project templates not even compiling, the tons of different utilities required to process source files.. All that and not a single reliable source of documentation, made me feel it would be a real nightmare to maintain on the long run.
- latchkey 7y agoYou are right. This is part of what made me try Flutter for a new app over RN. While it isn't perfect (no tooling is), the initial user experience is pretty good and the documentation is constantly updated as the product matures.
- paulintrognon 7y agoI understand they are using the Dart langugage? Was it hard to master?
- latchkey 7y agoSuper easy if you know JS/TS and turns out that I actually quite like it.
- virtualwhys 7y agoWhat's missing? TS has quite a few interesting language features that I assume Dart is missing (seems Dart has the reputation of being a Java-like language, with all the boilerplate that that entails).
- latchkey 7y agoProbably my largest complaint is the need to use codegen for the json stuff. Sure you can type it all out by hand, but the codegen really does automate a lot of it for you. I have intentionally kept my very specific use case mobile app very very simple and not gone deep on the magic edge cases. It is a private app and will never be on the store. It is basically used as a QR code scanner to track equipment. I'm sure that if you have a lot deeper/larger apps you'd find more to complain about, but so far I'm happy enough with going from zero to full fledged app in about a month of work. IMHO, the boilerplate argument with Java is kind of outdated (Project Lombok and modern java solve a lot of that).
- wdb 7y agoSounds like React Native causes more work then necessary. Business logic can be easily shared between different platforms, Android, macOS, Windows and iOS. Always the most time is spend to make the app behave right for each platform, so that’s only bit which differs. I am happily writing apps in Swift for Android and iOS
- mattacular 7y agoThe Swift for Android and iOS makes sense but how do you "easily" share same business logic between those other different platforms?
- rsynnott 7y agoSwift will also work on Windows, and of course on MacOS (and Linux). If you prefer, you could use Kotlin in a similar role via kotlin-native.
- eropple 7y agoBut Swift won't work on Android. And Kotlin Native is severely compromised. The lingua franca options are effectively Xamarin, Flutter, and React Native. Xamarin's dev experience sucks and Flutter's perf isn't much different from React Native with a way less mature ecosystem. There are people who should write platform-native mobile apps. For everybody else, React Native is fine. And, for my money, TypeScript is the most right programming language easily available on major platforms today, so that makes this one pretty self-evident to me.
- dannyr 7y agoSo Discord's iOS app is React Native while its Android app is native (i.e. Java/Kotlin)?
- mrkcsc 7y agoBlog author here - this is correct (mostly Kotlin :) This is primarily an artifact of history for us. When we first set out to build the mobile apps, React Native for Android had not yet been open sourced so we had no choice but to build it in native. That being said, the Android side of RN has always been more nascent and so one of the benefits for us has been not having to deal with some of those early bugs/issues while building our our current iOS app. It's since become much more mature however - so we may explore RN for Android again someday.
- jpincheira 7y agoVery interesting to read how they were able to overcome their performance issues and didn't know they were such a small but effective team. For us at Standups[1] RN has been just instrumental. As a small team, we are able to ship features, just like Discord, vertically all across the stack. Having 1 language in common (TypeScript) all across your stack is the best for small teams/startups. We share most of our code. For those of you interested in how to share code vertically using TypeScript[2], check out this guide by Bruno Lemos, super helpful, great value there for startups and especially tech solopreneurs. [1] https://standups.io https://standups.io [2] https://dev.to/brunolemos/tutorial-100-code-sharing-between-ios-android--web-using-react-native-web-andmonorepo-4pej https://dev.to/brunolemos/tutorial-100-code-sharing-between-...
- hqrlk 7y agoThe iOS app of Discord is crappy compared to the Android app. I mean, it's not bad bad, but it's not good, or at least not as good. I wonder why they decided to go this route instead of hiring iOS developers? I could understand if they used the same app for both platforms (like they do with their Electron app, which is also not as good as Ripcord), but since they have a native app for Android...
- Assadi 7y agoAs far as I know, they use react for both. Where did you hear that they had a native android app?
- hqrlk 7y agoSince their iOS and Android apps are different, and the iOS one is built using React, I just assumed the Android one is native. Why would they build two different React apps? Isn't the entire point that you can share the code?
- sedeki 7y agoThe point of React Native is being cross-platform, yes. But you said Android had a native app.
- GeneralTspoon 7y agoFrom their open job positions - it looks like the Android app is indeed native (mostly Kotlin + heavy use of RxJava). And only iOS + web (+ desktop?) are mentioned in the post. I'd imagine the reason they didn't use RN on Android is because historically it's always had much worse performance on that platform. iOS RN performance is usually acceptable, but Android has always been a bit of a 2nd-class citizen.
- helpPeople 7y agoReduce your Apple footprint? I try to stay away from that company as much as I can, but since users unfortunately use that company.
- defied 7y agoAnother good optimization step is to replace the JsC engine for Android with Hermes.
- saghul 7y agoIs it ready for prime time? IIRC it has only been around for the last couple of releases which makes me worry a bit.
- llacb47 7y agoTheir app is still slow...
- dancemethis1 7y agoGrabbing all that user data and metadata has its share of computing cost. But hey, the higher-ups will profit from it so it's ok.
- tov_objorkin 7y agoOnce i have a dream about RN application for iOS/Android without Xcode and AndroidStudio. Started with Expo, great tool if you don't have native modules. But i have, very complex search library in Rust. After few attempts the code was converted to asmjs (RN doesn't support wasm). So i have JS-only codebase that works on Expo. Livecoding (a bit slow beause of large js codebase) and easy deploymnet on all platforms. After release users starts complain about performance. RN fetch API doesn't support binaries, everything passed back and forth as base64. Some low-mid tier phones got stuck for few minutes. Also RN fetch doesn't support progress and a lot of other thing. Decision was to start using native libraries. Ehh, goodby sweety Expo... The lesson was learned, if you have complex application don't expect too much without heavy investment. JS is ugly and unpredictable as usualy. Overall experience is ok/mehh, but not great. For the next project i give Qt5 a chance.
- tracker1 7y agoMay want to also look at MS/Xamarin development, I know a few people that really like it. Though, RN seems a bit more popular. For that matter, in what ways is JS unpredictable? Generally combined with Redux or something similar, I've found it to be fairly consistent and predicatble.
- tov_objorkin 7y agoAbout five years ago i have a dream, that i can abandon all this peasant C/C++ development and jump into mono/xamarin train. As a main product we have Linux ARM/MIPS karaoke machine with optional remote control via desktop/mobile apps. The idea was to use same code every where. - Tooling for Linux was horrible, like really! - Alien mobile UI look and feel - One can not simple build mobile app for desktop. - New shiny search engine prototype doesn't fit into low tier Phone RAM. - Mono Hello world application on MIPS device with 128RAM uses about 28 mb of RAM. - 400 MHz cpu have really hard times with GC, nogo for soft-realtime. - No seamless integration with native code, using libs like ffmpeg is crazy hard. - F# was 2nd citizen in that time! Now things changed, but still imho Linux is not a good choose for .net, also MS force you to use Azure/Cloud/etc infrastructure.
- beders 7y agoAmazing job by the discord team having the patience with the available tools to analyze these problems and the stamina to dig deeper and deeper. Well done! It is quite interesting to see that the re-frame and fulcro authors were on the right track adding their own 'componentNeedsUpdate' layer which is very fast and will minimize the repainting React has to do. (Mostly thanks to immutability)
- mrkcsc 7y agoThank you for the kind words!
- trevorah 7y agoReact Native is excellent for web teams that are creating a new mobile app. If your team has more experience with React than native iOS/Android, then it's a no-brainer. However, in my experience you get diminishing returns once your app has passed v1 and your customers expect more after the new-ness wears off. You find yourself spending more and more engineering effort to make your RN app to feel as good as existing mature native-first apps, which is especially frustrating as you are solving problems that native-first app developers never had to solve in the first place. They got the solutions for free with the native sdks. This plateau of developer effectiveness is hard to get away from as your app becomes so coupled to RN and your team invests so much into RN tooling and skills that it feels like a sunk cost. I do not envy the Discord apps team.
- adatavizguy 7y agoI use react native svg with low level d3.js utils to produce data visualizations with a utility class that holds all the animation values across components and screens which is sort of a hack but very clean for animating several pseudo svg components. For me it isn't about look and feel so much as being able to quickly manage massive amounts of data for interaction and data viz. I use the ramda lenses, sagas, redux, and selector stack to manage state of the data. It is clean and quick to develop. Everything is memoized with selectors only changing if the reference to the object it is using on the state tree changes. Nobody can work data the way I can with React. It makes sense.
- nazka 7y agoHum! I didn't know Ramda, very interesting... Thank you for sharing your stack :)
- mrkcsc 7y agoBlog author here. As a native app developer, I would say that the trade off is similar to developing an app on native Android vs. native iOS. You inevitably must solve problems on Android that iOS has not yet solved (or are trivially easy to do) and vice versa, but each framework also has its own strengths that come with it. React Native is no different in this regard. We sometimes solve different problems that occasionally area easier to do on Native (although as mentioned by this post, this is the first time in years we've actually had to sit down and focus on performance). That being said, some of the pros are that we save a tremendous amount of time through code sharing, web team contributions, etc.
- nfRfqX5n 7y agogreat work
- rkangel 7y agoIt's good to see that they care a lot about TTI and put work into optimisation, but the desktop app needs the same love. My Windows PC boots to the desktop in less time than it takes for Discord to then start up. I'm unclear what it's doing - checking for updates? This is about my only gripe with Discord though, it's a great service.
- xez 7y agowhat does TTI stand for? I'm having some trouble figuring that one out
- neon_electro 7y agoTime to Interactive: https://calibreapp.com/blog/time-to-interactive https://calibreapp.com/blog/time-to-interactive
- Justsignedup 7y agoI'm just gonna say. Great writeup and a good example case in performance optimizations. Now please make discord in windows start up faster than it takes to boot windows. That's right cold starting my computer and logging in takes less time than starting discord.
- enraged_camel 7y agoWhy not just use the browser client?
- dbg31415 7y agoI like Discord a lot, but it's so funky. (Also, wish their support team would just send a link to allow users to file bugs.) 1) Weird issue where it reconnects you on across multiple devices. I was on my phone... then switched to computer. Phone was no longer active. About 5 minutes after I got done with the game, Discord on my phone kicked on all by itself. Phone was sitting in another room, and all of a sudden Discord chat was being broadcast. (Luckily PTT was enabled so they didn't hear me.) It shouldn't try and reconnect... once you hang up once, it should know to hang up across all devices. 2) Can't upload profile or server images more than twice before it triggers some sort of internal cooldown on uploading images. Just puts you on the same page and pops a warning, "You have unsaved changes!" but won't let you save. Quit, wait a few minutes, try again... works. Annoying when you crop something wrong and have to re-upload. It should always let you upload, or give some message, "Still sending out your last image to all users, try again in 5 minutes." 3) Can't resize Window via window manager (Magnet on MacOS). I think this is the only program I have seen that won't let me drag and snap it. Annoying.
- nothis 7y agoWhy, in the "Battery Heat" section is there a link on the small d in Discord that leads to http://watchanimeattheoffice.com/ http://watchanimeattheoffice.com/, which apparently redirects to discordapp.com. So weird!
- eternalny1 7y ago> Why, in the "Battery Heat" section is there a link on the small d in Discord that leads to http://watchanimeattheoffice.com/ http://watchanimeattheoffice.com/, which apparently redirects to discordapp.com. So weird! Pssst ... https://twitter.com/discordapp/status/1088195791355703296 https://twitter.com/discordapp/status/1088195791355703296
- ThomPete 7y agoWe were considering using React Native for our task and communication app for non-desktop workforce, we even started out that way but realised how much effort we would have to put into getting things working especially since our interface is a little different and ended but ended up building native for both Android and iOS. Haven't regretted it a bit.
- chasd00 7y agothe cross platform dream is so appealing and I've used Ionic off and on for years because of it. At the end of each project I say to myself "never again, i will just learn Swift" ( i already know java ). Then, slowly but steadily, the cross platform dream takes root and blossoms. Off I go with the latest Ionic and "this time it will be different".
- olah_1 7y agoIn terms of snappy / beautiful messaging apps, nothing beats Telegram imo. It's made with Qt, I believe.
- ignoramous 7y agoThe client code is open-source, btw: https://github.com/DrKLO/Telegram https://github.com/DrKLO/Telegram
- js2 7y agoSome people, when confronted with having to develop a mobile app on Android and iOS, think “I know, I'll use React Native.” Now they have three problems: Android, iOS and React Native. My company has both natively developed Android and iOS apps, as well as a few RN apps. I'm in the developer tooling part of the company. Indeed, the RN apps did allow those teams to add developers who had only JavaScript coding experience. But at the cost of a lot of additional complexity elsewhere in the company. Now we effectively have to support three platforms in our build system, in our SDKs, and so forth. I'm fairly confident that it is not a net win. Those RN developers eventually have to learn the weird idiosyncrasies of both Android and iOS besides the idiosyncrasies added by RN itself. They now have bugs that show up on only one platform because RN Android is using a different JS engine than RN iOS. There's just a gigantic amount of complexity added by RN on-top of the gigantic amount of complexity you already get with Android and iOS. In the end, at best you end up with a mediocre cross-platform app. I think RN probably has a sweet spot: a small to medium sized app developed by a sole or maybe a few developers. Once you're big enough to have teams of developers, I think RN is a mistake. With respect to this article, the amount of work and expertise in both RN and iOS necessary to achieve their performance goals seems pretty extreme ("mobile performance squad"). And this was all just for iOS? Did any of it translate to their RN Android app? It's a counter factual so who knows, but I suspect the performance problems wouldn't have occurred on a native app in the first place, and if they had, would've been straightforward to track down in Instruments. They claim all this work is offset by allowing their web app developers to contribute to the RN app and that it allowed them to develop the iOS app more quickly, but I have my doubts. As it is, they've got three developers dedicated to the RN iOS app alone and despite that, still ran into performance problems. Again, maybe they have enough shared code and developers to make it worthwhile, but I dunno.
- jjeaff 7y agoI don't think size of app is the concern. It's what your app does. We have a pretty large CRM style app. React Native is a huge help. Since it's just forms and table displays mostly, there isn't a lot of platform specific code we have to create. Maybe 10 or so edge cases where we maintain some differing RN code to make things work well on both platforms.
- jammygit 7y agoHas anyone ever tried a graphics engine for cross playform desktop apps? Godot's interface is made in Godot for example.