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

推荐订阅源

Vercel News
Vercel News
The GitHub Blog
The GitHub Blog
博客园 - 【当耐特】
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
D
Docker
GbyAI
GbyAI
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
The Cloudflare Blog
雷峰网
雷峰网
A
About on SuperTechFans
小众软件
小众软件
博客园 - Franky
博客园 - 聂微东
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
C
Check Point Blog
MongoDB | Blog
MongoDB | Blog
G
Google Developers Blog
Microsoft Azure Blog
Microsoft Azure Blog
U
Unit 42
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
V2EX
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
aimingoo的专栏
aimingoo的专栏
量子位
P
Proofpoint News Feed
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
罗磊的独立博客
Martin Fowler
Martin Fowler
D
DataBreaches.Net
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Secure Thoughts
Project Zero
Project Zero
L
LangChain Blog
阮一峰的网络日志
阮一峰的网络日志
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tailwind CSS Blog
S
Schneier on Security
Blog — PlanetScale
Blog — PlanetScale
The Hacker News
The Hacker News
Spread Privacy
Spread Privacy
Security Latest
Security Latest
NISL@THU
NISL@THU
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
C
CXSECURITY Database RSS Feed - CXSecurity.com
J
Java Code Geeks

Comments for Michael Tsai

Michael Tsai - Blog - Dissecting Apple’s Sparse Image Format (ASIF) Michael Tsai - Blog - What to Do With a Hot Mac Michael Tsai - Blog - macOS California Adventure Michael Tsai - Blog - Shutting Down Notion Mail Michael Tsai - Blog - Export Control for Fable and Mythos Michael Tsai - Blog - Mac App Store Search Not Showing Mac Apps Michael Tsai - Blog - Boom Mobile Restructuring Michael Tsai - Blog - “If You Can’t Stand By a Feature, You Shouldn’t Launch It.” Michael Tsai - Blog - Apple Hardware Price Hikes Michael Tsai - Blog - Tony Krueger, RIP Michael Tsai - Blog - WebKit Always Enables the Copy Menu Item in Every App Michael Tsai - Blog - Xcode 27’s Device Hub Michael Tsai - Blog - Swift 6.4 Michael Tsai - Blog - RCS in iOS 27 Michael Tsai - Blog - SwiftData in appleOS 27 Michael Tsai - Blog - Bar None 1.0 Michael Tsai - Blog - CrashReportExtension Michael Tsai - Blog - SwiftUI in appleOS 27 Michael Tsai - Blog - Apple Clearing App Store Clutter Michael Tsai - Blog - Mandatory Apple Intelligence Michael Tsai - Blog - macOS Touch Michael Tsai - Blog - UIKit in iOS 27 Michael Tsai - Blog - Runaway Spotlight With Pages Document on iCloud Drive Michael Tsai - Blog - macOS 27 to Drop Support for AirPort and Time Capsule Backups Michael Tsai - Blog - WWDC 2026 Links Michael Tsai - Blog - SpaceX Acquires xAI, Goes Public, Acquires Cursor Michael Tsai - Blog - Apple Intelligence in appleOS 27 Michael Tsai - Blog - Apple Foundation Models in appleOS 27 Michael Tsai - Blog - Agentic Password Updates Michael Tsai - Blog - Photos AI in appleOS 27 Michael Tsai - Blog - AI-Generated Shortcuts Michael Tsai - Blog - Apple’s Dormant CUPS Michael Tsai - Blog - The End of Pinboard? Michael Tsai - Blog - Anticipating the Coming USB-C iPhone Backlash Michael Tsai - Blog - App Store Personalized Recommendations and Keylogging Michael Tsai - Blog - Safari 27 Announced Michael Tsai - Blog - Apple Creator Studio Now Shipping Michael Tsai - Blog - Rewriting Apple’s TrueType Hinting Interpreter in Swift Michael Tsai - Blog - Rewriting Notion in SwiftUI Michael Tsai - Blog - FastSpring Store Unexpectedly Offline Michael Tsai - Blog - Locked Out of Apple Account Due to Gift Card Michael Tsai - Blog - No Siri AI in EU Michael Tsai - Blog - Siri AI Announced Michael Tsai - Blog - Child Safety Features in appleOS 27 Michael Tsai - Blog - Golden Gate Window Corners Michael Tsai - Blog - Golden Gate Sidebars and Toolbars Michael Tsai - Blog - Golden Gate Menu Icons Michael Tsai - Blog - Liquid Glass 27 Icons Michael Tsai - Blog - Liquid Glass 27 Slider Michael Tsai - Blog - Glow Leopard Michael Tsai - Blog - Xcode 27 Announced Michael Tsai - Blog - macOS 27 Golden Gate Announced Michael Tsai - Blog - iPadOS 27 Announced Michael Tsai - Blog - watchOS 27 Announced Michael Tsai - Blog - WWDC 2026 Keynote Michael Tsai - Blog - Sirius Pomodoro Michael Tsai - Blog - WWDC 2026 Preview Michael Tsai - Blog - Xogot for Mac Beta Michael Tsai - Blog - Where Did SwiftUI Leave You Hanging? Michael Tsai - Blog - Fixing mediaanalysisd Storage and CPU Use Michael Tsai - Blog - Adobe Modifies Your Hosts File for Their Analytics Michael Tsai - Blog - WWDC 2026 Wish Lists Michael Tsai - Blog - macOS Needs Its Spaces Grid Back Michael Tsai - Blog - WhisperPad Rejected From the Mac App Store Michael Tsai - Blog - Restoring Contacts From a Time Machine Backup Michael Tsai - Blog - Bricking Microsoft Office 2019 Michael Tsai - Blog - No Bounty for Mysk Michael Tsai - Blog - fsck_hfs Cache Exhaustion Bug Michael Tsai - Blog - macOS 26.5.1 Michael Tsai - Blog - iOS 26.5.1 Michael Tsai - Blog - BBEdit 16 Michael Tsai - Blog - Nisus Probably Moribund Michael Tsai - Blog - Pair Networks Price Increase Michael Tsai - Blog - Taphouse 1.5 Michael Tsai - Blog - More App Store Ad Spots Michael Tsai - Blog - StopTheMadness Pro 26 Michael Tsai - Blog - Mac External Display Support Reference Michael Tsai - Blog - Bartender Pro Michael Tsai - Blog - Iris 1.0 Michael Tsai - Blog - Halide Mark III Michael Tsai - Blog - !Camera Michael Tsai - Blog - Project Indigo Michael Tsai - Blog - Unpro Camera Michael Tsai - Blog - MailMate License Model: One Year Later Michael Tsai - Blog - Iris Rejected From the App Store Michael Tsai - Blog - OpenAI Model’s Proof of Erdős Unit Distance Problem Michael Tsai - Blog - Apps for YouTube℠™®•! Michael Tsai - Blog - Google’s Intelligent Search Box Michael Tsai - Blog - Catalina Data Protections Break File Sharing Michael Tsai - Blog - Apple Asks Supreme Court to Review Epic Ruling Michael Tsai - Blog - Stats Visualization in Apple Sports Michael Tsai - Blog - Steve Jobs in Exile Michael Tsai - Blog - Leaving CloudKit Michael Tsai - Blog - Lawsuits Claim OpenAI and Perplexity Shared User Data for Advertising Michael Tsai - Blog - Inkwell Rejected From the App Store Michael Tsai - Blog - Updating Shared Shortcuts Michael Tsai - Blog - Claude Desktop App Michael Tsai - Blog - OmniFocus 4.8.10 Michael Tsai - Blog - Chrome’s Huge weights.bin File Michael Tsai - Blog - Gemini App for Mac
Michael Tsai - Blog - ARC Overhead in Swift Sorting
Michael J. Tsai · 2026-05-29 · via Comments for Michael Tsai

Sean Heber:

I made a function in Tapestry 23x faster today by sorting an array using its indices instead of using its data directly. Like this:

let unsorted = items
var indices = Array(unsorted.indices)
indices.sort { a, b in unsorted[a].thing > unsorted[b].thing }
items = indices.map { unsorted[$0] }

Versus presumably something like:

items.sort { a, b in a.thing > b.thing }

With Objective-C, at least pre-ARC, this was simple. The array owns the objects, and they do not get retained and released when passed to your comparator, or within it. Unless you do something silly, like removing objects from the array during sorting, it will be safe and have no memory management overhead.

With Swift, I find the situation rather confusing, and I was not able to find any documentation that lays out exactly what happens. Various searches and AI prompts turned up all sorts of conflicting information. Gemini, in particular, had some explanations that sounded reasonable but that I began to doubt because the sources that it linked to did not actually say what it claimed. I’ve tried to figure this out, but it may well be that some of my conclusions are wrong.

There are several things going on:

  1. Swift will insert retains and releases for the closure parameters. I can see this in the disassembly and by setting breakpoints. I think this is only because they’re accessed within the closure. They don’t need to be retained by the caller because the closure is non-escaping.

  2. If the optimizer is enabled, Swift can sometimes remove that retain counting. I’m not sure exactly when this happens. In my tests, where everything is defined in the same module, it worked for both classes and structs, but I get the impression that sometimes the optimizer is not able to remove the ARC traffic. This is a longstanding frustration with Swift, that the behavior under optimization can be wildly different and that it’s not obvious when you’re changing something in the code that defeats a crucial optimization.

  3. There can also be ARC traffic from the non-comparator aspects of the sorting. Values need to be moved and sometimes copied into temporary buffers, since Swift uses a complex sorting algorithm that does merging as well as swapping. Some of this seems to be done at a low level to avoid ARC, but at least for structs I don’t think it can be totally avoided.

  4. Swift also has exclusivity checks, which can detect (at runtime) if you’re modifying the array from inside the closure. So safety is somewhat decoupled from memory management.

Heber was sorting large structs and saw overhead related to properties that were not accessed in the closure. I’m not sure whether this was due to #1 or #3 or both. In any case, switching to indices adds (linear) overhead from creating two additional array buffers, but it reduces other types of ARC overhead because only integers are passed as parameters and moved around during sorting.

Is there a way—other than using indices—to guarantee the minimum ARC traffic? Swift now supports explicitly marking parameters as borrowing. That seems like conceptually the right idea. It directly expresses that the elements are owned by the array and so don’t need to be retained at other levels. But I don’t think it helps here. For #1, I think the parameters are already essentially borrowed, and it doesn’t address the overhead from #3. Also, the caller (sort) is not typed as taking a closure with borrowed parameters. Changing the closure wouldn’t change its behavior.

I also wondered whether it would help to use one of the other built-in sorting methods. With Comparable, you can avoid passing in a closure. But if the closure isn’t capturing anything, the signature seems identical to that of < in other respects. Still, maybe there are cases where the compiler would be able to see through more for certain Comparable types?

KeyPathComparator also seems promising in that more of the work happens internally. Maybe this could be optimized as the language evolves to do things that are not possible with normal functions/closures. But, so far, I think it’s mostly just syntactic sugar. In my tests, it still retained and released a lot with optimizations disabled.

Lastly, there’s the option of the Schwartzian transform. This can reduce the computational overhead during each comparison, e.g. if thing is a computed property. It needs extra space for a temporary array, but if you’re already making one for the indices trick, you can use the same one, just wider to store pairs.

Unfortunately, I don’t have a very satisfying conclusion except that I would be skeptical about trying to reason from first principles how the complete system will behave. I think you need to profile to see what’s actually happening. Even that’s easier said than done because the sorting algorithm switches between different modes based upon the size and character of the data.

Previously:

2 Comments