Wednesday, August 26, 2015

What Happens to OO When Processors Are Free?

A while ago, I presented as a crazy thought experiment the idea of using Montecito's transistor budget for creating a chip with tens of thousand of ARM cores. Well, it seems the idea wasn't so crazy after all: The SpiNNaker project is trying to build a system with a million ARM CPUs, and it is designing a custom chip with lots of ARM cores on it.

Of course they only have 1/6th the die area of the Montecito and are using a conservative 135nm process rather than the 95nm of the Montecito or the 15nm that is state of the art, so they have a much lower transistor budget. They also use the later ARM 9 core and add 54 SRAM banks with 32KB each (from the die picture, 3 per core), so in the end they "only" put 18 cores on the chip, rather than many thousands. Using a state of the art 14nm process would mean roughly 100 times more transistors, a Montecito-sized die another factor of six. At that point, we would be at 10000 cores per chip, rather than 18.

One of the many interesting features of the SpiNNaker project is that "the micro-architecture assumes that processors are ‘free’: the real cost of computing is energy." This has interesting consequences for potentially simplifying object- or actor-oriented programming. Alan Kay's original idea of objects was to scale down the concept of "computer", so every object is essentially a self-contained computer with CPU and storage, communicating with its peers via messages. (Erlang is probably the closest implementation of this concept).

In our core-scarce computing environments, this had to be simulated by multiplexing all (or most) of the objects onto a single von Neumann computer, usually with a shared address space. If cores are free and we have them in the tens of thousands, we can start entertaining the idea of no longer simulating object-oriented computing, but rather of implementing it directly by giving each object its own core and attached memory. Yes, utilization of these cores would probably be abysmal, but with free cores low utilization doesn't matter, and low utilization (hopefully) means low power consumption.

Even at 1% utilization, 10000 cores would still mean throughput equivalent to 100 ARM 9 cores running full tilt, and I am guessing pretty low power consumption if the transistors not being used are actually off. More important than 100 core-equivalents running is probably the equivalent of 100 bus interfaces running at full tilt. The aggregate on-chip memory bandwidth would be staggering.

You could probably also run the whole thing at lower clock frequencies, further reducing power. With each object having around 96KB of private memory to itself, we would probably be looking at coarser-grained objects, with pure data being passed between the objects (Objective-C or Erlang style) and possibly APL-like array extensions (see OOPAL). Overall, that would lead to de-emphasis of expression-oriented programming models, and a more architectural focs.

This sort of idea isn't new, the Transputer got there in the late 80ies, but it was conceived when Moore's law didn't just increase transistor counts, but also clock-frequencies, and so Intel could always bulldozer away more intelligent architectures with better fabs. This has stopped, clock-frequencies have been stagnant for a while and even geometries are starting to stutter. So maybe now the time for intelligent CPU architectures has finally come, and with it the impetus for examining our assumptions about programming models.

As always, comments welcome here or on Hacker News.

UPDATE: The kilo-cores are here:

  • Kilocore: 1000 processors, 1.78 Trillion ops/sec, and at 1.78pJ/Op super power-efficient, so at 150 GOps/s only uses 0.7 watts. On a 32nm process, so not yet maxed out.
  • GRVI Phalanx joins The Kilocore Club: 1680 cores.
No reports of any of them running actors, but ensembles might work :-)

Tuesday, July 7, 2015

Greek Choices: A German's Perspective

My 6Wunderkinder Microsoft colleague James Duncan Davidson penned some beautiful notes on the Impossible Greek Choices that happened effectively during his wedding and honeymoon (congratulations!!), to the people he has grown to know and, in some cases, love. It's a wonderful piece that I highly recommend. There were some calls for a German perspective, which is by necessity going to be less personal, but I hope it can provide some additional background.

The Referendum

The Greek Referendum was an odd one, because it asked voters whether to accept or not accept an offer by the 18 other Euro states and the IMF that was, in fact, no longer on the table. So that's at least a little weird, as there really wasn't a choice to make, and from here it looked like pure grandstanding / political theater.

I don't know how it was perceived in Greece, but from here it looked like the government presented the choices as "bow to German dictates" vs. "we can do without them". And the capital controls imposed by the Greek government because the banks were effectively insolvent were described as "terrorism" perpetrated by the EU. That's a bit rich when you take into account that the only thing keeping the country afloat was EU funds and the money that is still available is coming from EU emergency funds. If "terrorists" are people who give you money, I want some more terrorists around me.

Even weirder is the fact that Tsiprias seems to think that the No vote will strengthen his position in future negotiations, that now he will be able to negotiate a better deal. I have a feeling that this will go down as one of the biggest political miscalculations in history, but I may be wrong and he will now get everything he wanted.

The "German" View

The German perspective on the Greek debt crisis is really quite simple: you can't live beyond your means indefinitely. You can do it temporarily by taking on debt, but at some point that debt has to be repaid. At that point you have to not only revert to living within your original means, but significantly below because you have the debt to repay.

I think this is completely obvious and non-controversial, as it relies on no more than basic arithmetic. But then again, I am German.

This doesn't mean you can never take on debt. For example, it makes sense to time-shift availability of things. Or to invest in things that increase your earning potential. Or one-time events, especially with a strong time component. But never to lift your general standard of living. There is no way that can work.

The Keynesian View

Keynesians say that governments are different from private individuals, and the debt they take on is different from normal household debt. Important is the role of government debt in a recession: the government should take on more debt to minimize economic contraction and spur growth. The worst thing a government can do in a recession is start saving and imposing "austerity": the economy will contract even more, and apart from hurting citizens, this actually tends to make the debt problem worse. The reason is that government debt is generally measured relative to GDP, because GDP/economic output is a pretty direct indicator of a country's ability to pay back its debt.

While not quite as uncontroversial, I think this is also largely trivially true.

Although these two views are often described as contradictory, for example Krugman criticizes the "Austerians" by showing how Keynesian predictions turn out to be true, I don't think they are. After all, you can pick up debt in a crisis and then pay back the debt when the economy is doing well, and IIRC, that is exactly what Keynes said governments should do, behave anti-cyclically.

Of course, this requires discipline: why should I do something uncomfortable when things are going well? After all, the fact that things are going well proves that what I am doing is right, right? Empirically, governments do not seem to pay back debt in any significant way shape or form, for reasons I do not fully understand. Part appears to be simple expediency, why cut spending (=happy voters) when you don't absolutely have to? Part might be that our pensions systems tend to depend on having "safe" government debt to invest in. Financial markets also appear to be fine with a small-ish permanent fiscal deficit.

I personally think this is hugely problematic and undermines democratic principles, because governments sell out their sovereign (the voters) to the financiers for a little bit of extra spending money. Panem et circenses.

A Third Way (I)

Of course, there is a way of living beyond your means without having to suffer the consequences, which is to have someone else pick up the tab, for example by not repaying your debt. The most obvious way is a default, but if you are a country and the debt is in your own currency, you get more subtle options such as devaluation, where you just lessen the value of the debt (and of all the money in circulation, but hey...) or high inflation, which has the same effect but stretches it out over time so it is less noticeable.

In the past, at least Italy and Greece used to do this all the time, but of course this means that people are much less willing to lend you money, and they will demand much higher interest payment, pricing in actual or potential inflation and risk of devaluation or default. In the worst case, people will stop lending you money altogether.

Without control over a currency and attached printing press for said currency, inflating or devaluing your way out of trouble is no longer an option, which is why joining the Euro area was contingent on meeting "convergence criteria" on inflation and public debt.

Whereas Italy made a real effort to meet the criteria, Greece never really did. Even the official figures were at best marginal, but these had been doctored by US money house and vampire squid Goldman Sachs.

However, private money lenders were unaware (possibly willfully) of this, and lent Greece money at Euro-group rates, way, way below previously attainable rates. Greece, freed from the difficulty and expense of obtaining debt, went on a debt-fueled spending spree: GDP skyrocketed, from Euro introduction in 2001 to the start of the financial crisis in 2008 by a factor of 2.3!

Did the Greek economy become super-competitive in this time, did exports soar, did tourism? As far as I know, the answer to these questions is "No", the rise in GDP was largely fueled by cheap debt. The Euro area in general did well during this time, but for example Germany's GDP in 2008 was only 50% higher than the high point in the mid 90ies.

Greece piled on public debt in this period at >10% of the budget.

The Greek Problem

When the financial crisis hit, the toxicity of all the debt held by pretty much everyone became evident, but for some reason, Greece was particularly hard hit, despite the fact that their overall debt levels were not that much worse than everyone else's. However, how bad existing debt is is very much influenced by your creditworthiness, because debt is constantly refinanced and a bad credit rating means that what used to be sustainable levels of debt can become unsustainable, a self-fulfilling prophecy.

Well, our favorite vampire-squid Goldman Sachs announced that something was "fishy" with Greece. How did they know this? Easy, as we saw above they were the ones who had helped Greece cook the books in the first place! Suddenly Greece's credit load was unsustainable, because rates skyrocketed. Well, Greece's rates reverted to pre-Euro levels, because it became known that the information that had been used to justify low Euro-area rates (meeting the "convergence criteria") had been falsified.

Without those falsifications, Greece's borrowing costs would have been much higher, and those high borrowing costs would have prohibited taking on as much debt as had been taken on to fuel Greece's GDP bubble. Added factors were that Greece no longer had the option of devaluing creditors' assets by devaluing or inflating debt away, but at the core is trustworthiness: do I, as a creditor, believe that my debtor will pay back their debt to me in full? If I am 100% certain, rates are low, with every bit of doubt rates rise until they are infinite, i.e. you can't borrow.

Greece simply was never trustworthy, and for most of history this was well known, except for the period between 2001 (Euro introduction) and 2008 (financial crisis). Of course, it could have been known if the banks lending Greece money had bothered to look. But they didn't look, which was reckless, beyond the lie that Goldman Sachs had helped Greece sell, which was criminal.

So what I think should have happened (aside from the debt never accumulating in the first place because of people and institutions not lying and doing their jobs properly) is that Greece should have defaulted on those debts, the banks that recklessly lent that money took the hit they deserved to take and then sued Goldman Sachs and the Greek government(s) and the officials for the damages.

What happened instead was the typical and sickening socialization of private losses, while profits from those same transactions continued and continue to be privatized.

At this point, we could have taken the economically correct Keynesian approach of helping the Greek economy recover with the help of possibly even more debt, but debt that becomes sustainable because GDP rises faster than debt and thus the all important debt/GDP ratio falls.

Instead we got the mess we're in now, with GDP down 25% from peak, though still significantly higher than before the Euro. Why? As far as I can tell, a large part of the reason is that no one in the EU trusts pretty much any Greek government with a scheme that entails "you get stuff now, and you will do the right things later". No one.

The reason for this is that, in the context of the EU, successive Greek governments have flouted every rule, broken every agreement, ignored every regulation on the books. Consistently. Over the last 30 plus years. All while receiving billions in EU funds that are contingent on compliance with those rules. Rules that every other EU country had to abide by, and when non-compliance was detected, funds were withheld. This includes the old countries as well as the newest. Except Greece.

For example, one of the largest pieces of the budget is the Common Agriculture Policy (CAP), a system of farm subsidies. Every country is required to have specific electronic reporting systems in order to receive CAP funds. The new states all had to install them, even the poorest, and when they did not, CAP funds were withheld. Except Greece, which to this day does not have such a system.

The plastic olive trees used to obtain additional farm subsidies are legendary, but sadly not mythical. Having better controls would make this sort of creative farming (and accounting) much more difficult.

There are also requirements for good governance and tax collection standards, for example you need to have a land registry in order to collect property tax (and protect property rights). Greece does not have such a registry, which is pretty novel for an ostensibly developed nation.

They were required to have one. Didn't bother successive Greek governments. At one point they got significant EU funds to build such a system (€100m IIRC UPDATED: I initially recalled incorrectly that it was €400m, the correct figure is €100m). After a couple of years, an EU official was sent to check. At first, the Greek authorities didn't know what he was talking about. Then they remembered. Of course, not a thing had been done to create a registry.

After being reminded that they had received (and accepted) €400m in funds specifically dedicated to the purpose of building such a registry, they offered to "refund" half the amount, €200m. The mind boggles.

Of course, tax collection is a huge domestic problem in Greece, with often huge wealth and income taxed at best theoretically. Real estate plays a huge role in this, and this is why a land registry is not popular with the elites. When the tax collectors come to these quite fabulous houses, nobody there knows who the hoses belong to.

I still really like Volker Pispers's idea of tax collection via bulldozer: knock at the first house on the block. If an owner can't be found, knock it down. I am pretty certain tax compliance will improve markedly.

Anyway, as far as I can see, Greek governments see flouting EU rules as their birthright, as something that cannot possibly have consequences, a view that they has never been challenged until now. So I think their indignation at actually being held accountable is quite real, and they do see enforcement of rules as cruel and certainly unusual punishment, because for them it is just that: unusual, unexpected, unfamiliar.

And of course, EU institutions that let them get away with, well, everything over so many years certainly share some of the blame. But only some, not nearly as much as Greek politicians would like everyone to believe.

When Syriaza was voted into power, I was hopeful that things would improve, but they almost immediately started placing their relatives in well-paid positions, and apparently their proposals are just as vague about finally taxing the actual significant wealth that exists, and just as concrete about squeezing lower incomes to enrage public opinion and effectively use these people as human shields to protect the wealthy. I think I've used the word "sickening" before.

A Third Way (II)

Duncan writes:
What should be on the table is a decision by Europe to strengthen the economic union by sharing the eurozone’s debt. While the particulars of the Greek situation sent them over the edge first in the financial meltdown of 2008, sharing a currency between states without sharing debt is unsustainable in the long term for the entire eurozone. This isn’t news.
I confirmed with him that he meant "debt + fiscal" union. Yes. It is the only way a monetary union can work, in the long run. This has been pointed out many times, by many people. Alas, he adds:

The only surprising thing at this point is that states like Germany insist on keeping Greece under the weight of a debt that can’t ever be repaid.
I take exception to that on several levels:
  1. Nobody forced Greece to take on loans (from private banks) that it knew it couldn't repay
  2. Nobody forced Greece to cheat in order to obtain those loans, which it would never have had access to without cheating.
  3. Nobody forced Greece to avoid certain default, with all the awful consequences that we are now only beginning to see, by accepting a bailout using public/taxpayer money. Which came with certain conditions. If you don't like to conditions, don't take the money.
That said, I don't think anyone in the remaining Eurozone governments has any illusions about Greece avoiding having to default on at least part of that debt. After all, said governments already negotiated a partial default, with both public and private lenders taking a hit.

However, those governments have a justified interest in the same thing not happening again and again. The easiest way to do this would be to have a fiscal union, with member states giving up some chunk of their sovereignty over spending. However, national governments currently balk at this, most vehemently the Greek government with their referendum and "national pride" demagoguery.

Given that fiscal union is not on the table, the other alternative are stringent reforms. And given the simple fact that Greek governments have not been the least bit trustworthy, including this one, the only way to get those reforms is "under the gun". This is unfortunate, and economically stupid, but there does not appear to be any alternative other than letting Greece continue to spend as it wishes with others picking up the tab from time to time. And that is also not an option.

So yeah, it's complicated, and life sometimes sucks, especially for all the people that get to suffer from the consequences of their governments' actions.

The Seldon Crisis You Ordered Is Ready, Where Would You Like It Delivered?

Coming back to Euro, my view of the Euro project was always that it was never really about monetary union. The people who instigated it were dedicated Europeans, a view I share. They wanted political union. They knew that political union was not possible at the time. So they created monetary union, which was politically possible, knowing that over time it would create a situation that would force political union as the only reasonable alternative. A classic Seldon crisis. The only weird thing is that the crisis is here and yet it is not being used to create the fiscal and political union as one would expect. There were plans, it seems, but these were not acted upon. Is it because our current crop of leaders are too fearful, too used to just waiting it out, whatever "it" is? Are they too timid to take the bold leap required to create something great? Or maybe the crisis just isn't deep enough yet? I truly don't know, and am completely flabbergasted.

Of course, things are always a bit more complicated, for example the Euro was also a precondition for German unification, demanded by various European "partners", particularly France in order to limit German power post-unification. The fact that the Euro is now described as an evil German master plan to subjugate the proud southern European nations make this somewhat ironic, or more likely demonstrates how off-base and populist those types of claims are.

The US angle

You've probably noticed the central role of US investment bank and favorite vampire squid (sorry for the repitition, I just can't resist writing that...) Goldman Sachs in this saga: not only were they absolutely instrumental in creating the problem, they then blabbed about at the exact worst possible moment, in the middle of the worst financial crisis the world has seen in the last 80 years or so.

While I am not much into conspiracy theories, this is just too much of a coincidence to be... a coincidence, especially when you keep in mind the revolving door between GS and various parts of the US government and the fact that the US is not very fond of the EU, and absolutely hates the Euro.

When taken together, the EU is the world's largest economic power, with more people than the US and a greater GDP. If and when it gets its political act together, it will also be a significant political power, with 2 seats on the security council, a nuclear arsenal, unparalleled economic might and much less hatred for it in the world than the US. Having the EU get its political act together is not in the US's national interest, and as the NSA affair amply demonstrated (not that it was ever in dispute), there are no friendships at this level, just national interests that may coincide from time to time.

While the EU as such is a problem for US interests, the Euro presents an actual real danger. Not only is it a central piece of getting to political union (not just, but especially if my idea that it was intended to hasten the process is true), it has started to become an alternative to the dollar as a petro-, trade- and reserve-currency.

Why is this problematic? One of the mysteries of the US economy is how it has been able to have huge trade deficits, expand the money supply ("print money") and do all sorts of other things, without ever being punished by the usual consequences: high inflation and high interest rates.

While part of the answer is the "confidence fairy" that Professor Krugman ridicules in other contexts (people just think that the US will continue to be a good investment), a huge part is the use of dollars by other countries, which soaks up the dollars you just printed and spent.

An alternative reserve-/trading-currency means that those dollars will not just no longer be soaked up, but even worse existing reserves will likely be released, so all those dollars flood the market and cause the effects that were previously avoided. Which could be financially disastrous.

Friday, July 3, 2015

When Is My Unit Test Coverage Adequate?

  1. When you are not afraid of changing any of the code.
  2. When you are comfortable with releasing as soon as the tests are green (i.e. always).
  3. Tertium non datur :-)

Why unit tests and not integration test?

Integrated Tests Are a Scam [vimeo]

EOM

Friday, June 26, 2015

Guys, "guys" is perfectly fine for addressing diverse groups

With the Political Correctness police gaining momentum again after being laughed out of the 80ies, the word "guys" has apparently come under attack as being "non-inclusive". After discussing the topic a bit on twitter, I saw Peter Hosey's post declaring the following:

"when you’re addressing a mixed-gender or unknown-gender group, you should not use the word 'guys'."
As evidence, he references a post by Julia Evans purportedly showing that for most uses, people perceive "guys" to be gender-specific. Here is the graph of what she found:

What I find interesting is that that data show exactly the opposite of Peter's claim. Yes, most of the usage patterns are perceived as gender-specific by more people than not, but all of those are third person. The one case that is second person plural, the case of addressing a group of people, is overwhelmingly perceived as being gender neutral, with women perceiving it as gender neutral slightly more than men, but both groups at over 90%.

This matches with my intuition, or to be more precise, I find it somewhat comforting that my intuition about this appears to still match reality. I find "hey guys" neutral (2nd person plural), whereas "two guys walked into a store" is male.

Prescription vs. Description

Of course, they could have just checked their friendly local dictionary, for example Webster's online:
guy (noun)
Definition of GUY
  1. often capitalized : a grotesque effigy of Guy Fawkes traditionally displayed and burned in England on Guy Fawkes Day
  2. chiefly British : a person of grotesque appearance
  3. a : man, fellow
    b : person —used in plural to refer to the members of a group regardless of sex
  4. 4 : individual, creature <the other dogs pale in companion to this little guy>
So there we go: "used in plural to refer to the members of a group regardless of sex". It is important to note that unlike continental dictionaries (German, French), which proscribe correct usage, the anglo-saxon tradition is descriptive, meaning actual use is documented. In addition, my recollection is that definitions are listed chronologically, with the older last and newer ones first. So the word's meaning is shifting to be more gender neutral. This is called progress.

What I found interesting is that pointing out the dictionary definition was perceived as prescriptive, that I was using trying to force an out-of-touch dictionary definition on a public that perceives the word differently. Of course, the opposite is the case: a few people are trying to force their perception based on outdated definitions of the word on a public and a language that has moved on.

Language evolution and the futility of PC

Speaking of Anglo-Saxons and language evolution: does anyone feel the oppression when ordering beef or pork? Well, you should. These words for the meat of certain animals were introduced to English in 1066 with the conquering Normans. The french words for the animals were now used to describe the food the upper class got served, whereas the anglo-saxon words shifted to denote just the animals that the peasants herded. Yeah, and medieval oppression was actually real, unlike some other "oppression" I can think of.

Of course, we don't know about that today, and the words don't have those association anymore, because language just shifts to adapt to and reflect reality. Never the other way around, which is why the PC brigade's attempts to affect reality by policing language is so misguided.

Take the long history of euphemisms for "person with disability". It started out as "cripple", but that word was seen as stigmatizing, so it was replaced with "handicapped", because it wasn't something a defect with the person, but a handicap they had. Then that word got to be stigmatized and we switched to "disabled". Then "person with disabilities", "special", "challenged", "differently abled". And so on and so forth. The problem is that it never works: the stigma moves to the new word that was chosen because it was so far stigma-free, so nowadays calling someone "special" is no longer positive. And calling homeless people "the temporarily underhoused" because "home is wherever you are" also never helped.

So leave language be and focus on changing the underlying reality instead. All of this does not mean that you can't be polite: if someone feels offended by being addressed in a certain way, by all means accomodate them and/or come to some understanding.

Let the Hunting begin :-))

Wednesday, June 17, 2015

Protocol-Oriented Programming is Object-Oriented Programming

Crusty here, I just saw that my young friend Dave Abrahams gave a talk that was based on a little keyboard session we had just a short while ago. Really sharp fellow, you know, I am sure he'll go far someday, but that's the problem with young folk these days: they go rushing out telling everyone what they've learned when the lesson is only one third of the way through.

You see, I was trying to impart some wisdom on the fellow using the old Hegelian dialectic: thesis, antithesis, synthesis. And yes, I admit I wasn't completely honest with him, but I swear it was just a little white lie for a good educational cause. You see, I presented ADT (Abstract Data Type) programming to him and called it OOP. It's a little ruse I use from time to time, and decades of Java, C++ and C# have gone a long way to making it an easy one.

Thesis

So the thesis was simple: we don't need all that fancy shmancy OOP stuff, we can just use old fashioned structs 90% of the time. In fact, I was going to show him how easy things look in MC68K assembly language, with a few macros for dispatch, but then thought better of it, because he might have seen through my little educational ploy.

Of course, a lot of what I told him was nonsense, for example OOP isn't at all about subclassing, for example the guy who coined the term, Alan I think, wrote: "So I decided to leave out inheritance as a built-in feature until I understood it better." So not only isn't inheritance not the defining feature of OOP as I let on, it actually wasn't even in the original conception of the thing that was first called "object-oriented programming".

Absolute reliance on inheritance and therefore structural relationships is, in fact, a defining feature of ADT-oriented programming, particularly when strong type systems are involved. But more on that later. In fact, OOP best practices have always (since the late 80ies and early 90ies) called for composition to be used for known axes of customization, with inheritance used for refinement, when a component needs to be adapted in a more ad-hoc fashion. If that knowledge had filtered down to young turks writing their master's thesis back in what, 1997, you can rest assured that the distinction was well known and not exactly rocket science.

Anyway, I kept all that from Dave in order to really get him excited about the idea I was peddling to him, and it looks like I succeeded. Well, a bit too well, maybe.

Antithesis

Because the idea was really to first get him all excited about not needing OOP, and then turn around and show him that all the things I had just shown him in fact were OOP. And still are, as a matter of fact. Always have been. It's that sort of confusion of conflicting truth seeming ideas that gets the gray matter going. You know, "sound of one hand clapping" kind of stuff.

The reason I worked with him on a little graphics context example was, of course, that I had written a graphics context wrapper on top of CoreGraphics a good three years ago. In Objective-C. With a protocol defining the, er, protocol. It's called MPWDrawingContext and live on github, but I also wrote about it, showed how protocols combine with blocks to make CoreGraphics patterns easy and intuitive to use and how to combine this type of drawing context with a more advanced OO language to make live coding/drawing possible. And of course this is real live programming, not the "not-quite-instant replay" programming that is all that Swift playgrounds can provide.

The simple fact is that actual Object Oriented Programming is Protocol Oriented Programming, where Protocol means a set of messages that an object understands. In a true and pure object oriented language like Smalltalk, it is all that can be, because the only way to interact with an object is to send messages. Even if you do simple metaprogramming like checking the class, you are still sending a message. Checking for object identity? Sending a message. Doing more intrusive metaprogramming like "directly" accessing instance variables? Message. Control structures like if and while? Message. Creating ranges? Message. Iterating? Message. Comparing object hierarchies? I think you get the drift.

So all interacting is via messages, and the set of messages is a protocol. What does that make OO? Say it together: Protocol Oriented Programming.

Synthesis

So we don't need objects when we have POP, but at the same time POP is OOP. Confused? Well, that's kind of the point of a good dialectic argument.

One possible solution to the conflict could be that we don't need any of this stuff. C, FORTRAN and assembly were good enough for me, they should be good enough for you. And that's true to a large extent. Excellent software was written using these tools (and ones that are much, much worse!), and tooling is not the biggest factor determining success or failure of software projects.

On the other hand, if you want to look beyond what OOP has to offer, statically typed ADT programming is not the answer. It is the question that OOP answered. And statically typed ADT programming is not Protocol Oriented Programming, OOP is POP. Repeat after me: OOP is POP, POP is OOP.

To go beyond OOP, we actually need to go beyond it, not step back in time to the early 90ies, forget all we learned in the meantime and declare victory. My personal take is that our biggest challenges are in "the big", meaning programming in the large. How to connect components together in a meaningful, tractable and understandable fashion. Programming the components is, by and large, a solved problem, making it a tiny bit better may make us feel better, but it won't move the needle on productivity.

Making architecture malleable, user-definable and thus a first class citizen of our programming notation, now that is a worthwhile goal and challenge.

Crusty out.

As always, comments welcome here and on HN.

Sunday, June 7, 2015

Steve Jobs on Swift

No, there is no actual evidence of Steve commenting on Swift. However, he did say something about the road to sophisticated simplicity.

In short, at first you think the problem is easy because you don't understand it. Then you begin to understand the problem and everything becomes terribly complicated. Most people stop there, and Apple used to make fun of the ones that do.

To me this is the perfect visual illustration of the crescendo of special cases that is Swift.

The answer to this, according to Steve, is "[..] a few people keep burning the midnight oil and finally understand the underlying principles of the problem and come up with an elegantly simple solution for it. But very few people go the distance to get there."

Apple used to be very much about going that distance, and I don't think Swift lives up to that standard. That doesn't mean it's all bad or that it's completely irredeemable, there are good elements. But they stopped at sophisticated complexity. And "well, it's not all bad" is not exactly what Apple stands for or what we as Apple customers expect and, quite frankly, deserve. And had there been a Steve in Dev Tools, he would have said: do it again, this is not good enough.

As always, comments welcome here or on HN

Saturday, May 23, 2015

I am jealous of Swift

Really, I am. They get to do everything wrong there is in language design and yet the results get fawned upon and the obvious flaws not just overlooked but turned into their opposite.

Language Design

What do I mean? Well, primarily this:
Swift is a crescendo of special cases stopping just short of the general; the result is complexity in the semantics, complexity in the behaviour (i.e. bugs), and complexity in use (i.e. workarounds).
The list Rob compiled is impressively well-researched. Although "special cases stopping just short of the general" for me is enough, it is THE cardinal sin of language design, I would add "needlessly replacing the keyword message syntax at exactly the point where it was no longer an issue and adding it back as an abomination of accidental complexity the world has never seen before". Let's see what Gilad Bracha, an actual programming language designer, has to say on the keyword syntax:
This notation makes it impossible to have an arity error when calling a method. In a dynamically typed language, this is a huge advantage.

I am keenly aware that this syntax is unfamiliar to most programmers, and is a potential barrier to adoption. However, it improves usability massively. Furthermore, a growing number of programmers are learning this notation because of its use in Objective-C (e.g., the iOS APIs).

Abandoning keyword syntax at this point in time takes "snatching defeat from the jaws of victory" to a whole new and exciting level!

Or the whole idea of having every arithmetic operation be a potential crash point, despite the fact that proper numeric towers have been around for many decades and decently optimized (certainly no slower than unoptimized Swift).

And yet, Rob for example writes that the main culprit for Swift's complexity is Objective-C, which I find somewhat mind-boggling. After all, the requirement for Objective-C interoperability couldn't exactly have come as a last minute surprise foisted on an existing language. Folks: if we're designing a replacement language for Apple's Cocoa frameworks, Objective-C compatibility needs to be designed in from the beginning and not added in as an afterthought. And if you don't design your language to be at odds with the frameworks you will be supporting, you will discover that you can get a much cleaner design.

Performance

The situation is even more bizarre when it comes to performance. For example, here's a talk titled How Swift is Swift. The opening paragraph declares that "Swift is designed to be fast, very fast", yet a few paragraphs (or slides) down, we learn that debug builds are often 100 times slower than optimized builds (which themselves don't really rival C).

Sorry, that's not the sign of a language that's "designed to be fast". Those are the characteristics of a language design that is inherently super, super slow, and that requires leaning heavily on the optimizer to get performance to an acceptable level.

And of course, the details bear that out: copy semantics are usually expensive, they need the optimizer to elide those copies in the majority of cases. Same with ARC, which is built in and also requires the optimizer to be effectively clairvoyant (and: on) in order not to suffer 30x regressions.

Apart from the individual issues, the overriding one is that Swift's performance model is extremely opaque (100x for turning the optimizer on). Having the optimizer do a heroic job of optimizing code that we don't care about is of no use if we can't figure out why the code we do care about is slow or how to make it go fast.

Jealousy

So what makes little amateur language designer me jealous is that I really do try and get these things right, make sure the design is parsimonious, and these guys just joyfully ignore every rule in the book, and then trample on said book in ways that should get the language designer's guild to revoke their license, yet there is almost universal fawnage.

Whoever said life was fair?

As always, comments welcome here or on HN

Sunday, April 5, 2015

React.native isn't

While we're on the subject of terminological disasters, Facebook's react.native seems to be doing a good job of muddling the waters.

While some parts make use of native infrastructure, a lot do not:

  1. uses views as drawing results, rather than as drawing sources, has a
  2. parallel component hierarchy,
  3. ListView isn't UITableView (and from what I read, can't be),
  4. even buttons aren't UIButton instances,
  5. doesn't use responder chain, but implements something "similar", and finally,
  6. oh yes, JavaScript

None of this is necessarily bad, but whatever it is, it sure ain't "native".

What's more, the rationale given for React and the Components framework that was also just released echoes the misunderstandings Apple shows about the MVC pattern:

Mvc data event flow fb components

Just as a reminder: what's shown here with controllers pushing data to view at any time is not MVC, unless you use that to mean "Massive View Controller".

In Components and react.native, this "pushing of mutable state to the UI" is supposed to be replaced by "a (pure) function of the model". That's what a View (UIView or NSView) is, and what drawRect:: does. So next time you are annoyed by pushing data to views, instead of creating a whole new framework, just drag a Custom View from the palette into your UI and then implement the drawRect::. Creating views as a result of drawing (and/or turning components into view state mutations) is more stateful than drawRect::, not less.

Again, that doesn't mean it's bad or useless, it just means it isn't what it says on the tin. And that's a problem. From what I've heard so far, the most enthusiastic response to react.native has come from web developers who can finally code "native" apps without learning Objective-C/Swift or Java. That may or may not be useful (past experience suggests not), but it's something completely different from what the claims are.

Oh and finally, the "react" part seems to refer to "one-way reactive data flow", an even bigger terminological disaster that I will examine in a future post.

As always, comments welcome here or at HN

Friday, April 3, 2015

Model Widget Controller (MWC) aka: Apple "MVC" is not MVC

I probably should have taken more notice that time that after my question about why a specific piece of the UI code had been structured in a particular way, one of my colleagues at 6wunderkinder informed me that Model View Controller meant the View must not talk to the model, and instead the Controller is responsible for mediating all interaction between the View and the Model. It certainly didn't match the definition of MVC that I knew, so I checked the Wikipedia page on MVC just in case I had gone completely senile, but it checked out with that I remembered:
  1. the controller updates the model,
  2. the model notifies the view that it has changed, and finally
  3. the view updates itself by talking to the model
(The labeling on the graphic on the Wikipedia is a bit misleading, as it suggests that the model updates the view, but the text is correct).

What I should have done, of course, is keep asking "Why?", but I didn't, my excuse being that we were under pressure to get the Wunderlist 3.0 release out the door. Anyway, I later followed up some of my confusion about both React.native and ReactiveCocoa (more on those in a later post) and found the following incorrect diagram in a Ray Wenderlich tutorial on ReactiveCocooa and MVVC.

Hmm...that's the same confusion that my colleague had. The plot thickens as I re-check Wikipedia just to be sure. Then I had a look at the original MVC papers by Trygve Reenskaug, and yes:

A view is a (visual) representation of its model. It would ordinarily highlight certain attributes of the model and suppress others. It is thus acting as a presentation filter. A view is attached to its model (or model part) and gets the data necessary for the presentation from the model by asking questions.

The 1988 JOOP article "MVC Cookbook" also confirms:

MVC Interaction Krasner 88

So where is this incorrect version of MVC coming from? It turns out, it's in the Apple documentation, in the overview section!

Model view controller

I have to admit that I hadn't looked at this at least in a while, maybe ever, so you can imagine my surprise and shock when I stumbled upon it. As far as I can tell, this architectural style comes from having self-contained widgets that encapsulate very small pieces of information such as simple strings, booleans or numbers. The MVC architecture was not intended for these kinds of small widgets:

MVC was conceived as a general solution to the problem of users controlling a large and complex data set.
If you look at the examples, the views are large both in size and in scope, and they talk to a complex model. With a widget, there is no complex model, not filtering being done by the view. The widget contains its own data, for example a string or a number. An advantage of widgets is that you can meaningfully assemble them in a tool like Interface Builder, with a more MVC-like large view, all you have in IB is a large blank space labeled 'Custom View'. On the other hand, I've had very good experiences with "real" (large view) MVC in creating high performance, highly responsive user interfaces.

Model Widget Controller (MWC) as I like to call it, is more tuned for forms and database programming, and has problems with more reactive scenarios. As Josh Abernathy wrote:

Right now we write UIs by poking at them, manually mutating their properties when something changes, adding and removing views, etc. This is fragile and error-prone. Some tools exist to lessen the pain, but they can only go so far. UIs are big, messy, mutable, stateful bags of sadness.

To me, this sadness is almost entirely a result of using MWC rather than MVC. In MVC, the "V" is essentially a function of the model, you don't push or poke at it, you just tell it "something changed" and it redraws itself.

And so the question looms: is react.native just a result of (Apple's) misunderstanding (of) MVC?

As always, your comments are welcome here or on HN.

Thursday, March 19, 2015

Why overload operators?

One of the many things that's been puzzling me for a long time is why operator overloading appears to be at the same time problematic and attractive in languages such as C++ and now Swift. I know I certainly feel the same way, it's somehow very cool to massage the language that way, but at the same time the thought of having everything redefined underneath me fills me with horror, and what little I've seen and heard of C++ with heavy overloading confirms that horror, except for very limited domains. What's really puzzling is that binary messages in Smalltalk, which are effectively the same feature (special characters like *,+ etc. can be used as message names taking a single argument), do not seem to not have either of these effects: they are neither particularly attractive to Smalltalk programmers, nor are their effects particularly worrisome. Odd.

Of course we simply don't have that problem in C or Objective-C: operators are built-in parts of the language, and neither the C part nor the Objective part has a comparable facility, which is a large part of the reason we don't have a useful number/magnitude hierarchy in Objective-C and numeric/array libraries are't that popular: writing [number1 multipliedBy:number2] is just too painful.

Some recent articles and talks that dealt with operator overloading in Apple's new Swift language just heightened my confusion. But as is often the case, that heightened confusion seems to have been the last bit of resistance that pushed through an insight.

Anyway, here is an example from NSHipster Matt Thompson's excellent post on Swift Operators, an operator for exponentiation wrapping the pow() function:

func ** (left: Double, right: Double) -> Double {
    return pow(left, right)
}
This is introduced as "the arithmetic operator found in many programming languages, but missing in Swift [is **]". Here is an example of the difference:
pow( left, right )
left ** right
pow( 2, 3 )
2 ** 3
How come this is seen as an improvement (and to me it does)? There are two candidates for what the difference might be: the fact that the operation is now written in infix notation and that it's using special characters. Do these two factors contribute evenly or is one more important than the other. Let's look at the same example in Smalltalk syntax, first with a normal keyword message and then with a binary message (Smalltalk uses raisedTo:, but let's stick with pow: here to make the comparison similar):
left pow: right.
left ** right.
2 pow: 3.
2 ** 3.
To my eyes at least, the binary-message version is no improvement over the keyword message, in fact it seems somewhat worse to me. So the attractiveness of infix notation appears to be a strong candidate for why operator overloading is desirable. Of course, having to use operator overloading to get infix notation is problematic, because special characters generally do not convey the meaning of the operation nearly as well as names, conventional arithmetic aside.

Note that dot notation for message sends/method calls does not really seem to have the same effect, even though it could technically also be considered an infix notation:

left.pow( right)
left ** right
2.pow( 3 )
2 ** 3
There is more anecdotal evidence. In Chris Eidhof's talk on functional swift, scrub to around the 10 minute mark. There you'll find the following code with some nested and curried function calls:
let result = colorOverlay( overlayColor)(blur(blurRadius)(image))
"This does not look to nice [..] it gets a bit unreadable, it's hard to see what's going on" is the quote.
let result = colorOverlay( overlayColor)(blur(blurRadius)(image))
Having a special compose function doesn't actually make it better
let myFilter = composeFilters(blur(blurRadius),colorOverlay(overlayColor))
let result = myFilter(image)
Infix to the rescue! Using the |>operator:
let myFilter = blur(blurRadius) |> colorOverlay(overlayColor)
let result = myFilter(image)
Chris is very fair-minded about this, he mentions that due to the special characters involved, you can't really infer what |> means from looking at the code, you have to know, and having many of these sorts of operators makes code effectively incomprehensible. Or as one twitter use put it: Like most things in engineering, it's a trade-off, though my guess is the trade-off would shift if we had infix without requiring non-sensical characters.

Built in
I do believe that there is another factor involved, one that is more psychologically subtle having to do with the idea of language as a (pre-defined) thing vs. a mechanism for building your own abstractions that I mentioned in my previous post on Swift performance.

In that post, I mentioned BASIC as the primary example of the former, a language as a collection of built-in features, with C and Pascal as (early) examples of the latter, languages as generic mechanisms for building your own features. However, those latter languages don't treat all constructs equally. Specifically, all the operators are built-in, not user-definable over -overridable. They also correspond closely to those operations that are built into the underlying hardware and map to single instructions in assembly language. In short: even in languages with a strong "user-defined" component, there is a hard line between "user-defined" and "built-in", and that line just happens to map almost 1:1 to the operator/function boundary.

Hackers don't like boundaries. Or rather: they love boundaries, the overcoming of. I'd say that overloaded operators are particularly attractive (to hacker mentalities, but that's probably most of us) in languages where this boundary between user-defined and built-in stuff exists, and therefore those overloaded operators let you cross that boundary and do things normally reserved for language implementors.

If you think this idea is too crazy, listen to John Siracusa, Guy English and Rene Ritchie discussing Swift language features and operator overloading on Debug Podcast Number 49, Siracusa Round 2, starting at 45:45. I've transcribed a bit below, but I really recommend you listen to the podcast, it's very good:

  • 45:45 Swift is a damning comment on C++ [benefits without the craziness]
  • 46:06 You can't do what Swift did [putting basic types in the standard library] without operator overloading. [That's actually not true, because in Swift the operators are just syntax -> but it is exactly the idea I talked about earlier]
  • 47:50 If you're going to add something like regular expressions to the language ... they should have some operators of their own. That's a perfect opportunity for operator overloading
  • 48:07 If you're going to add features to the language, like regular expressions or so [..] there is well-established syntax for this from other languages.
  • 48:40 ...or range operators. Lots of languages have range operators these days. Really it's just a function call with two different operands. [..] You're not trying to be clever All you're trying to do is make it natural to use features that exist in many of other languages. The thing about Swift is you don't have to add syntax to the language to do it. Because it's so malleable. If you're not adding a feature, like I'm adding regular expressions to the language. If you're not doing that, don't try to get clever. Consider the features as existing for the benefit of the expansion of the language, so that future features look natural in it and not bolted on even though technically everything is in a library. Don't think of it as in my end user code I'm going to come up with symbols that combine my types in novel ways, because what are you even doing there?
  • 50:17 if you have a language like this, you need new syntax and new behavior to make it feel natural. [new behavior strings array] and it has the whole struct thing. The basics of the language, the most basic things you can do, have to be different, look different and behave different for a modern language.
  • 51:52 "using operator overloading to add features to the language" [again, not actually true]
The interesting thing about this idea of a boundary between "language things" and "user things" is that it does not align with the "operators" and "named operators" in Swift, but apparently it still feels like it does, so we "extending the language" is seen as roughly equivalent to "adding some operators", with all the sound caveats that apply.

In fact, going back to Matt Thompson's article from above, it is kind of odd that he talks about exponentiation operator as missing from the language, when if fact the operation is available in the language. So if the operation crosses the boundary from function to operator, then and only then does it become part of the language.

In Smalltalk, on the other hand, the boundary has disappeared from view. It still exists in the form of primitives, but those are well hidden all over the class hierarchy and not something that is visible to the developer. So in addition to having infix notation available for named operations, Smalltalk doesn't have the notion of something being "part of the language" rather than "just the library" just because it uses non-sensical characters. Everything is part of the library, the library is the language and you can use names or special characters as appropriate, not because of asymmetries in the language.

And that's why operator overloading is a a thing even in languages like Swift, whereas it is a non-event in Smalltalk.

Thursday, September 11, 2014

iPhone 6 Plus and The End of Pixels

It's been a long time coming. NeXTStep in 1989 featured DisplayPostscript, and therefore a device independent imaging model that meant you did not specify graphics in pixels, but rather in physical units. The default was a variant of the printer's point at 1/72nd of an inch, which happened to be close the the typical pixel resolution of displays at the time. However, 1 point never meant 1 pixel, it meant 1/72nd of an inch, and the combination of floating point coordinates and transformation matrices meant you could use pretty much any unit you wanted. When NeXT bought Apple, it brought this imaging model with it, although with some modifications due to Adobe intransigence about licensing and the addition of anti-aliasing.

However, despite the device-independent APIs, we still have pixel-based content, and "pixel-accurate" graphics. This has made less and less sense over time, with retina displays making pixel-accuracy moot (no more screen fonts!) scaled modes making it impossible and both iOS 7 and OS X 10.10 going for a more geometric look. Still, the design community has resisted, talking about @3 pixel art etc.

No more.

The iPhone 6 Plus has a 1920x1080 panel, but the simulator renders at 3x. These two resolutions don't match and so the pixels will need to be downsampled to the display resolution. Whether that is accomplished by downsampling pixel art (which happens automagically with Quartz and the proper device transform set) or as a separate step that downsamples the entire rendered framebuffer doesn't matter (much). Either way, there are no more "pixel perfect" pre-rendered designs.

Device-independent graphics, here we come at last. We're only a quarter century late.

Update: "Its 401 PPI display is the first display I’ve ever used on which, no matter how close I hold it to my eyes, I can’t perceive the pixels. " - John Gruber (emphasis mine)

Wednesday, September 10, 2014

collect is what for does

I recently stumbled on Rob Napier's explanation of the map function in Swift. So I am reading along yadda yadda when suddenly I wake up and my eyes do a double take:
After years of begging for a map function in Cocoa [...]
Huh? I rub my eyes, probably just a slip up, but no, he continues:
In a generic language like Swift, “pattern” means there’s a probably a function hiding in there, so let’s pull out the part that doesn’t change and call it map:
Not sure what he means with a "generic language", but here's how we would implement a map function in Objective-C.
#import <Foundation/Foundation.h>

typedef id (*mappingfun)( id arg );

static id makeurl( NSString *domain ) {
  return [[[NSURL alloc] initWithScheme:@"http" host:domain path:@"/"] autorelease];
}

NSArray *map( NSArray *array, mappingfun theFun )
{
  NSMutableArray *result=[NSMutableArray array];
  for ( id object in array ) {
    id objresult=theFun( object );
    if ( objresult ) {
       [result addObject:objresult];
    }
  }
  return result;
}

int main(int argc, char *argv[]) {
  NSArray *source=@[ @"apple.com", @"objective.st", @"metaobject.com" ];
  NSLog(@"%@",map(source, makeurl ));
}

This is less than 7 non-empty lines of code for the mapping function, and took me less than 10 minutes to write in its entirety, including a trip to the kitchen for an extra cookie, recompiling 3 times and looking at the qsort(3) manpage because I just can't remember C function pointer declaration syntax (though it took me less time than usual, maybe I am learning?). So really, years of "begging" for something any mildly competent coder could whip up between bathroom breaks or during a lull in their twitter feed?

Or maybe we want a version with blocks instead? Another 2 minutes, because I am a klutz:


#import <Foundation/Foundation.h>

typedef id (^mappingblock)( id arg );

NSArray *map( NSArray *array, mappingblock theBlock )
{
  NSMutableArray *result=[NSMutableArray array];
  for ( id object in array ) {
    id objresult=theBlock( object );
    if ( objresult ) {
       [result addObject:objresult];
    }
  }
  return result;
}

int main(int argc, char *argv[]) {
  NSArray *source=@[ @"apple.com", @"objective.st", @"metaobject.com" ];
  NSLog(@"%@",map(source, ^id ( id domain ) {
    return [[[NSURL alloc] initWithScheme:@"http" host:domain path:@"/"] autorelease];
        }));
}

Of course, we've also had collect for a good decade or so, which turns the client code into the following, much more readable version (Objective-Smalltalk syntax):
NSURL collect URLWithScheme:'http' host:#('objective.st' 'metaobject.com') each path:'/'.

As I wrote in my previous post, we seem to be regressing to a mindset about computer languages that harkens back to the days of BASIC, where everything was baked into the language, and things not baked into the language or provided by the language vendor do not exist.

Rob goes on the write "The mapping could be performed in parallel [..]", for example like parcollect? And then "This is the heart of good functional programming." No. This is the heart of good programming.

Having processed that shock, I fly over a discussion of filter (select) and stumble over the next whopper:

It’s all about the types

Again...huh?? Our map implementation certainly didn't need (static) types for the list, and all the Smalltalkers and LISPers that have been gleefully using higher order techniques for 40-50 years without static types must also not have gotten the memo.

We [..] started to think about the power of functions to separate intent from implementation. [..] Soon we’ll explore some more of these transforming functions and see what they can do for us. Until then, stop mutating. Evolve.
All modern programming separates intent from implementation. Functions are a fairly limited and primitive way of doing so. Limiting power in this fashion can be useful, but please don't confuse the power of higher order programming with the limitations of functional programming, they are quite distinct.

Tuesday, September 9, 2014

No Virginia, Swift is not 10x faster than Objective-C

About a month ago, Jesse Squires published a post titled Apples to Apples, documenting benchmark results that he claims show Swift now with a roughly 10x performance advantage over Objective-C. Although completely bogus, the post was retweeted by Chris Lattner (who should know better, and was supposedly mostly interested in highlighting the improvements in the Swift optimizer, rather than the bogus comparison) and has now been referenced a number of times as background knowledge as to the state of Swift. More importantly, though the actual mistake Jesse makes is pretty basic and not that interesting, it does point to some deeper misunderstandings about performance and language that I at least do find interesting.

So what's the mistake? Ironically, given the post's title, is that he is comparing apples to oranges, so to speak. The following table, which shows the time to sort an array of 10000 numbers 10 times in millisecond, illustrates the problem:

NSNumbernative integer
Objective-C6.040.97
Swift11.920.8
Jesse compared the two versions highlighted, so native Swift integers with Objective-C NSNumber object wrappers. All times are for binaries with optimization enabled, the machine was a 13" MBR with 2.9 GHz Intel Core i7 and 8GB of RAM. The integer sort was done using a C integer array and the system qsort() function. When you compare apples to apples, Objective-C has a roughly 2x edge with NSNumbers and is around 18% slower for native integers, at least when using qsort()

Why the 18% disadvantage? The qsort() function is made generically applicable to different types of arrays using a function pointer parameter for the comparison function that itself is parametrized using pointers to the elements to be compared. This means there is a per-comparison overhead of one function call and two pointer dereferences per comparison. That overhead overwhelms the actual comparison operation, which is a single machine instruction on most processors.

Swift, on the other hand, appears to produce a version of the sort function that is specialized to the integer type, with the comparison function inlined to the generated function so there is no function call or pointer dereference overhead. That is very clever and a Good Thing™ for performance. Sort of. The drawback is that this breaks separate compilation, because the functions actually have to be combined during the compile/link process every time it is used (I assume there is caching going on so we only got one per type combination).

Apart from making the compiler/linker slower , possibly significantly so (like C++ headers, though I presume they use LLVM bitcode to optimize the process), it also likely bloats the executable, causing cache and memory pressure. So it's a tradeoff, as usual, and while I think having the ability to specialize at compile-time is good, not being able to control it is not.

Objective-C doesn't have this ability to automagically adapt a function or method to parameters, if you want inlining the relationship has to be known at definition not at point of use. However, if the benefit of inlining is only 21% for the most primitive type, a machine integer, then it is clear that that the set of types for which compile-time specialization is beneficial at all is small.

Cocoa of course already provides specialized collection classes for the byte and unichar types, NSData and NSString respectively. I never quite understood why this wasn't extended to the other primitive types, particularly integer and float/double. On the other hand, the omission never bothered me much, I just implemented those classes myself in MPWFoundation. MPWRealArray even has support for DisplayPostscript binary object sequences, it's that old!

Both MPWRealArray and the corresponding MPWIntArray classes are small and fairly trivial to implement, and once I have them, using a specialized integer or real array is at least as convenient as using an NSArray, just a lot faster. They could also be quite a bit smaller than they are, sharing code either via subclassing or poor-man's generic programming via include files. Once I have a nice OO interface, I can swap out the implementation for something really quick like a dual-pivot integer sort I found in Java-land and adapted to C. (It is surprising just how similar they are at that level). With that sort, the test time drops to 0.56 ms, so 42% faster than the Swift version and almost twice as fast as the system qsort() function.

So the takeaway is that if you are using NSNumber objects in performance-sensitive code: stop. This is always a mistake. The native number types for Objective-C are int, float, double and friends, not NSNumber. After all, how do you perform arithmetic? Either directly on a primitive or by unboxing the NSNumber and then performing arithmetic on the primitive and then reboxing. Use primitive scalar types as much as possible where they make sense.

A second takeaway is that the question "which language is faster" doesn't really make sense, a more relevant and interesting question is "does this language make it hard/possible/easy to write fast code". Objective-C lets you write really fast code, if you want to, because it has the low-level chops and an understandable performance model. Swift so far can achieve reasonable performance at times, ludicrously bad at other times (especially with the optimizer turned off, which hardly fazes Objective-C), with as far as I can tell fairly little predictability or control. Having 10% faster (or slower) performance for code I don't particularly care about is not worth nearly as much as the knowledge that I can get the 1-5% of code that I do care about in shape no matter what. Swift is definitely not there yet, and given the direction it is taking I am not sure whether it will allow that kind of control, at least in comprehensible ways.

A third point is something more general about language. The whole argument that NSNumber and NSArray are "built in" somehow and int is not displays a lack of understanding of Objective-C that to me seems staggering. Even more so, the whole idea that you must only use what comes provided with Cocoa and are not allowed to build your own flies in the face of modern language design, throwing us back to the times of BASIC (Arthur Luehrmann, in the comments):

I had added graphics primitives to Dartmouth Basic around 1976 and developed an X-Y pen-plotter to carry out graphics commands mixed in with the text being sent to Teletype terminals.
The idea is that is that a language is a bundle of features, or to put it linguistically, a language is a list of words to be used as is.

Both C and Pascal introduced me to a new notion: that languages are not lists of words, but means of constructing your own words. For example, C did/does not have I/O as a language feature. I/O was just another set of functions placed in a library that you included just like any of your own functions/libraries. And there were two sets of them, the stdio package and the raw Unix I/O.

At around the same time I was introduced to both top-down and bottom-up programming. Both assume there is a recursive de-composition of the problem at hand (assuming the problem sufficiently complex to warrant it).

In bottom-up programming, you build up the vocabulary (the procedures and functions) that are necessary to succinctly describe your top-level problem, and then you describe your program in terms of that vocabulary you created. In top-down programming, you start at the other end and write your top-level program in terms of the vocabulary you wish you had to optimally describe the problem. Then you fill in the blanks.

In both, you define your own language to fit the problem, then you solve the problem using the language you defined. You would not add plotting commands to the language, you would either add plotting commands as a library or, if that were not possible, a way of adding plotting commands as a library. You would not look at whether plotting comes with the "standard library" or not. To quote Guy Steele in Growing a Language:

This is the nub of what I want to say. A language design can no longer be a thing. It must be a pattern—a pattern for growth—a pattern for growing the pattern for defining the patterns that programmers can use for their real work and their main goal.
So build your own libraries, your own abstractions. It's easy, fun and useful. It's the heart of Domain Driven Design, probably the most productive and effective software construction technique we as an industry have come up with to date. See what abstractions you can build easily and which ones are hard. Analyze the latter and you have started on the road to modern language design.

CORRECTION (June 4th 2015): I misattributed the Dartmouth BASIC quote to Cathy Doser, when the comment line on the Macintosh folklore entry clearly said Arthur Luehrmann. (Cathy's comment was a bit earlier).

Saturday, August 30, 2014

So how are those special Swift initializers working out?

Splendidly:
If you're building a UIView subclass that needs to set up a mess of subviews this can get old really quick. Best option I've found so far? Just initialize them with a default value like you would a regular variable. Now the compiler's off your back and and you can move on with your life, or at least what's left of it after choosing software development as a career.
Justin Driscoll

This is something people who create elaborate mechanisms to force people to "Do the Right Thing" never seem to understand: they hardly ever achieve what they are trying to achieve. Instead, people will do the minimal amount of work to get the compiler off their backs. Compare Java's checked exceptions.

Friday, July 11, 2014

Overspeccing

I just took my car to its biennial TüV inspection and apart from the tires that had simply worn out everything was A-OK, nothing wrong at all. Kind of surprising for a 7 year old mechanical device that has been used: daily commute from Mountain View to Oakland, tight cornering in the foothills, shipped across the Atlantic twice and now that it is back in its native country, occasional and sometimes prolonged sprints at 200 km/h. All that with not all that much maintenance, because the owner is not exactly a car nut.

Cars used to not be nearly this reliable, and getting there wasn't easy, it took the industry both plenty of time and a lot of effort. It's not that the engineers didn't know how to build reliable cars, but making them reliable and keeping them affordable and still allowing car companies to turn a profit, that was hard.

One particular component is the alternator belt, which had to be changed so frequently that engine compartments were specially designed to make the belt easily accessible. That's no longer the case, and the characteristic screeching sound of a worn belt is one that I haven't heard in a long time.

My late dad, who was in the business, told me how it went down, at least at Volkswagen. As other problems had been whittled away over the decades, alternator belts were becoming a real issue on the reliability reports compiled by motoring magazines, and the engineers were tasked with the job of fixing the problem. And fix it they did: they came up with a design that would "never" break or wear out, and no I don't know the details of how that was supposed to work.

Problem was: it was a tad expensive. Much more expensive than the existing solution and simply too expensive for the price bracket they were aiming for (this may seem odd to outsiders considering the total cost of a car, but pennies matter). Which of course was one reason why they had put up with unreliable belts for so long. Then word came in that the Japanese had solved the problem as well, and were offering it on their cheap(er) models. Next auto-show, they went to the both of one of those Japanese companies and popped the hood.

The engineers scoffed: the design the Japanese was cheaper because it was much, much more primitive than the one they had come up with, and it would, in fact, also wear out much more quickly. But exactly how much more quickly would it wear out? In other words, what was the expected lifetime of this cheaper, inferior alternator belt design?

About the expected lifetime of the car.

Ahh. As far as I can tell, the Japanese design or variants thereof conquered the world. I can't recall the last time I heard the screech of a worn out belt, engine compartments these days are not designed with accessibility in mind and cars are still affordable, although changing the belt if it does break will cost more in labor because of the less accessible placement.

What do alternator belts have to do with software development? Probably nothing, but to me at least, the situation reminds me of the one I write about in The Safyness of Static Typing. I am actually with those commenters who scoffed at the idea that the safety benefit of static typing is only around 2%, because theoretically having a tight specification of possible values checked at compile-time absolutely should bring a greater benefit.

For example, when static typing and protocols were introduced to Objective-C, I absolutely expected them to catch my errors, so I was quite surprised when it turned out that in practice they didn't: because I could actually compile/run/test my code without having to specify static types, by the time I added static types the code simply no longer had type errors, because the vast majority of those were caught by running it. The dynamic safety also helped, because instead of a random crash, I got a nice clean error message "object abc doesn't understand message xyz".

My suspicion is that although dynamic typing and the practices that go with it may only be, let's say, 50% as good at catching type errors as a good static type system, they are actually 98% effective at catching real world type errors. So if static type systems are twice as good, they would be 196% effective at catching real world type errors, which just like the perfect, german-engineered alternator belts, is simply more than is actually needed (96% more with my hypothetical numbers).

There are obviously other factors at play, but I think this may account for a good part of the perceived discrepancy.

What do you think? Comments welcome here or on Hacker News.

Saturday, June 28, 2014

Compiler Writers Gone Wild: ARC Madness

In this week's episode of CWGW: This can't possibly crash, yet crash it does.

In a project I am currently working on, the top crash for the last week or so has been the following NSOutlineView delegate method:

- (BOOL)outlineView:(NSOutlineView *)outlineView isGroupItem:(id)item
{
    return NO;
}
The team had been ignoring it, because it just didn't make any sense and they had other things to do. (Fortunately not too many other crashes, the app is pretty solid at this point). When they turned to me, I was also initially puzzled, because all this should do on x86 is stuff a zero into %eax and return. This cannot possibly crash[1], so everyone just assumed that the stack traces were off, as they frequently are.

Fortunately I had just looked at the project settings and noticed that we were compiling with -O0, so optimizations disabled, and my suspicion was that ARC was doing some unnecessary retaining. That suspicion turned out to be on the money, otool -Vt revealed that ARC had turned our innocuous return NO; into the following monstrosity:

-[SomeOutlineViewDelegeate outlineView:isGroupItem:]:
00000001001bfdb0        pushq   %rbp
00000001001bfdb1        movq    %rsp, %rbp
00000001001bfdb4        subq    $0x30, %rsp
00000001001bfdb8        leaq    -0x18(%rbp), %rax
00000001001bfdbc        movq    %rdi, -0x8(%rbp)
00000001001bfdc0        movq    %rsi, -0x10(%rbp)
00000001001bfdc4        movq    $0x0, -0x18(%rbp)
00000001001bfdcc        movq    %rax, %rdi
00000001001bfdcf        movq    %rdx, %rsi
00000001001bfdd2        movq    %rcx, -0x30(%rbp)
00000001001bfdd6        callq   0x10027dbaa             ## symbol stub for: _objc_storeStrong
00000001001bfddb        leaq    -0x20(%rbp), %rdi
00000001001bfddf        movq    $0x0, -0x20(%rbp)
00000001001bfde7        movq    -0x30(%rbp), %rsi
00000001001bfdeb        callq   0x10027dbaa             ## symbol stub for: _objc_storeStrong
00000001001bfdf0        leaq    -0x20(%rbp), %rdi
00000001001bfdf4        movabsq $0x0, %rsi
00000001001bfdfe        movl    $0x1, -0x24(%rbp)
00000001001bfe05        callq   0x10027dbaa             ## symbol stub for: _objc_storeStrong
00000001001bfe0a        movabsq $0x0, %rsi
00000001001bfe14        leaq    -0x18(%rbp), %rax
00000001001bfe18        movq    %rax, %rdi
00000001001bfe1b        callq   0x10027dbaa             ## symbol stub for: _objc_storeStrong
00000001001bfe20        movb    $0x0, %r8b
00000001001bfe23        movsbl  %r8b, %eax
00000001001bfe27        addq    $0x30, %rsp
00000001001bfe2b        popq    %rbp
00000001001bfe2c        retq
00000001001bfe2d        nopl    (%rax)
Yikes! Of course, this is how ARC works: it generates an insane amount of retains and releases (hidden inside objc_storeStrong()), then relies on a special optimization pass to remove the insanity and leave behind the necessary retains/releases. Turn on the "standard" optimization -Os and we get the following, much more reasonable result:
-[WLTaskListsDataSource outlineView:isGroupItem:]:
00000001000e958a        pushq   %rbp
00000001000e958b        movq    %rsp, %rbp
00000001000e958e        xorl    %eax, %eax
00000001000e9590        popq    %rbp
00000001000e9591        retq
Much better!

It isn't clear why those retains/releases were crashing, all the objects involved looked OK in the debugger, but at least we will no longer be puzzled by code that can't possibly crash...crashing, and therefore have a better chance of actually debugging it.

Another issue is performance. I just benchmarked the following equivalent program:

#import 

@interface Hi:NSObject {}
-(BOOL)doSomething:arg1 with:arg2;
@end

@implementation Hi
-(BOOL)doSomething:arg1 with:arg2
{
  return NO;
}
@end

int main( int argc, char *argv[] ) 
{
  Hi *hi=[Hi new];
  for (int i=0;i < 100000000; i++ ) {
    [hi doSomething:hi with:hi];
  } 
  return 0;
}
On my 13" MBPR, it runs in roughly 0.5 seconds with ARC disabled and in 13 seconds with ARC enabled. That's 26 time slower, meaning we now have a highly non-obvious performance model, where performance is extremely hard to predict and control. The simple and obvious performance model was one of the main reasons Objective-C code tended to actually be quite fast if even minimal effort was expended on performance, despite the fact that some parts of Objective-C aren't all that fast.

I find the approach of handing off all control and responsibility to the optimizer writers worrying. My worries stem partly from the fact that I've never actually had that work in the past. With ARC it also happens that the optimizer can't figure out a retain/release isn't needed, so you need to sprinkle a few __unsafe_unretains throughout your code (not many, but you need to figure out which).

Good optimization has always been something that needed a human touch (with automatic assistance), the message "just trust the compiler" doesn't resonate with me. Especially since, and this is the other part I am worried about, compiler optimizations have been getting crazier and crazier, clang for example thinks there is nothing wrong with producing two different values for de-referencing the same pointer (at the same time, with no stores in-between (source: http://blog.regehr.org/archives/767):

#include 
#include 
 
int main() {
  int *p = (int*)malloc(sizeof(int));
  int *q = (int*)realloc(p, sizeof(int));
  *p = 1;
  *q = 2;
  if (p == q)
    printf("%d %d\n", *p, *q);
}
I tested this with clang-600.0.34.4 on my machine and it also gives this non-sensical result: 1 2. There are more examples, which I also wrote about in my post cc -Osmartass. Of course, Swift moves further in this direction, with expensive default semantics and reliance on the compiler to remove the resulting glaring inefficiencies.

In what I've seen reported and tested myself, this approach results in differences between normal builds and -Ofast-optimized builds of more than a factor of 100. That's not close to being OK, and it makes code much harder to understand and optimize. My guess is that we will be looking at assembly a lot more when optimizing Swift than we ever did in Objective-C, and then scratching our heads as to why the optimizer didn't manage to optimize that particular piece of code.

I fondly remember the "Java optimization" WWDC sessions back when we were supposed to rewrite all our code in that particular new hotness. In essence, we were given a model of the capabilities of HotSpot's JIT optimizer, so in order to optimize code we had to know what the resulting generated code would be, what the optimizer could handle (not a lot), and then translate that information back into the original source code. At that point, it's simpler to just write yourself the assembly that you are trying to goad the JIT into emitting for you. Or portable Macro Assembler. Or object-oriented portable Macro Assembler.

Well it could if the stack had previously reached its limit
Discuss here or on HN

Thursday, June 26, 2014

How to Swiftly Destroy a $370 Million Dollar Rocket with Overflow "Protection"

Apple's new Swift programming language has been heavily promoted as being a safer alternative to Objective-C, with a much stronger emphasis on static typing, for example. While I am dubious about the additional safety of static typing, I argue that it produces far more safyness than actual safety, this post is going to look at a different feature: overflow protection.

Overflow protection means that when an arithmetic operation on an integer exceeds the maximum value for that integer type, the value doesn't wrap around as it does on most CPU ALUs, and by extension C. Instead the program signals an exception and since Swift has no exception handling the program crashes.

While this looks a little like the James Bond anti theft device in For Your Eyes Only, which just blows up the car, the justification is that the program should be protected from operating on values that have become bogus. While I understand the reasoning, I am dubious that it really is safer to have every arithmetic operation on integers and every conversion from higher precision to lower in the entire program become a potential crash site, when before those operations could never crash (except for division by zero).

While it would be interesting to see what evidence there is for this argument, I can give at least one very prominent example against it. On June 4th 1996, ESA's brand new Ariane 5 rocket blew up during launch, due to a software fault, with a total loss of US $370 million, apparently one of the most expensive software faults in history. What was that software fault? An overflow protection exception triggered by a floating point to (short) integer conversion.

The resulting core-dump/diagnostics were then interpreted by the next program in line as valid data, causing effectively random steering inputs that caused the rocket to break up (and self destruct when it detected it was breaking up).

What's interesting is that almost any other handling of the overflow apart from raising an exception would have been OK and saved the mission and $370 million. Silently truncating/clamping the value to the maximum permissible range (which some in the static typing community incorrectly claim was the problem) would have worked perfectly and was the actual solution used for other values.

Even wraparound might have worked, at least there would have been only one bogus transition after which values would have been mostly monotonic again. Certainly better than effectively random values.

Ideally, the integer would have just overflowed into a higher precision as in a dynamic language such as Smalltalk, or even Postscript. Even JavaScript's somewhat wonky idea that all numbers are floats, but some just don't know it yet would have been better in this particular case. Considering the limitations of the hardware those languages weren't options, but nowadays the required computational horsepower is there.

In Ada you at least could potentially trap the exception generated by overflow, but in Swift the only protection is to manually trace back the inputs of every arithmetic operation on integers and enforce ranges for all possible combinations of inputs that do not result in that operation overflowing. For any program with external inputs and even slightly complex data paths and arithmetic, I would venture to say that that is next to impossible.

The only viable method for avoiding arithmetic overflow is to not use integer arithmetic with any external input, ever. Hello JavaScript!

You can try the Ada code with GNAT, or online:

with Ada.Text_IO,Ada.Integer_Text_IO;
use Ada.Text_IO,Ada.Integer_Text_IO;
procedure Hello is
  b : FLOAT;
  a : INTEGER;
begin
  b:=3123123.0;
  b:=b*b;
  a:=INTEGER(b);
  
  Put("a=");
  Put(a);
end Hello;
You can watch your Swift playground crash using the following code:

var a = 2
var b:Int16
for i in 1..100 {
  a=a*2
  println(a)
  b=Int16(a)
}
Note that neither the Ada nor Swift compilers have static checks that detect the overflow, even when all the information is statically available, for example in the following Swift code:

var a:UInt8
a = 254
println(a)
a += 2
println(a)
What's even worse is that the -Ofast flag will remove the checks, the integer will just wrap around. Optimization flags in general should not change visible program behavior, except for performance. Or maybe this is good, since it looks like we need that flag to get decent performance at all, we also remove the overflow crashers...

Discuss here or on Hacker News.