This is the historical English version of Yingyun’s article. See the Chinese original or the English-site version.
1 Origin
I am starting a series about the decisions involved in OS architecture. The same questions arise when designing other large software systems too.
My knowledge and experience have limits, and these views are subjective. There will be gaps. I would like to hear other views and see what I have missed.
Technical review: 2026-10-14. This article retains Yingyun’s 2023 views on architectural trade-offs and developer ecosystems. Technical sections clarify kernels, memory reclamation, and background execution with version-specific updates. Platform preferences and forecasts are historical opinions, not comparative measurements of current releases.
In my opinion, the core differences between Android and iOS from the OS perspective are primarily manifested in:
- The IPC mechanism between applications and core services
- Platform development environment, including programming languages, IDE tools, and the construction of the developer ecosystem
- Application lifecycle management mechanisms and strategies
- The runtime organizational structure of the kernel and core services
Why do they adopt different strategic decisions? It relates to the factors considered during architectural design. A software architectural decision is a selection of the most suitable decision for the present and foreseeable future amidst a series of current considerations; it is a collection of decisions. Thus, there’s no absolute right or wrong in architectural design, or rather, rational or irrational. Different projects and decision-makers face different considerations and prioritize different aspects. If architects of similar skill levels switch scenarios, they are likely to make similar decisions. This indicates that architectural design is an engineering process and a technical craft, learnable and following certain patterns.
The challenge in architectural design lies in accurately understanding the environment the organization operates within, current and foreseeable considerations, and finding the most suitable methodologies or tech stacks from existing engineering practices. It is evident that considerations play a significant role. What factors need to be considered in software architectural design? These include, but are not limited to, testability, component release efficiency, development efficiency, security, reliability, performance, scalability, etc. Experienced architects, especially those with operational experience in similar businesses, are better at discerning what to focus on at different times, what must be adhered to, and what can be relaxed or even abandoned. Considering the law of diminishing marginal returns, the consideration of influencing factors and decision-making behavior will permeate the entire lifecycle, introducing another art of decision-making.
We can summarize that:
- Under different stages and constraints of various considerations, software architectural designs on different projects may differ.
- During the entire cycle of software product iteration, such design decisions are always evolving.
Interestingly, one consideration may conflict with another, leading to a situation where one cannot have the best of both worlds. For example, improving component development efficiency might impact program performance. So, what were the considerations for the designers of Android and iOS in the context of mobile OS design? To answer this question, we first need to explain the relationship between the OS, application programs, and the kernel.
2 Mechanisms and Policies
The OS and applications form a software stack above the hardware. Kernel code normally runs in a privileged CPU mode for tasks such as scheduling, memory management, and interrupt handling. Many system services run in user space with particular permissions; the entire OS does not run in kernel mode. Apps access these capabilities through system calls, IPC, and framework APIs.
At a higher level, from the user experience perspective, application programs, OS, and hardware are all part of the same entity. When issues arise in their collaboration, ordinary consumers might simply feel that the device is less than ideal. Therefore, all three parties are obligated to cooperate and facilitate each other; only when the consumer is well-served can these entities sustainably profit.
In discussing the OS, it’s crucial to recognize that the vast majority of modern OSes consist of a kernel and system services.
- macOS/iOS use the XNU kernel, which combines Mach, BSD components, and IOKit. XNU is part of the Darwin operating-system foundation; Darwin is not a kernel formed by placing XNU beside Mach. User-space daemons and frameworks provide further services. See Apple’s XNU overview.
- Android uses the Linux kernel. SurfaceFlinger is a native system-service process; system_server hosts many Java framework services and also uses native components. Neither is the kernel itself.
Current mainstream operating systems include macOS, Windows, and various derivatives of Linux. Clearly, Android belongs to the Linux derivatives, with another renowned version in the developer community being Ubuntu. Due to the complexity and path-dependent nature of a complete OS, derivatives are often deployed on different hardware and application scenarios. For a while, people liked to point out how many kinds of devices ran Linux and how widely it was used. However, being able to run an OS and running it well—connecting hardware and application programs to offer an optimal user experience—are two different things.
An increasingly common understanding is that the OS’s mechanisms, policies, and closely associated application programs vary greatly depending on the application scenario.
For instance, even if based on the same Linux kernel, the use and system services built upon it for embedded devices, smartwatches, smartphones, large servers, or even smart cars are distinctly different, as are the operating strategies of application programs. The Linux kernel and device drivers can be seen as the bridge between hardware and system services—a standard bridge—but the vehicles and pedestrians traversing it are entirely distinct.
This leads to another classic OS design concept: mechanism and policy.
The Art of Unix Programming describes separating policy from mechanism and interfaces from engines. Mechanism provides a capability; policy decides how to use it.
The boundary depends on the level of discussion; an entire scheduler or filesystem contains both mechanisms and policies. For example, the kernel provides scheduling and frequency-control facilities, while policy uses workload and foreground/background information to choose resource allocations. A governor selects performance targets and a driver performs supported transitions. DVFS describes voltage/frequency scaling; predicting demand and choosing targets are policy decisions. See Linux CPUFreq’s governor/driver separation.
Memory compression is used by many systems, but it is not a requirement for every modern OS. Apple’s WWDC 2018 memory discussion describes the page-based compressor introduced in iOS 7; this does not mean compressing an entire process into one object. Android commonly uses Linux zRAM as a compressed in-memory swap device. Compressed pages still occupy RAM, and compression/decompression costs CPU time. Policies and any additional backing storage depend on the device.
Though OS mechanisms might be similar, policies are diverse. The extent of their differences depends on the OS designers’ understanding of their own business—meaning the application programs running on the OS and the kind of experience and services they aim to provide users. The original desktop analogy concerns background-execution freedom; it does not mean Android was originally a desktop OS. Whether a vendor policy better suits a mobile device depends on its version and workload.
The OS for smartphones and smart cars probably faces a similar scenario—they cannot be directly transplanted.
One interesting aspect of policy is that implementing one policy often brings up another issue, necessitating the introduction of an additional policy. When one policy compensates for another, a chain forms, eventually creating a closed-loop mechanism. In other words, all policies must be in effect simultaneously to maximize the system’s benefits. When learning about a competitor OS’s policies, remembering this aspect is essential; otherwise, we might only grasp the superficial aspects, leading to “negative optimization” once the features are launched.
Now, narrowing it down to Android and iOS, where do their strategy designs originate?
3 Butts Decide Heads
Apple’s operating systems share parts of their foundations but differ in background-execution, interaction, and resource policies. Both iOS and macOS support multitasking. iOS places stricter limits on ordinary third-party apps in the background; it does not lack “real” multitasking. The comparison here concerns product policies.
AOSP (Android Open Source Project) is Android’s open-source foundation; shipped products may also include vendor components and separately licensed services. Device manufacturers adapt AOSP and integrate their services based on their business models and understanding of target users. Apple is singular, but there are numerous device manufacturers, each with their own profit models and interpretations of user needs. They modify AOSP accordingly, and the market decides which version prevails.
AOSP already contains resource and lifecycle policies, including JobScheduler, Doze/App Standby from Android 6.0, lmkd, and the cached apps freezer from Android 11. These policies are not all implemented in GMS. GMS is a separately licensed collection of apps and cloud services outside AOSP. Vendors can further adapt the platform; comparisons need specific devices, versions, and workloads.
Given Google’s less-than-ideal strategic implementation, domestic manufacturers in China have carved out space for themselves. The intense competition and the sheer volume of phone shipments in mainland China have led manufacturers to prioritize consumer feedback and innovative adaptations of AOSP.
So if a boss tells you, “Making a phone is easy—just combine open-source Android with a vendor platform,” my advice is to keep your distance. You could waste years working under that assumption.
This article focuses on policy differences rooted in product objectives. Kernel, IPC, runtime, and framework differences also matter; performance differences cannot all be attributed to policy.
The verifiable timeline is that Apple announced third-party Web apps in June 2007, then released a native iPhone SDK beta and introduced the App Store in March 2008. The SDK included Xcode, Interface Builder, and Instruments. The original article discussed motives through the Jobs biographies, but it supplied no performance evidence that XNU overhead made third-party applications impossible. That causal claim should not be treated as a technical finding.
As Apple had written the first batch of apps themselves, they amassed a wealth of insights on designing excellent embedded device applications, leading to the creation of effective API systems. This comprehensive approach from hardware to software was not for the sake of exclusivity, but a necessary path to crafting the best user experience.
My view when writing in 2023 was that the early Eclipse tools had been adequate, but comparison made their shortcomings harder to ignore. Android Studio was a big improvement, helped by IntelliJ. I still preferred Xcode for application development and performance debugging: finding slow code felt easier, and the process was more pleasant. That is my experience of those tools at the time.
Java offered a mature ecosystem and portability; its exact market rank depends on the measure used. Early Android used Dalvik, while ART became the default in Android 5.0 (API 21). They were not one VM designed together in 2007. Chet Haase’s Androids: The Team That Built the Android Operating System covers the early team. Google’s December 2007 SDK update already describes an Eclipse plugin; public SDK tooling was not limited to command-line tools.
I consider Apple’s developer tools one part of its ecosystem advantage. This is a 2023 assessment, not a current feature or performance ranking of Xcode and Android Studio. LLVM also needs distinct attribution: it originated in research at the University of Illinois, with Apple later contributing; it should not be grouped with Swift and SwiftUI as an entirely Apple-originated project. See the University of Illinois history.
The purpose of designing an OS is profit-oriented, and it should facilitate app developers in crafting quality programs. Apple has showcased that offering quality developer services can be instrumental in achieving optimal device experiences. A summary of insights gleaned from Apple’s approach includes:
- Building an OS is a means; delivering a complete and excellent experience is the end goal. Both the OS and device manufacturers may need to put in extra effort to achieve this objective.
- Serve app developers well, assist them in improving app quality, and even identify and diagnose app issues.
- Provide faster and more user-friendly APIs to efficiently meet the needs of app developers.
- An excellent IDE tool can serve developers well, enabling the development of superior apps, and ensuring the OS’s survival.
While Apple exercises absolute control, it also offers software services that are significantly above industry standards. Offering an OS is merely a means; understanding the nature of the relationship with developers and providing developer services, such as IDE, is a more profound consideration at the cognitive level.
4 Strategy of “Overload Protection”
The greatest feature of mobile devices is their portability, enabled by battery power. Besides, as handheld devices, they primarily rely on passive cooling since they don’t have an active cooling mechanism (exceptional cases of gaming phones and attachable fans aside). Currently, there are two trends: one, the transistor fabrication process is inching closer to its physical limit, and two, more functionalities are being integrated into a single chip. Actual heat depends on workload, voltage, frequency, fabrication process, and power management rather than transistor count or area alone, although it wasn’t a primary concern during the early days of smartphones. Now, the balance between power consumption and performance has become a significant challenge for smartphones.
More runnable threads can contend for CPU time, and frequent wake-ups can increase energy use. Total thread count, actual CPU time, and user-visible latency are different measures. Desktops and servers also enforce resource controls; mobile products put particular weight on battery life, temperature, and interaction latency.
Java OutOfMemoryError, lmkd under system memory pressure, and the Linux kernel OOM killer operate at different levels. A managed-heap allocation failure can throw OOME; an unhandled error can crash the app. This is not simply a system kill when the heap crosses a threshold. lmkd instead considers memory pressure and process importance. Android 10 supports PSI-based detection, and Android 11 revised the reclaim policy.
CPU accounting is not divided by Java versus native code. Android 13 AppProfiler accumulates process user and kernel CPU time; ActivityManagerService applies process-state, observation-window, and threshold checks when handling excessive CPU use. Accounting scope and termination policy are separate; native threads are not inherently excluded.
iOS diagnostics also need to be separated by mechanism rather than described as a list of guaranteed kills:
- EXC_RESOURCE can concern CPU, wake-ups, memory, or disk writes.
NON-FATAL CONDITIONmeans the report did not terminate the process on that occasion. - Jetsam reports describe process reclamation under memory and related pressure.
vnode-limitconcerns system-wide vnode exhaustion;fc-thrashingconcerns file-cache thrashing. A background app selected for reclamation need not have caused the pressure. - A watchdog termination concerns time limits for responsiveness or lifecycle operations, not the same threshold as a resource exception.
- Background tasks have API-specific completion and expiration requirements. Thermal protection can also apply, but a warmer device does not mean every app is immediately terminated.
Use the actual diagnostic report, hardware, and OS version to identify a termination. Example limits are not universal quotas across iOS devices and releases.
Vendors add resource controls to protect the user experience. But if the rules are undocumented and developers cannot find out why their app was terminated, how are they supposed to fix it? That is the part I object to.
Android 11 (API 30) added ApplicationExitInfo for historical process-exit information. Coverage varies: not every device reports REASON_LOW_MEMORY, and a trace is not always available. Vendor details can still be incomplete, but it is inaccurate to say developers have no exit information at all.
Consequently, application developers resort to various tricks to keep their applications alive and bypass the system’s detection mechanisms. What should have been a collaborative ecosystem building effort has turned into a battleground. In the end, both parties suffer, with consumers bearing the brunt of the damage.
In an ideal world:
- Overload protection mechanisms should be documented and explained in application development guides.
- Debugging information context should be saved when the system executes overload protection, and developers should have access to this information (with specific permissions, scope, and validity to be determined).
- Manufacturers should provide convenient and user-friendly debugging tools for developers to fix issues locally during development.
- Developers should be mandated to fix issues when they exceed the quality standards set by the manufacturers, failing which their applications should be delisted.
Manufacturers and developers should be partners. Manufacturers may need to do more to assist developers, as many capabilities are exclusive to them. Blaming developers solely for poor quality is not a competitive approach for manufacturers.
I think that approach starts from the wrong idea about the relationship.
5 Strategy on “Lifecycle Management”
Device categories use different lifecycle policies. Desktop apps generally have more scope for continuous execution, but users, crashes, memory pressure, shutdown, and administrative policies can end them. Desktops, servers, and laptops also face power, thermal, and resource limits; an app does not wholly control its lifetime.
On the contrary, smartphones are a different story due to their limitations in power consumption and heat generation. Similarly, smartwatches also suffer from these restrictions but to a more stringent degree. No one desires a watch that heats up their wrist and cannot last a day on a full charge. Moreover, their performance and memory limitations mean that too many apps can’t remain active in the background, necessitating a centralized management module to uniformly implement services for most common applications, known as a hosted architecture. Vehicles also face computing, power, thermal, and standby-energy constraints. Different controllers have their own sleep, wake, and reliability requirements; the whole vehicle is not one continuously running system until power is removed. Resource leaks and recovery remain important for long-lived services.
iOS normally suspends ordinary execution after an app moves to the background. A suspended process does not execute code, but suspension is not termination. The original “five seconds” refers to the applicationDidEnterBackground return deadline, not a universal allowance for every background API. Specific modes and task grants have their own rules.
The original vendor comparison reflects a 2023 observation, not evidence about the following two or three years. AOSP does support freezing: the cached apps freezer has existed since Android 11 (API 30), using a kernel cgroup freezer to stop eligible cached processes while retaining their memory. Android 14 revised related cached-process and broadcast behavior. Enablement, exemptions, and timing depend on the OS, kernel, and device configuration. A process doing supported background work or hosting a foreground service is not necessarily eligible for cached-process freezing.
If an app is suspended in the background, how can it do the work that still needs doing? iOS offers several mechanisms, not one BackgroundTask permission:
- UIKit
beginBackgroundTaskrequests limited finishing time for important work already started in the foreground. End it promptly and handle expiration; it is not a periodic scheduler. BGAppRefreshTask, available from iOS 13, supports short refresh work scheduled by the system, with up to about 30 seconds of runtime.BGProcessingTask, also from iOS 13, supports longer processing. It can run for minutes but can be interrupted; it has no universal fixed 30-second allowance.- iOS/iPadOS 26 adds
BGContinuedProcessingTaskfor user-visible work that starts in the foreground and continues in the background. It must report progress; the user can cancel it, and resource constraints can end it.
See background strategy selection, BGProcessingTask, and BGContinuedProcessingTask. The system chooses scheduling and budgets. There is no fixed daily count for every app or guaranteed periodic interval. Handle expiration, preserve progress, and report completion.
Background work also includes playing music, tracking location, and transferring files. How are those handled? They have distinct capabilities, permissions, and APIs. App Store review governs distribution; on-device OS mechanisms decide execution, suspension, and reclamation. The store is not the runtime scheduler. Memory pressure can terminate suspended processes, but reclamation also includes discarding caches and compressing memory rather than only killing processes.
What if the process has been terminated altogether—how does it run tasks or receive messages then? After system termination, eligible tasks may launch an app in the background, but this is not unconditional. User force-quit also differs from system reclamation; see Apple’s background execution limits. Distinguish system-displayed visible notifications, silent background-update notifications, and VoIP pushes for real incoming calls.
Background notification delivery and wake-up are not guaranteed and can be throttled. Background work is not limited to a notification tap or VoIP. PushKit VoIP notifications serve incoming calls; apps built with the iOS 13 SDK or later must follow the documented CallKit integration, not use them as a general keep-alive channel.
Android background scheduling and push delivery are separate. JobScheduler has provided platform job scheduling since API 21, and WorkManager does not require Google Play services. Neither is simply a GMS feature or permission for permanent process residency.
The standard FCM Android client requires the corresponding Google-services environment. Vendors also offer channels such as HUAWEI Push Kit. Device coverage, delivery, and execution rules differ. Lack of GMS does not technically require permanent app processes, and adding RAM is not the only possible response. My argument remains that vendors and app developers need to build the ecosystem together, instead of each solving only their own part of the problem.
Looking at iOS’s design, compared to macOS, it restricts application freedom but isn’t a one-size-fits-all solution. It offers various “windows of opportunity” or “unified solutions” to cater to different developers’ needs. The objective is to allow developers to operate within reasonable boundaries, not to drain users’ battery and performance.
Summarizing the principles beyond the technology:
- Mobile devices have many constraints; therefore, application “freedom” must be restricted but not completely cut off, requiring corresponding solutions.
- Common tasks among applications should be provided uniformly by the system, saving overall system load, especially crucial for devices with many constraints.
- The final execution power of a program should be determined by the system, which, after synthesizing various information, schedules uniformly, benefiting the ultimate user experience protection.
At this point, it seems like a clash between two regimes: one valuing freedom and individual priority, and the other advocating unified arrangement and scheduling. Regardless of the regime type, the ultimate objective must be considered. If the aim is to offer the best device user experience, evidently, the latter regime has been proven right by the market.
6 Above Design
Specialized accelerators can improve efficiency for particular workloads, as seen in GPUs, media codecs, and machine-learning engines. They do not imply that general-purpose CPUs have stopped improving or that every program benefits equally. DSA (Domain-Specific Architecture) tailors hardware and software interfaces to a domain. The idea that DSA would dominate the next decade’s gains is retained as the author’s 2023 forecast, not a verified prediction.
The 2020 M1 combines CPU, GPU, Neural Engine, and media encode/decode engines. Accelerator benefits depend on the task, format, and software path. A blanket claim that it outperforms Intel chips ignores generations, power limits, and workloads. This article provides no controlled benchmark; the example illustrates architectural specialization rather than a platform ranking.
However, this doesn’t signify the end of the road for performance enhancements based on CPUs. As relying on CPU upgrades alone becomes insufficient, precise understanding of demands and optimizations of matrices and architectural designs to boost performance on existing CPUs become imperative. Profound insights into hardware, compilers, algorithms, and operating systems (both frameworks and kernels) are increasingly crucial. After optimizing business codes to a certain extent, focus inevitably shifts towards the underlying layers.
Failures teach you where a design needs support. By an “optimization matrix,” I mean the related pieces that have to work together: the OS, developer tools, cloud services, and the decisions connecting them. Providing a good experience is difficult, but the more I learn, the more work I can see to do. I want to stay aware of what I do not know.
The people designing the system need to understand those connections too.
Munger’s advice was to look beyond financial statements and price charts when investing, and learn from psychology, sociology, politics, biology, and other fields. I value that approach to learning across disciplines. I have not reached the breadth of understanding I am describing. Studying outside my specialty and writing down what I learn are ways to work toward it.
“I leave my sword to those who can wield it.” - Charlie Munger
About Me && Blog
- About Me: I am eager to interact and progress together with everyone.
- Follow me on Twitter
- Blog Content Navigation
- Record of Excellent Blog Articles - Essential Skills and Tools for Android Performance Optimization
An individual can move faster, a group can go further.