
Performance These Days - mpweiher
http://inessential.com/2016/04/21/performance_these_days
======
nasalgoat
I'm afraid I have to disagree with the basic premise of this article and say
that app performance matters more than developer performance.

Improving the sign-up funnel speed on our app by one second resulted in a 11%
increase in signups. People are impatient and lazy, and everything you do to
improve app performance will improve sign ups, retention, app store reviews
and the perceived quality of your app.

The point isn't to get apps or new features out as quickly as possible, it's
to make a quality product and the speed of your app is critical to that.

~~~
kenferry
I don't think you're catching the basic premise here. Brent is suggesting that
when you're writing code targeting iOS or the Mac, the majority of time spent
is within the system libraries (in most situations). So the language of the
driver code (i.e., your stuff) doesn't have much impact on app performance.

~~~
rlander
You're correct, and that's the same excuse Ruby and Python advocates use when
developers complain about performance. Frankly, it's bullshit.

Take Rails as an example. In 2006 we were told that Ruby's slowness didn't
matter since web apps spend most of the time waiting for IO, processors were
getting faster, yada yada yada.

Guess what? 10 years later and Rails is still slow. Django is also slow.
Template rendering is slow. I've written enough Erlang, Clojure and OCaml apps
to know that no, I don't need "russian doll caching" in a fast language. Hell,
I rarely need caching at all. My database layer is fast enough. /rant

~~~
meric
I'm Django developer and I agree with you. We've ditched Django templates
entirely. We use it as our API platform only - most of the computation time is
spent in json and in Postgres.

------
jasode
The article's title is somewhat coy about the author's central thesis which he
states at the bottom[1]: _Basically, he prefers a language that is dynamic
instead of static._

Instead of giving a reader an immediate heads up about the dynamic-vs-static
argument, he gave it the subtitle of _" Another kind of performance"_ ...
which he means to be "programmer performance." The majority of the article is
about this topic.

The (cpu) "performance" is therefore a subtopic of the dynamic-vs-static
choice. He argues that "performance" was one of the drivers of static type
checking but that factor does not matter anymore. (E.g. his example of
objc_msgSend taking nanoseconds on both desktop & mobile.) I think the Android
interest in AOT (static) instead of JIT is a counterexample to that.
Performance still matters on battery powered, low GHz cpu devices like
smartphones.

[1]author says: _" Yes, I realize that would have meant pushing some errors
from compile time to run time, in exactly the same way Objective-C does right
now. But I don’t care — I’d take that trade-off every single day of the
week."_

~~~
mbrock
For me, when working in dynamic languages (that lack static checking of types,
null, etc) I'm a bit too nervous to "really fly."

When the computer helps me find errors, misspellings, and bugs—given that I
understand the type system well enough to not get very confused— _that 's_
when I "fly."

~~~
mpweiher
What sort of dynamic language? And what sort of environment?

I know people working in very dynamic/interactive environments who feel
exactly the same way when they can no longer "touch the objects".

~~~
mbrock
Well, I'll also say that I really fly in Common Lisp, and I think that
language has a nice balance: the compilers do check types and nullability, to
some extent at least... and the interactivity, "touching the objects"-ness,
and general pleasure of coding weighs up for the lack of a really rigorous
Haskell-like type system.

And I'm not really a strong advocate of any particular language. I'm still
holding out for a really excellent environment with some kind of best of all
worlds approach. Maybe in 30 years...

~~~
mpweiher
Same here (2nd para). IMHO, it _all_ sucks pretty badly, though there are tiny
patches of light here and there.

What I get somewhat tired of is advocates who have seen one of these tiny
patches and then proclaims having seen THE LIGHT and declaring all the rest
obvious darkness (and you're obviously not one of them).

I want to be able to adapt my language to my domain without having to write a
DSL or solve boring multi-language integration problems, I want to reuse
components without being overwhelmed by and stuck in glue code, I want to be
able to define any type of architectural connector that's appropriate for my
problem and have it be on par with any built-in stuff. I want static checking
of any properties I care to check, and I want to that to not get in my way by
obscuring the problem I am trying to solve. And I want it all live and with
amazing performance that is under my control :)

------
corysama
objc_msgSend is amazingly fast considering everything it is trying to
accomplish. But, it is amazingly slow considering what it actually does 99% of
the time in practice: call a single function repeatedly without variation that
could have been determined at compile time, but wasn't.

I sometimes come across companies making iOS products that don't heavily
leverage Apple's SDKs (games) but still use 100% ObjC instead of C or C++ for
some reason. Best I can guess is because Apple said that's what you are
supposed to do. ObjC is very nice. But, some of these companies have measured
upwards of 50% of their CPU time being spent inside objc_msgSend and I
question how much benefit they are getting in return.

Meanwhile, I have measured a direct, immediate correlations between
performance issues coming and going in my own apps to drops and recoveries in
revenue per day in those apps.

My point is: The widespread theme of valuing productivity over performance is
very wise. But, I frequently see it being applied in knee-jerk, unwise
situations. Getting good performance is difficult. Working in high-
productivity languages/styles is fun. I know you'd rather work on stuff that's
fun. But, having fun making a product that performs badly and drives users
away isn't as much fun in the end as it seems in the beginning.

------
pcwalton
That "2 nanoseconds for objc_msgSend" number is misleading for several
reasons. For one, that's the timing you'll get for a fully correctly
predicted, BTB hit, method cache hit, which does not always describe the real
world: Obj-C method cache misses are several orders of magnitude slower. But
the bigger problem is that the dynamic nature of Objective-C makes
optimization harder. Inlining can result in multi-factor performance increases
by converting intraprocedural optimizations to interprocedural ones, not to
mention all the actual IPO that a modern compiler for a more static language
can easily do. Apple clearly cares about this a lot, as shown by all the work
they've done on SIL-level optimizations.

Another way to look at it is: I would probably get similar (or better) numbers
by comparing the speed of a JavaScript method call with a warm monomorphic
inline cache, with the type test correctly predicted by the CPU branch
predictor. Does that mean JS is as fast as C++?

~~~
microcolonel
Though if your code size is smaller, your icache more likely has what you're
looking for.

------
santaclaus
The article seems to conflate performance with speed. An app's impact on
battery life is also an increasingly important performance metric.

~~~
dijit
Usually there is a direct correlation, most of an applications power
consumption will come from time on the CPU, even SSD's are using 2-4W.. memory
is even less expensive for power, but CPU can be up to 85W for a fully loaded
laptop CPU (well, mine)

Make sure your application doesn't idle rough, and executes quickly to spend
less time on the CPU, power consumption will follow.

~~~
PeCaN
It's a little more complicated than that though. For example, SSE/AVX
instructions cause Intel CPUs to (briefly) raise power consumption
considerably[1]. In some cases it may be better to avoid vector instructions
when optimizing for battery life at the cost of speed.

Also being smart about rendering (particularly for web, poorly written
animations can run smoothly but kill battery life) can dramatically affect
battery life even without affecting execution speed particularly much. They
are separate, though closely related, concepts.

1\. See e.g.
[http://www.intel.com/content/dam/www/public/us/en/documents/...](http://www.intel.com/content/dam/www/public/us/en/documents/white-
papers/performance-xeon-e5-v3-advanced-vector-extensions-paper.pdf) p.1 ¶2

~~~
pcwalton
> For example, SSE/AVX instructions cause Intel CPUs to (briefly) raise power
> consumption considerably[1].

I've never seen a case in which getting the work done faster wasn't a win.
That doesn't mean it can't happen, of course… But usually vector instructions
are a win.

~~~
corysama
When optimizing for wattage, SIMD is great for getting stuff done quickly so
you can get back to spinning on low-power Pause instructions.

But, if you SIMD-optimize, cheer at how much faster things are, then tell
yourself "That means I can squeeze in 4-8x more work in the same time!"
Well... You not only eliminated all the Pause time you gained, but you
replaced it with high-wattage work.

It takes discipline to optimize for power. Somewhat karmicly, pushing to max
out everything can backfire when you overheat the CPU and end up just pushing
it into adopting a lower clock rate.

------
flohofwoe
It's not so much raw performance of a given language, but the stuff that
"managed" languages and their runtimes do under the hood that's the problem.
I've spent a lot of time debugging stuff like ARC (Automatic Reference
Counting) creating hidden reference counting calls that were eating up a
terrible amount of total CPU time. These hidden performance traps are much
worse than having to think about (e.g.) proper memory management and data
layout. I'll take manual memory management over any 'magic solution' anytime
(they just increase complexity and if disaster strikes it is _much_ more
trouble to find and fix the problem).

Details: [http://floooh.github.io/2016/01/14/metal-
arc.html](http://floooh.github.io/2016/01/14/metal-arc.html)

~~~
_yosefk
Kinda depends on the cost of an error vs the cost of a slowdown though, and
then there's a big difference between say Objective-C or the once-relevant
COM/ATL etc. by MS, where you have all the C bugs and manual memory management
plus somewhat automated memory management in some places with all the troubles
of _that_ , and say Java where at least you have a fully working garbage
collector which deals with cycles and never leaks unreachable memory, and you
also have guaranteed memory safety.

I'd rather trust my credit card number to a Java program than a C/C++ program
- or an Objective-C program; see also
[http://www.flownet.com/ron/xooglers.pdf](http://www.flownet.com/ron/xooglers.pdf)
for the early Google billing server disaster, not possible with a garbage
collector "thinking" about proper memory management and rather hard to prevent
with very good developers thinking that they have thought proper memory
management through. (And git had a bug where you could execute code remotely
because nobody can really manage memory in C, etc. etc. etc.)

------
andrewflnr
I don't buy it. Part of what makes a great app is that it doesn't have bugs.
So don't try to tell me that the special tool you need to really make great
apps is one that lets you write more bugs.

------
jheriko
lols. as if replacing objective-c with clean c or c++ wasn't a valid
performance strategy (p.s. it is. i've made real world applications hit
framerate that way because a ton of objc_msgSend is more expensive than
nothing every single time, and its very exceptionally necessary (are you
crossing a very hard boundary like a network?)).

i agree with his basic point though. almost all ways of building an app
require needless complexity that is easily solved at the tools level.

------
cbsmith
I wish people would stop talking about "fast" and instead talk about
"efficient".

~~~
taneq
I think it's actually the opposite. The important thing is a short response
time to the user - whether that's achieved by reducing the number of things
you do, or by doing them more efficiently, is kind of moot.

~~~
majewsky
> whether that's achieved by reducing the number of things you do, or by doing
> them more efficiently

Is there any way to do stuff more efficiently instead of doing less things
(i.e. doing it in less steps)? Optimizing is always about trimming out the
fat.

~~~
taneq
Depends on what you're defining as "things". In terms of base instructions?
No, all you can do is do less things. (Edit: Although even here, you can do
different things to make the overall process cheaper - multiply by the inverse
instead of dividing, replace a sin() calculation with a lookup, etc.) In terms
of intermediate goals? If you have to process 500 objects, you can either find
a way to skip some of the objects ('reduce the number of things you do') or
you can make processing an object as fast as possible ('doing them more
efficiently').

------
elcritch
Most of the other comments point out the idiosyncrasies of the article but I
think most of the commentators are missing the point behind the author's basic
frustration. While Chris Lattner is a brilliant system's programmer, the work
he and his team did with Swift shows their focus on systems type programming.
As the author points out, Objective-C was actually a _brilliant_ language for
GUI's and application design. It was hampered by C syntax cruft (easily
remedied), but the proof is that Objective-C and the Cocoa Framework has had
one of the best (IMHO) successes for any GUI toolkit and desktop framework.

Consider that Obj-C survived transitions from desktop to mobile apps, and many
of the features such as modern email viewers with embedded image viewing were
accomplished on NeXT long before Windows had comparable features. I think
Steve Jobs realized this which was his particular genius -- choosing the right
tech and focusing it with a "marketing" angle [8]. I think the newer shift
toward Swift at Apple shows a focus on "systems" type of thinking, but
unfortunately I've also notice a certain decline in application quality --
i.e. Safari search bar crashing on OS X and iOS [2].

If I had to speculate, I'd say the success of many of Apple's UI were due to
the SmallTalk aspects of Objective-C which focused on message passing instead
of eager function binding and C++ style inheritance. Having written my own low
level object system in C and LLVM for an XML processing language, my take is
that while having similar intent to implement dynamic dispatching, the
emphasis shift between message-passing vs virtual-tables forces a slightly
different style of library and framework composition. Essentially message
passing is more expressive but sacrifices potential speed, but as Wikipedia
describes it:

> Because a type can have a chain of base types, this look-up can be
> expensive. A naive implementation of Smalltalk's mechanism would seem to
> have a significantly higher overhead than that of C++ and this overhead
> would be incurred for each and every message that an object receives. Real
> Smalltalk implementations often use a technique known as inline caching[3]
> that makes method dispatch very fast. Inline caching basically stores the
> previous destination method address and object class of the call site (or
> multiple pairs for multi-way caching). The cached method is initialized with
> the most common target method (or just the cache miss handler), based on the
> method selector. --
> [https://en.wikipedia.org/wiki/Dynamic_dispatch](https://en.wikipedia.org/wiki/Dynamic_dispatch)

However, practically speaking cache inlining can allow the language
implementation to be more expressive and forgiving -- a failed method lookup
can be forwarded to an "unknown handler" method as in Ruby's `method_missing`
unlike in C++ [3], or the situation in Swift (?) [4].

Basically, Haskell et al have made tremendous strides in progressing type
theory and corresponding practical implementation of functional style
programming with monadic theory and similar, we're still not sophisticated
enough to basically provide easily expressive statically type code which still
gives the full expressiveness of dynamic languages. Humans are _really_ good
at reasoning about systems of communicating components (message passing,
overlapping the actor models of computation) but really not as good at
category theory, which while mathematically equivalent don't necessary make
them as good for programming large, untyped information that's present in most
modern GUI's. Thing's like React however make a huge stride forward in some
aspects in that regard. Though I'd rather program that in JavaScript (another
prototype based language borrowing from the message passing tradition) than in
Swift/C++ style languages which essentially force type checking at a lower
level while more complex higher abstractions remain un-type checked. So all
the work of the type system while not getting benefit for higher abstractions
(e.g. User clicks button which sets system into X state). I'm branching out
quite a bit, but it's actually quite a complex problem and is still very much
an "open problem", although one we're getting closer to solving well. For
clearer examples of what I'm talking about see some of these type of papers I
found with a quick search: [5], [6]. My take is that the author is talking
about a language more oriented toward system-architecting, an example approach
like that taken by Ceylon [7].

[1]:
[http://arstechnica.com/apple/2005/12/2221/](http://arstechnica.com/apple/2005/12/2221/)
[2]:
[http://www.bbc.com/news/technology-35420573](http://www.bbc.com/news/technology-35420573)
[3]:
[https://rosettacode.org/wiki/Respond_to_an_unknown_method_ca...](https://rosettacode.org/wiki/Respond_to_an_unknown_method_call#C.2B.2B)
[4]: [https://github.com/rodionovd/SWRoute/wiki/Function-
hooking-i...](https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-
Swift) [5]:
[https://pdfs.semanticscholar.org/8a42/9baf82c17a936801de4e37...](https://pdfs.semanticscholar.org/8a42/9baf82c17a936801de4e37b8bd6b5c9e077e.pdf)
[6]: [http://lambda-the-ultimate.org/node/5329](http://lambda-the-
ultimate.org/node/5329) [7]: [http://ceylon-lang.org](http://ceylon-lang.org)
[8]: [http://www.infoq.com/news/2011/10/steve-jobs-
contribution](http://www.infoq.com/news/2011/10/steve-jobs-contribution)

~~~
blub
Objective-C is not a brilliant language and it's finally being discarded by
Apple and replaced with something better. This is hard to accept for the
(surprisingly) many fans that it has, but Objective-C is almost legacy - jobs,
docs, APIs will be Swift-first. Talking about performance and dynamic typing
and message passing won't change that.

Apple looked at the competition and saw that Java 6(!!) was kicking
Objective-C's ass - it was easier to program in, less error-prone, easier to
understand and fast enough.

------
ahoka
I think that in most programs the performance depends on the architecture. A
well written Python + twisted or Java + netty network code can easily
outperform any naive C implementation. The same goes for algorithms used.
Number crunching is the exception, not the rule.

------
namuol
Forget scripting languages -- Where's our Photoshop for (web)apps?

