Archive for March 9, 2018

Friday, March 9, 2018

Solving a Mysterious Heap Corruption Crash

Agnes Vasarhelyi (tweet, via Alexis Gallagher):

I removed every third-party dependency, to exclude the possibility that the problem is not in our code.

[…]

Move suspicious pieces to an empty project

[…]

The code was fairly slim at this point - a few thousand lines of parsing 3D models into all kinds of data structures. Nothing concurrent, everything running synchronously. I wanted to try and look at the crash site again. Even though I knew the cause of the heap corruption could be elsewhere, seeing the stack trace in the same piece of code every time made me want to look closer there.

The pattern I started to see was that there was always a Dictionary involved, and there was always a simd type such as double3 in the dictionary.

[…]

But what if.. what if it’s really a Swift bug? 🙀

[…]

When their elements had unusually wide alignments, storage for the standard library’s collection types was not guaranteed to be always allocated with correct alignment. If the start of the storage did not fall on a suitable address, Dictionary rounded it up to the closest alignment boundary. This offset ensured correct alignment, but it also meant that the last Dictionary element may have ended up partially outside of the allocated buffer — leading to a form of buffer overflow. Some innocuous combination of OS/language/device parameters probably caused this issue to trigger more frequently — which is probably why it became noticeable on particular devices running iOS 11.

Update (2018-03-23): Greg Heo (via Agnes Vasarhelyi):

The tail-allocated size is sufficient, but the system didn’t take alignment into account. The alignment boundary we need is not at the start of the tail allocation.

The result? A buffer overflow. Corrupted heap. 💥

Faster Swift String Concatenation

Nick Lockwood:

I’m sure I heard somewhere that "\(foo)\(bar)" is the recommended way to do string concatenation in Swift, but I benchmarked it and it’s almost 100x slower than using + or String.append().

I know I’ve heard that as well. I assumed it was taken as a hint to figure out the proper allocation size up front. But currently it’s slower because the interpolated elements are not assumed to be strings.

Joe Groff:

Yeah, \(x) goes through the print-anything path for x, which hasn’t really been optimized

Steve Barnegren:

I thought that the recommendation to use "\(foo)\(bar)" over + was more for compilation performance than runtime performance, as the compiler has to work to understand which + operator to use.

Joey Devilla:

Running on the phone, the + method is almost 70 times faster, which is a significant difference when concatenating a large number — 100 million — strings. If you’re concatenating far fewer strings, your better bet is to go with the option that gives you the more readable, editable code.

Marcel Weiher:

A factor 100 here, a factor 100 there, soon enough… ¯\_(ツ)_/¯

Nick Lockwood:

A lot of people have jumped on this to criticise Swift’s maturity as a language.

To put it in context, even at 100x slower, you can still comfortably perform 500,000 string concatenations per second. In most apps this would be a complete non-issue.

Update (2018-03-10): Nick Lockwood:

Deleted this, since it was due to a misconception on my part.

His original test measured foo = "\(foo)bar" vs. foo += "bar", which is not what I would have expected from the tweet’s description. The latter is 100x faster because Swift is able to mutate the string rather than create a new one. The benchmark code is here.

I measured baz = "\(foo)\(bar)" vs. baz = foo + bar, which is what I thought he was originally talking about (i.e not building up a giant string), and found the latter to be about twice as fast, perhaps because of the overhead that Groff mentioned.

Devilla measured newString = "\(string1) \(string2)" vs. newString = string1 + " " + string2 and found the latter to be 70x faster. I tried to reproduce this but found less than 10% difference in the opposite direction. In other words, interpolation was slightly faster. However, I am using Swift 4, and he was using Swift 2.

Your Nose Isn’t Really As Big As It Looks in Selfies

Rachel Becker:

Last year, more than half of plastic surgeons were approached by patients who wanted to look better in selfies, according to a survey by the American Academy of Facial Plastic and Reconstructive Surgery.

[…]

Most smartphone cameras have wide-angle lenses, says The Verge’s creative director James Bareham, and close-ups with wide-angle lenses cause distortion that makes objects closer to the camera — like, say, a nose — look larger. “It’s kind of one of the basics of photography: don’t shoot portraits on a wide-angle lens because you will look terrible,” Bareham says.

Old Steve Jobs Videos

MIT (via Thomas Brand):

Steve Jobs, one of the computer industry’s foremost entrepreneurs, gives a wide-ranging talk to a group of MIT Sloan School of Management students in the spring of 1992. Jobs shares his professional vision and personal anecdotes, from his role at the time as president and CEO of NeXT Computer Corporation, to the thrilling challenges of co-creating Apple Computer, and subsequent disappointments at his ousting. In conversational exchanges with audience members Jobs underscores the value of direct experience in the field, and “developing scar tissue.”

ABC (via Farhad Manjoo):

Ted Koppel, Bettina Gregory, and Ken Kashiwahara present news stories from 1981 on the relevancy of computers in every day life and how they will affect our future. Included are interviews with Apple Computer Chairman Steve Jobs and writer David Burnham.

Photoshop CC Easter Eggs

Michael Zhang (via John Nack):

Did you know that hidden within Photoshop CC are a number of “easter eggs” that customize the photo editing app in wacky ways? Three that you can activate in the latest version of Photoshop CC are “Layer Monkey,” the “Banana Toolbar,” and “Coffee & Toast.”

Here’s a quick look at how you find each one (keep in mind that these are entirely for fun, i.e. completely useless)[…]