Archive for December 31, 2021

Friday, December 31, 2021

AirPrint Drivers Can Cause Reduced Print Saturation

Adam Engst:

He uses a Canon imagePROGRAF PRO-1000 printer designed for professional photos and fine art—this is a serious printer. After a recent upgrade odyssey from Mojave to Catalina to Big Sur, Charles started seeing problems with his printouts lacking sufficient color saturation when printing from Photoshop. His research turned up a helpful page by color management consultant Phil Cruse that points the finger at Apple’s AirPrint drivers. (Printouts made from Preview—which can open Photoshop files—were fine, suggesting this is an Adobe/Apple conflict.) Charles followed the instructions and thought he had removed the AirPrint drivers, but the problem persisted. After some discussions with Phil Cruse, Charles realized that he had set up the printer again as a Bonjour printer, which evidently uses AirPrint. Since the printer sits on his Ethernet network, he was able to set it up again as an IP printer with a static IP address, after which the saturation in his prints finally returned to normal.

[…] I tried using Photoshop to print the same photo using different printer drivers while having Photoshop do color management using the same color profile. I can’t confirm the fix that Charles found, but I can say that the prints were quite different.

Siri Can No Longer Rate Songs

Jean Leon:

Rating songs serves as a sorting method for the user’s music library. In this way, you can sort your songs according to the ones you like the most.

Apple made it easy to use this feature with support for Siri voice commands. Then, users can rate their music even without having to touch their phones. But, this is not working properly now.

Via Andrew Abernathy:

[…] a big loss for me, especially as AFAICT there is no API on iOS for rating songs, so no apps support it. I have a large library, mostly rated, and I use those ratings; I wish Apple hadn’t become so hostile to it.

Previously:

Update (2022-01-03): Tim Hardwick:

Yet reports on Reddit, Apple Support Communities, and the MacRumors forums suggest that the function is not available in iOS 15 or iOS 15.1, and has remained out of action in the latest iOS 15.2 point release, issued in December. Instead of carrying out the request, Siri responds with “I’m Sorry, I’m afraid I can’t do that,” or some variation thereof.

It’s unclear if this is an intended change by Apple, or an intermittent server-side problem that has arisen since the release of iOS 15 , but it’s worth noting that iOS 15 and iOS 15.2 both made functional changes to Siri , in relation to Apple Music interoperability and more generally at the system level.

Lightweight Dependency Injection Using Async Functions

John Sundell:

What if we could actually make our code fully testable in a way that doesn’t require us to introduce any new protocols, mocking types, or complicated abstractions? Let’s explore how we could make use of Swift’s new async/await capabilities to make that happen.

[…]

One thing that’s very neat about the above pattern is that it still lets us keep using our existing Networking and ProductLoader code just like before — all that we have to do is to call that code within the reloading function/closure that we pass into our ProductViewModel when creating it[…]

Previously:

The Surprising Cost of Checking Protocol Conformances in Swift

Noah Martin (Hacker News):

The entry point to our investigation is Mike Ash’s PR which implements a 13x faster cache that was released in Swift 5.4.

[…]

We now see that the speed of protocol conformance lookups is dependent on the number of conformances in your app. This will be influenced by how many Swift libraries you link to, and how many conformances you include in your own code. otool -l Helix.app/Helix | | grep _swift5_proto -A 4 tells us Uber’s app has a 411200 byte protocol conformance section. Each 4 bytes is a relative pointer so 411200 / 4 = 102,800 conformances.

[…]

One source of low hanging fruit that might be in your app is removing protocols that are used only for providing stub implementations in unit tests. These can be compiled out of release builds of the app to avoid them being included in runtime metadata.

[…]

Profiling your app using tools like Instruments or the Emerge startup time visualization can help you identify where conformance checks are most often used in your app. Then you can refactor code to avoid them entirely.

[…]

The concept behind zconform is to eagerly load all possible protocol conformances and store them in a map keyed by the protocol’s address in memory.

Previously:

Update (2022-01-03): Checking protocol conformances can also be a bottleneck in Objective-C.

Update (2022-02-08): Saagar Jha:

This appears to have been fixed in Xcode Version 13.3 beta (13E5086k). There’s a new DVTCachedConformsToProtocol method that is now used extensively throughout the app for conformsToProtocol: checks, including for the specific block I originally identified as being problematic.

Greg Parker:

Protocol conformance is one of those things that is never quite high enough priority to optimize in the OS. But some apps really do suffer, so they’re forced to work around it. Then the presence of those workarounds makes it less important to improve it in the OS.

Update (2023-02-16): Noah Martin:

The big change [in iOS 16] comes in the “dyld closure”, which is a per-app cache used to accelerate various dyld operations during app launch. The closure now contains pre-computed conformances, allowing each lookup to be much faster. Note that the dyld closure is not always used, e.g. because it’s out-of-date or because it’s being launched from Xcode, which complicates things.

Michael Eisel:

Beyond the issues mentioned above, the Salesforce Service Cloud SDK spends 67ms running class_conformsToProtocol and objc_copyClassList (perhaps iterating over all classes to determine which ones conform to some protocol) in non-initializer setup. All of this setup can likely be moved out of startup.

Noah Martin:

Although this improvement is in iOS 16, it’s difficult to measure in practice because this dyld behavior is disabled when running the app from Xcode or Instruments. Emerge has a local performance debugging tool that works around this and can be used to profile apps that do have access to the dyld closure.