Archive for December 19, 2016

Monday, December 19, 2016

Swift: Challenges and Opportunity for Language and Compiler Research

Chris Lattner (PDF, tweet, Hacker News):

That said, many of the things we talked about earlier are actually powered by the LLVM JIT, including the REPL, #! scripts, Playgrounds, and the LLDB debugger. Being able to pick and choose the right compilation model for a specific use case is a strong point of LLVM.

[…]

The compiler can optimize Swift ARC better than (e.g.) a C++ compiler can optimize shared pointers, because the language model explicitly allows early destruction of objects.

[…]

Functions normally take ownership of their arguments, so that call will have to copy each element, incrementing any reference counts inside it.

By simply annotating the argument as borrowed, we can easily avoid that, letting the function decide whether it needs to copy. This annotation also makes this method correct for collections of affine types.

[…]

Async/await are effectively proven at this point and would fit well with the Swift type system and structure, we should probably just do it.

bsaul:

Funny how people here mention source breaking change as the main issue with the language. I think it’s because they haven’t used swift on a large codebase. The main issue once you start to work on a big project are compiler crash and compilation time.

I really don’t understand how a compiler can crash that much ( actually i’ve been coding in many client and server languages before and it’s the first time i see a compiler crashing while i code).

I completely agree. I welcome the source breaking changes because they have made the code much better. But the compiler and editor don’t feel like they’re at a 3.x level of reliability. I don’t have a large codebase.

Sidenote: I encountered lots of PDF bugs in macOS 10.12.2 trying to select and copy/paste text from this PDF.

macOS 10.12.2: SSH Starts Asking for id_rsa Passphrase

I have an id_rsa file set up so that I can SSH and Git into my servers. The SSH keys are protected by a passphrase. ssh-agent remembers the passphrase so I don’t have to keep entering it, and it can get the passphrase from the Mac keychain so that I don’t have to enter it at all. When I updated to macOS 10.12.2, I was suddenly being prompted for the passphrase again. It seems that macOS 10.12 added a new UseKeychain option for ssh, but this didn’t affect me because it defaulted to on. As of macOS 10.12.2, it defaults to off. There was also a change in macOS 10.12 that meant keys were no longer automatically added to the agent. I don’t think this affected me because mine had already been added and I didn’t start using any new servers.

Anyway, to get back to the behavior I like where auto-login works, I set up my .ssh/config file as:

Host *
  UseKeychain yes
  AddKeysToAgent yes

Update (2016-12-22): Apple Technical Note TN2449:

Prior to macOS Sierra, ssh would present a dialog asking for your passphrase and would offer the option to store it into the keychain. This UI was deprecated some time ago and has been removed.

Instead, a new UseKeychain option was introduced in macOS Sierra allowing users to specify whether they would like for the passphrase to be stored in the keychain. This option was enabled by default on macOS Sierra, which caused all passphrases to be stored in the keychain.

This was not the intended default behavior, so this has been changed in macOS 10.12.2. To store passphrases in the keychain, set this option in your ssh configuration file[…]

Golang’s Real-Time GC in Theory and Practice

Will Sewell (via Hacker News):

In this blog post, we’ll look at Go’s garbage collector. We’ll see how it works (the tricolor algorithm), why it works (achieving such short GC pauses), and most importantly, whether it works (benchmarking these GC pauses, and comparing them with other languages).

[…]

The GC still has two stop-the-world phases: the initial stack scan for root objects, and a termination of the mark phase. Excitingly, this termination phase has recently been eliminated. We will discuss this optimization later. In practice we found the pause times of these phases to be <1ms with very large heaps.

[…]

The key takeaway from this investigation is that GCs are either optimized for lower latency or higher throughput. They might also perform better or worse at these depending on the heap usage of your program. (Are there a lot of objects? Do they have long or short lifetimes?)

Update (2016-12-20): Mike Hearn (Hacker News):

The reality is that Go’s GC does not really implement any new ideas or research. As their announcement admits, it is a straightforward concurrent mark/sweep collector based on ideas from the 1970s. It is notable only because it has been designed to optimise for pause times at the cost of absolutely every other desirable characteristic in a GC.

NSRegularExpression and Swift

Nate Cook:

Well, many NSRegularExpression methods use NSRanges, as do the NSTextCheckingResult instances that store a match’s data. NSRange, in turn, uses integers for its location and length, while none of String’s views use integers as an index[…]

[…]

With that in mind, here are a few additions to String that will make straddling the Swift/Objective-C divide a bit easier:

extension String {
    /// An `NSRange` that represents the full range of the string.
    var nsrange: NSRange {
        return NSRange(location: 0, length: utf16.count)
    }

    /// Returns a substring with the given `NSRange`, 
    /// or `nil` if the range can't be converted.
    func substring(with nsrange: NSRange) -> String? {
        guard let range = nsrange.toRange() 
            else { return nil }
        let start = UTF16Index(range.lowerBound)
        let end = UTF16Index(range.upperBound)
        return String(utf16[start..<end])
    }

    /// Returns a range equivalent to the given `NSRange`,
    /// or `nil` if the range can't be converted.
    func range(from nsrange: NSRange) -> Range<Index>? {
        guard let range = nsrange.toRange() else { return nil }
        let utf16Start = UTF16Index(range.lowerBound)
        let utf16End = UTF16Index(range.upperBound)

        guard let start = Index(utf16Start, within: self),
            let end = Index(utf16End, within: self)
            else { return nil }

        return start..<end
    }
}

Hiding Your Action and Share Extensions In Your Own Apps

Aditya Krishnadevan:

In PDF Viewer, we use a UIActivityViewController to share PDFs. This means that our Action extension shows up in the list of actions as well! So a user would see an "Import to PDF Viewer" button inside PDF Viewer. There isn't an easily available API to prevent this from happening. However, the extension's Info.plist does have NSExtensionActivationRule inside NSExtensionAttributes.

[…]

The important bit is AND NOT (ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "your.unique.uti.here"). This ensures that if the UIActivityViewController is created with any items matching your.unique.uti.here, your extension will not be displayed in the list of options. […] Next we need to add an item with a UTI matching your.unique.uti.here to the items passed into the UIActivityViewController.