Live data from Hacker News

Why is Rosetta 2 fast?

dougallj.wordpress.com

301–310 of 367 posts

Re: Why is Rosetta 2 fast?

#301

Earlier quoted context omitted.

I think I landed in a place where it's basically "the compiler has insufficient information to achieve ideal optimization because some things can only be known at runtime." Which is not exclusively an argument for runtime JIT— it can also be an argument for instrumenting your runtime environment, and feeding that profiling data back to the compiler to help it make smarter decisions the next time. But that's definitel…

The problem with JIT is not all information known at runtime is the correct information to optimize one. In finance the performance critical code path is often the one run least often. That is you have a if(unlikely_condition) {run_time_sensitive_trade();}. In this case you need to tell the compiler to ensure the CPU will have a pipeline stall because of a branch misprediction most of the time to ensure the time that…

> In finance

Isn't low-latency trading only a subset of finance?

Re: Why is Rosetta 2 fast?

#302

Earlier quoted context omitted.

How does the compiler arrange for the CPU to mispredict the branch most of the time? I didn't think there were any knobs for the branch predictor other than static ones (e.g. backwards-jumps statically predicted as taken, or PowerPC branch hint bit).

C++20 is gaining the [[likely]] attribute for guiding the predictor in a portable way: http://eel.is/c++draft/dcl.attr.likelihood Prior to this it was also possible, but required compiler-specific macros like GCC's __builtin_expect, which is used all over the kernel: https://github.com/torvalds/linux/search?q=__builtin_expect

20 years of "progress" and hey, C++20 is gaining the likely attribute.

Re: Why is Rosetta 2 fast?

#303

Earlier quoted context omitted.

How does the compiler arrange for the CPU to mispredict the branch most of the time? I didn't think there were any knobs for the branch predictor other than static ones (e.g. backwards-jumps statically predicted as taken, or PowerPC branch hint bit).

C++20 is gaining the [[likely]] attribute for guiding the predictor in a portable way: http://eel.is/c++draft/dcl.attr.likelihood Prior to this it was also possible, but required compiler-specific macros like GCC's __builtin_expect, which is used all over the kernel: https://github.com/torvalds/linux/search?q=__builtin_expect

There are no ways to hint the branch predictor on some common CPUs. I think Intel says it's fully dynamic and has no static predictions.

If you want to cause a pipeline stall, there's usually serializing instructions like cpuid/eieio.

Re: Why is Rosetta 2 fast?

#304

Earlier quoted context omitted.

The problem with static compilation is not all information known at compile time is the correct information to optimize on. Assuming either source of data is the single source of truth for all optimizations is a fallacy. Use the right tool for the right job. Use all the tools if you can.

Static compilers usually don't have to make such a tradeoff, though. They are free to spend arbitrarily long amounts of time optimizing all branches. And they often do exactly that. Static + LTO w/ PGO is pretty much the practical ideal. JITs don't offer much until you start adding dynamically loaded code where LTO just isn't possible anymore.

If your hardware is designed to allow very lightweight profiling and tracing, then static + LTO w/ PGO can still be improved by runtime re-optimization. If designed properly, the runtime overhead can be brought arbitrarily low by increasing the sampling period.

Re: Why is Rosetta 2 fast?

#305
post #56

Earlier quoted context omitted.

I eventually changed my opinion into JIT being the only way to make dynamic languages faster, while strong typed ones can benefit from having both AOT/JIT for different kinds of deployment scenarios, and development workflows.

Before I talked myself out of writing my own programming language, I used to have lunch conversations with my mentor who was also speed obsessed about how JIT could meet Knuth in the middle by creating a collections API with feedback guided optimization, using it for algorithm selection and tuning parameters by call site. For object graphs in Java you can waste exorbitant amounts of memory by having a lot of “childre…

Swift and Objective-C have collections that change implementation as needed, but they can do it because they're well abstracted (enough) and usually immutable so there's less chance of making a bad assumption.

Most other languages only have mutable collections, and name collection types after their implementation details instead of what the user actually wants from them.

Re: Why is Rosetta 2 fast?

#306
post #15

I remember years ago when Java adjacent research was all the rage, HP had a problem that was “Rosetta lite” if you will. They had a need to run old binaries on new hardware that wasn’t exactly backward compatible. They made a transpiler that worked on binaries. It might have even been a JIT but that part of the memory is fuzzy. What made it interesting here was that as a sanity check they made an A->A mode where they…

>"I remember years ago when Java adjacent research was all the rage, ..."

What is meant by "Java adjacent research"? I'm not familiar with what that was.

Re: Why is Rosetta 2 fast?

#307

Earlier quoted context omitted.

C++20 is gaining the [[likely]] attribute for guiding the predictor in a portable way: http://eel.is/c++draft/dcl.attr.likelihood Prior to this it was also possible, but required compiler-specific macros like GCC's __builtin_expect, which is used all over the kernel: https://github.com/torvalds/linux/search?q=__builtin_expect

There are no ways to hint the branch predictor on some common CPUs. I think Intel says it's fully dynamic and has no static predictions. If you want to cause a pipeline stall, there's usually serializing instructions like cpuid/eieio.

I believe intel used to always predict forward branches not taken and backward branches always taken if it didn’t have any history.

Regardless, you can at least lay out code in a way that heavily favors one branch over the other, and potentially optimize for one branch (I.e. give one branch very expensive prelude/exit to make another branch very cheap). The last thing I’ve seen compilers greatly struggle with though…

Re: Why is Rosetta 2 fast?

#308
post #26
post #16

Earlier quoted context omitted.

What important Intel-only macOS software is going to exist in five years? It's basically only games and weird tiny niches, and Apple is pretty happy to abandon both those categories. The saving grace is that there's very few interesting Mac-exclusive games in the Intel era.

Yeah, Apple killed all "legacy" 32-bit support, so one would think there's not much software which is both x86-64 and not being actively developed.

Rosetta 2 can run 32-bit software, there just isn't a 32-bit macOS anymore so the only client is WINE.

Re: Why is Rosetta 2 fast?

#309

Earlier quoted context omitted.

Something that fascinates me about this kind of A -> A translation (which I associate with the original HP Dynamo project on HPPA CPUs) is that it was able to effectively yield the performance effect of one or two increased levels of -O optimization flag. Right now it's fairly common in software development to have a debug build and a release build with potentially different optimisation levels. So that's two builds…

One of the engineers I was working with on a project was from Transitive (the company that made QuickTransit which became Rosetta) found that their JIT based translator could not deliver significant performance increases for A->A outside of pathological cases, and it was very mature technology at the time. I think it's a hypothetical. The Mill Computing lectures talk about a variant of this, which is sort of equivale…

>"The Mill Computing lectures talk about a variant of this ..."

Might you or someone else have a link those Mill Computing lectures?

Re: Why is Rosetta 2 fast?

#310

I wonder if such a direct translation from ARM to another architecture would even be possible given that the instruction set can be changed at runtime (thumb mode). Does anybody know how often typical ARM32 programs execute this mode switching or if such sections can be recognized statically?

x86 is worse because you can jump into the middle of instructions. In that case you just fall back to JIT though.

And luckily AArch64 doesn't have Thumb.

Post reply on HN