News for hackers. Stuff that matters.
Re:Why is Rosetta 2 fast? by hinkley on Wednesday November 09, 2022 @11:27AM (#33533920)
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 took in one architecture and spit out machine code for the same architecture. The output was faster than the input. Meaning that even native code has some room for improvement with JIT technology.

I have been wishing for years that we were in a better place with regard to compilers and NP complete problems where the compilers had a fast mode for code-build-test cycles and a very slow incremental mode for official builds. I recall someone telling me the only thing they liked about the Rational IDE (C and C++?) was that it cached precompiled headers, one of the Amdahl’s Law areas for compilers. If you changed a header, you paid the recompilation cost and everyone else got a copy. I love whenever the person that cares about something gets to pay the consequence instead of externalizing it on others.

And having some CI machines or CPUs that just sit around chewing on Hard Problems all day for that last 10% seems to be to be a really good use case in a world that’s seeing 16 core consumer hardware. Also caching hints from previous runs is a good thing.

Re:Why is Rosetta 2 fast? by wmf on Wednesday November 09, 2022 @11:34AM (#33534018)
Re:Why is Rosetta 2 fast? by travisgriggs on Wednesday November 09, 2022 @11:49AM (#33534270)
It was particularly poignant at the time because JITed languages were looked down on by the “static compilation makes us faster” crowd. So it was a sort of “wait a minute Watson!” moment in that particular tech debate.

No one cares as much now days, we’ve moved our overrated opinion battlegrounds to other portions of what we do.

Re:Why is Rosetta 2 fast? by pjmlp on Wednesday November 09, 2022 @12:01PM (#33534479)
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.
Re:Why is Rosetta 2 fast? by mikepurvis on Wednesday November 09, 2022 @01:00PM (#33535416)
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 definitely a more involved process than just baking it into the same JavaScript interpreter used by everyone— likely well worth it in the case of things like game engines, though.

Re:Why is Rosetta 2 fast? by masklinn on Wednesday November 09, 2022 @01:41PM (#33536004)
It's also an argument for having much more expressive and precise type systems, so the compiler has better information.

Once you've managed to debug the codegen anyway (see: The Long and Arduous Story of Noalias).

Re:Why is Rosetta 2 fast? by mikepurvis on Wednesday November 09, 2022 @04:34PM (#33538215)
Is it? I'd love to see a breakdown of what classes of information can be gleaned from profile data, and how much of an impact each one has in isolation in terms of optimization.

Naively, I would have assumed that branch information would be most valuable, in terms of being able to guide execution toward the hot path and maximize locality for the memory accesses occurring on the common branches. And that info is not something that would be assisted by more expressive types, I don't think.

Re:Why is Rosetta 2 fast? by bluGill on Wednesday November 09, 2022 @03:17PM (#33537252)
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 counts the pipeline doesn't stall.

The above is a rare corner case for sure, but it is one of those weird exceptions you always need to keep in mind when trying to make any blanket rule.

Re:Why is Rosetta 2 fast? by dahfizz on Wednesday November 09, 2022 @03:59PM (#33537748)
The other issue with JIT is that it is unreliable. It optimizes code by making assumptions. If one of the assumptions is wrong, you pay a large latency penalty. In my field of finance, having reliably low latency is important. Being 15% faster on average, but every once in a while you will be really slow, is not something customers will go for.
Re:Why is Rosetta 2 fast? by bluGill on Thursday November 10, 2022 @08:46AM (#33546276)
I'm not in finance. I just remember one talk by a finance guy and it was a mind bender so I remember it.
Re:Why is Rosetta 2 fast? by ridiculous_fish on Wednesday November 09, 2022 @07:06PM (#33540148)
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).
Re:Why is Rosetta 2 fast? by bluGill on Wednesday November 09, 2022 @07:39PM (#33540510)
CPUs have documentation, for this. I forget which one, but the one I did read it was as simple as the true case is assumed more common, and it is easy to arrange logic around that (I probably mis remember, but close enough to that). The common case also should be near the if in memory (inline code), so it is likely on the same cache line (or the next which is prefetched), while the other case is farther away and so you can stall the cache if the if goes that way.
Re:Why is Rosetta 2 fast? by mikepurvis on Wednesday November 09, 2022 @07:57PM (#33540686)
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

Re:Why is Rosetta 2 fast? by wumpus on Thursday November 10, 2022 @12:14AM (#33542526)
20 years of "progress" and hey, C++20 is gaining the likely attribute.
Re:Why is Rosetta 2 fast? by astrange on Thursday November 10, 2022 @12:28AM (#33542611)
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? by vgatherps on Thursday November 10, 2022 @12:34AM (#33542661)
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? by menaerus on Tuesday November 15, 2022 @01:06PM (#33612745)
To my knowledge this does not have any direct impact to the CPU branch prediction mechanism. If that had been the case then we would at least have some x86-(64) instruction to manipulate with the BP. If I write a quick example such as https://godbolt.org/z/j7Y81j5fe, I also see no such instruction in the generated output.

But what likely/unlikely mechanism can do is that it can serve as a hint to the compiler which the compiler can then use to generate more optimal code layout. For example, if we provide the compiler with likely/unlikely hints in our code, compiler will try to use that hint to stitch together the more probable code paths first. In theory this approach should result with better utilization of CPU instruction cache and thus it may lead to better performance.

Re:Why is Rosetta 2 fast? by travisgriggs on Wednesday November 09, 2022 @08:15PM (#33540848)
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.

Re:Why is Rosetta 2 fast? by kllrnohj on Wednesday November 09, 2022 @09:14PM (#33541311)
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.

Re:Why is Rosetta 2 fast? by KMag on Thursday November 10, 2022 @12:28AM (#33542614)
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? by kllrnohj on Thursday November 10, 2022 @10:50AM (#33548196)
Are you speaking in theoreticals or can you point to any actual example of what you're describing? Usually for a JIT to work the source binary has to be unoptimized to begin with, otherwise information is lost that the JIT needs.

So What language/runtime out there ships unoptimized bytecode, an optimized precompiled static + LTO w/ PGO, and can re-optimize with runtime gathered information via a JIT?

Heck, what language/runtime is even designed around being performance-focused with a JIT to deliver even more performance in the first place? Pretty much ever JIT'd language makes trade-offs that sacrifice up-front performance and later hopes the JIT can claw some of it back. maybe this is kinda WASM-ish territory, although it then sacrifices up-front performance for security and hopes the JIT can claw it back.

Re:Why is Rosetta 2 fast? by KMag on Thursday November 10, 2022 @01:38PM (#33551087)
The basic elements all exist.

As others have pointed out, HP's Dynamo managed to use runtime re-optimization to improve performance of many binaries without cooperation from the original compiler. Runtime optimization doesn't strictly require any of the information lost in optimized binary builds.

Last I checked, the Android Runtime would AoT-compile Dalvik bytecode at install time, and in the background re-optimize the binary based on profiling information. Though, I don't think it performs hot code replacement.

I'm not sure the latest with Oracle's Java AoT. Last I checked, Oracle's JVM wasn't able to inline or re-optimize AoT-compiled code through JIT'd code.

Some optimizations, such as loop unrolling make JIT'ing harder. However, strength reduction, loop-invariant code hoisting, etc. make the JIT's life easier. Back around 2005-2006, my employer was getting good mileage out of a Java bytecode optimizer. If your AoT and JIT are cooperating, the AoT can stuff any helpful metadata (type information, aliasing analysis, serialized control flow graph, etc.) into an auxiliary section of the binary.

I'd like to eventually write a C compiler that essentially compiles to old-school threaded code: arrays of pointers to basic blocks (strait-line code with a single entry point and one or more exit points). Function entry would just pass the array of basic blocks to a trampoline function that calls the first basic block. Each basic block would return and index into the function's array of basic blocks for the trampoline to call next. Function return would be signaled by a basic block returning -1 to the trampoline loop. A static single assignment representation of each extended basic block would be stashed in an auxiliary ELF section. On a regular system without the runtime optimizer, the only startup overhead would be due to bloated binary size. A wild guess at the performance overhead without the runtime optimizer would be in the 5% to 15% range. However, on a system with the ELF dynamic loader replaced with a runtime-optimizer, the runtime would set up a perf signal handler that would keep counters for identifying hotspots to trace. If the tracing conditions were met, the perf signal handler would walk back up the call stack to find the last occurrence of the address of the trampoline, and replace it with a version of the trampoline that in addition, stores the address of the next extended basic block to run. Once a trace loops back on itself or meets some other TBD criteria, the runtime would stitch together the SSA representations of the constituent extended basic blocks, and generate a new optimized basic block that's the inline of the components of the trace, and finally place the address of the new extended basic block in the correct place in the array of extended basic blocks, thus performing runtime code replacement. Anyway, that's my grand vision. I've taken the introductiory Stanford compilers course, and am slowly working my way forward, but I have a job and a young kid, so I'm not holding my breath.

Re:Why is Rosetta 2 fast? by pjmlp on Thursday November 10, 2022 @01:27AM (#33542980)
Tooling and real data sets.

Most PGO for AOT scenarios suffers from tooling experience and not using data sets similar to production workflows.

Re:Why is Rosetta 2 fast? by kllrnohj on Thursday November 10, 2022 @10:44AM (#33548095)
Perhaps, but that's orthogonal. JITs don't just come with ideal production set sampling either after all. They only capture snippets, and rarely re-optimize already compiled functions in the face of changing workloads or new information. You can do crowd-sourced profiles (like Android does), but that's a completely independent set of infrastructure from JIT vs. AOT. You can feed that same profile to PGO for AOT. In fact, that's how Android uses it. They don't feed the profile to the JIT, they feed it to their offline, install-time or idle-maintenance AOT compiler.
Re:Why is Rosetta 2 fast? by wumpus on Thursday November 10, 2022 @12:13AM (#33542519)
> In finance

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

Re:Why is Rosetta 2 fast? by bluGill on Thursday November 10, 2022 @08:45AM (#33546267)
Yes. And the part I mentioned is a subset of low latency. See the other reply.
Re:Why is Rosetta 2 fast? by titzer on Wednesday November 09, 2022 @04:04PM (#33537801)
Darn it, replied too early. See sibling comment I just posted. The problem with dynamic languages is that you need to speculate and be ready to undo that speculation.
Re:Why is Rosetta 2 fast? by anyfoo on Wednesday November 09, 2022 @06:49PM (#33539933)
That's a lesson Intel had to (re-?)learn with Itanium as well.
Re:Why is Rosetta 2 fast? by inkyoto on Wednesday November 09, 2022 @07:46PM (#33540588)
> […] "the compiler has insufficient information to achieve ideal optimization because some things can only be known at runtime."

This is where the profile guided optimisation comes in – for statically compiled languages, with a caveat being not always straightforward to come up with a set of inputs that will trigger an execution of all possible code paths. One solution is to provide the coverage specifically for the performance critical code paths and let the rest just be.

Re:Why is Rosetta 2 fast? by funstuff007 on Wednesday November 09, 2022 @08:51PM (#33541115)
> it can also be an argument for instrumenting your runtime environment

Aren't JITs already self-instrumenting? What would you instrument that the JIT is not already keeping track of?

Re:Why is Rosetta 2 fast? by titzer on Wednesday November 09, 2022 @04:03PM (#33537794)
Dynamic languages need inline caches, type feedback, and fairly heavy inlining to be competitive. Some of that can be gotten offline, e.g. by doing PGO. But you can't, in general, adapt to a program that suddenly changes phases, or rebinds a global that was assumed a constant, etc. Speculative optimizations with deopt are what make dynamic languages fast.
Re:Why is Rosetta 2 fast? by hinkley on Wednesday November 09, 2022 @04:28PM (#33538132)
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 “children” members that are sized for a default of 10 entries but the normal case is 0-2. I once had to deoptimize code where someone tried to do this by hand and the number they picked was 6 (just over half of the default). So when the average jumped to 7, then the data structure ended up being 20% larger than the default behavior instead of 30% smaller as intended.

For a server workflow, having data structured tuned to larger pools of objects with more complex comparison operations can also be valuable, but I don’t want that kitchen sink stuff on mobile or in an embedded app.

I still think this is viable, but only if you are clever about gathering data. For instance the incremental increase in runtime for telemetry data is quite high on the happy path. But corner cases are already expensive, so telemetry adds only a few percent there instead of double digits.

The nonstarter for this ended up being that most collections APIs violate Liskov, so you almost need to write your own language to pick a decomposition that doesn’t. Variance semantics help a ton but they don’t quite fix LSP.

Re:Why is Rosetta 2 fast? by astrange on Thursday November 10, 2022 @12:30AM (#33542629)
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? by pjmlp on Thursday November 10, 2022 @02:09AM (#33543222)
That is in a sense what JIT caching with PGO feedback loop does to a certain extent.

As for mobile, this isn't far off from the whole set of hand written Assembly interpreter, JIT with PGO data caching, AOT compilation on idle with the PGO collected data, sharing PGO metadata with other devices via the PlayStore, that Android happens to do since version 7, and refined later.

Re:Why is Rosetta 2 fast? by saagarjha on Wednesday November 09, 2022 @02:11PM (#33536424)
I take it you are not very familiar with the website known as Hacker News.
Re:Why is Rosetta 2 fast? by kllrnohj on Wednesday November 09, 2022 @09:09PM (#33541274)
I think you're over estimating the impact or relevance of that anecdote. Particularly since the "static compilation makes us faster" crowd turned out to be correct, and people use JITs for non-performance reasons and just pay the performance tax they so often come with. The time-constrained nature in which a JIT has to run just largely kills it's theoretical runtime information gathering advantages. Devirtualization remains about the most advanced trick in the JIT book, which is generally not an issue static compiled languages struggle with in the first place.
Re:Why is Rosetta 2 fast? by pjmlp on Thursday November 10, 2022 @02:17AM (#33543257)
Sure, because everyone ships static linked binaries.
Re:Why is Rosetta 2 fast? by jeffbee on Wednesday November 09, 2022 @11:55AM (#33534365)
Post-build optimization of binaries without changing the target CPU is common. See BOLT https://github.com/facebookincubator/BOLT
Re:Why is Rosetta 2 fast? by freedomben on Wednesday November 09, 2022 @12:28PM (#33534905)
If JIT-ing a statically compiled input makes it faster, does that mean that JIT-ing itself is superior or does it mean that the static compiler isn't outputting optimal code? (real question. asked another way, does JIT have optimizations it can make that a static compiler can't?)
Re:Why is Rosetta 2 fast? by vips7L on Wednesday November 09, 2022 @12:49PM (#33535243)
Yes, the JIT has more profile guided data as to what your program actually does at runtime, therefore it can optimize better.
Re:Why is Rosetta 2 fast? by gpderetta on Wednesday November 09, 2022 @12:57PM (#33535364)
On the other hand some optimization are so expensive that a JIT just doesn't have the execution budget to perform them.

Probably the optimal system is an hybrid iterative JIT/AOT compiler (which incidentally was the original objective of LLVM).

Re:Why is Rosetta 2 fast? by andrewaylett on Wednesday November 09, 2022 @12:55PM (#33535341)
It depends on what the JIT does exactly, but in general yes a JIT may be able to make optimisations that a static compiler won't be aware of because a JIT can optimise for the specific data being processed.

That said, a sufficiently advanced CPU could also make those optimisations on "static" code. That was one of the things Transmeta had been aiming towards, I think.

Re:Why is Rosetta 2 fast? by kmeisthax on Wednesday November 09, 2022 @12:59PM (#33535394)
It's more the case that the ahead-of-time compilation is suboptimal.

Modern compilers have a thing called PGO (Profile Guided Optimization) that lets you take a compiled application, run it and generate an execution profile for it, and then compile the application again using information from the profiling step. The reason why this works is that lots of optimization involves time-space tradeoffs that only make sense to do if the code is frequently called. JIT only runs on frequently-called code, so it has the advantage of runtime profiling information, while ahead-of-time (AOT) compilers have to make educated guesses about what loops are the most hot. PGO closes that gap.

Theoretically, a JIT could produce binary code hyper-tailored to a particular user's habits and their computer's specific hardware. However, I'm not sure if that has that much of a benefit versus PGO AOT.

Re:Why is Rosetta 2 fast? by com2kid on Wednesday November 09, 2022 @01:24PM (#33535783)
> Theoretically, a JIT could produce binary code hyper-tailored to a particular user's habits and their computer's specific hardware. However, I'm not sure if that has that much of a benefit versus PGO AOT.

In theory JIT can be a lot more efficient, optimizing for not only the exact instruction set, and do per CPU architecture optimizations, such as instruction length, pipeline depth, cache sizes, etc.

In reality I doubt most compiler or JIT development teams have the resources to write and test all those potential optimizations, especially as new CPUs are coming out all the time, and each set of optimizations is another set of tests that has to be maintained.

Re:Why is Rosetta 2 fast? by saagarjha on Wednesday November 09, 2022 @02:15PM (#33536475)
The well funded production JIT compilers (HotSpot, V8, etc.) absolutely do take advantage of these. The vector ISA can sometimes be unwieldy to work with but things like replacing atomics, using unaligned loads, or taking advantage of differing pointer representations is common.
Re:Why is Rosetta 2 fast? by com2kid on Wednesday November 09, 2022 @03:02PM (#33537059)
They do some auto-vectorization, but AFAIK they don't do micro-optimizations for different CPUs.
Re:Why is Rosetta 2 fast? by duped on Wednesday November 09, 2022 @02:44PM (#33536848)
Like another commented, JIT compilers do this today.

The thing that makes this mostly theoretical is that the underlying assumption is only true when you neglect that an AOT has zero run-time cost while a JIT compiler has to execute the code it's optimizing and the code to decide if it's worth optimizing and generate new code.

So JIT compiler optimizations are a bit different than AOT optimizations since they have to both generate faster/smaller code and the execute code that performs the optimization. The problem is that most optimizations beyond peephole are quite expensive.

There's another thing that AOT compilers don't need to deal with, which is being wrong.Production JITs have to implement dynamic de-optimization in the case that an optimization was built on a bad assumption.

That's why JITs are only faster in theory (today), since there are performance pitfalls in the JIT itself.

Re:Why is Rosetta 2 fast? by titzer on Wednesday November 09, 2022 @04:08PM (#33537852)
Nearly all JS engines are doing concurrent JIT compilation now, so some of the compilation cost is moved off the main thread. Java JITs have had multiple compiler threads for more than a decade.
Re:Why is Rosetta 2 fast? by kllrnohj on Wednesday November 09, 2022 @09:22PM (#33541382)
But they all still optimize their JITs to prioritize compilation speed & RAM usage (JIT'd code is dirty pages after all) over maximum optimizations. This is why you see things like WebKits multi-tier JIT strategy: https://webkit.org/blog/3362/introducing-the-webkit-ftl-jit/

They still want to swap in that JIT'd result ASAP since after all by the time it's been flagged for compilation it's already too late & is a hot hot hot function.

Re:Why is Rosetta 2 fast? by pjmlp on Thursday November 10, 2022 @02:20AM (#33543273)
Which is why in the Java world (including Android), and .NET, now we use JIT caches as well, so that this data isn't lost between runs.
Re:Why is Rosetta 2 fast? by KMag on Wednesday November 09, 2022 @06:07PM (#33539476)
But, JIT vs. AoT is a false dichotomy. Given light-weight enough profiling utilizing cooperation between hardware designers and compiler writers, one could have AoT with feedback-guided optimization and link-time optimization, and still have just-in-time re-optimization.

Concretely, I think you'd want hardware that supported reservoir sampling of where CPU cycles are spent, sampling of which branches are mispredicted, and which code locations are causing cache misses. You'd also want lightweight hardware recording of execution traces.

Re:Why is Rosetta 2 fast? by saagarjha on Wednesday November 09, 2022 @08:13PM (#33540820)
Guess what Apple has? :)
Re:Why is Rosetta 2 fast? by bluGill on Wednesday November 09, 2022 @03:24PM (#33537338)
gcc and clang at least have options so you can optimize for specific CPUs. I'm not sure how good they are (most people want a generic optimization that runs well on all CPUs of the family, so there likely is lots of room for improvement with CPU specific optimization), but they can do that. This does (or at least can, again it probably isn't fully implemented), account for instruction length, pipeline depth, cache size.

The Javascript V8 engine, and the JVM both are popular and supported enough that I expect the teams working on them take advantage of every trick they can for specific CPUs, they have a lot of resources for this. (at least the major x86 and ARM chips - maybe they don't for MIPS or some uncommon variant of ARM...). Of courses there are other JIT engines, some uncommon ones don't have many resources and won't do this.

Re:Why is Rosetta 2 fast? by titzer on Wednesday November 09, 2022 @04:12PM (#33537914)
> take advantage of every trick they can for specific CPUs

Not to the extent clang and gcc do, no. V8 does, e.g. use AVX instructions and some others if they are indicated to be available by CPUID. TurboFan does global scheduling in moving out of the sea of nodes, but that is not machine-specific. There was an experimental local instruction scheduler for TurboFan but it never really helped big cores, while measurements showed it would have helped smaller cores. It didn't actually calculate latencies; it just used a greedy heuristic. I am not sure if it was ever turned on. TurboFan doesn't do software pipelining or unroll/jam, though it does loop peeling, which isn't CPU-specific.

Re:Why is Rosetta 2 fast? by astrange on Wednesday November 09, 2022 @04:13PM (#33537931)
> gcc and clang at least have options so you can optimize for specific CPUs. I'm not sure how good they are

They are not very good at it, and can't be. You can look inside them and see the models are pretty simple; the best you can do is optimize for the first step (decoder) of the CPU and avoid instructions called out in the optimization manual as being especially slow. But on an OoO CPU there's not much else you can do ahead of time, since branches and memory accesses are unpredictable and much slower than in-CPU resource stalls.

Re:Why is Rosetta 2 fast? by mockery on Wednesday November 09, 2022 @01:06PM (#33535508)
In addition to the sibling comments, one simple opportunity available to a JIT and not AOT is 100% confidence about the target hardware and its capabilities.

For example AOT compilation often has to account for the possibility that the target machine might not have certain instructions - like SSE/AVX vector ops, and emit both SSE and non-SSE versions of a codepath with, say, a branch to pick the appropriate one dynamically.

Whereas a JIT knows what hardware it's running on - it doesn't have to worry about any other CPUs.

Re:Why is Rosetta 2 fast? by acdha on Wednesday November 09, 2022 @01:50PM (#33536146)
One great example of this was back in the P4 era where Intel hit higher clock speeds at the expense of much higher latency. If you made a binary for just that processor a smart compiler could use the usual tricks to hit very good performance, but that came at the expense of other processors and/or compatibility (one appeal to the AMD Athlon & especially Opteron was that you could just run the same binary faster without caring about any of that[1]). A smart JIT could smooth that considerably but at the time the memory & time constraints were a challenge.

1. The usual caveats about benchmarking what you care about apply, of course. The mix of webish things I worked on and scientists I supported followed this pattern, YMMV.

Re:Why is Rosetta 2 fast? by duped on Wednesday November 09, 2022 @02:46PM (#33536866)
AOT compilers support this through a technique called function multi-versioning. It's not free and only goes so far, but it isn't reserved to JITs.

The classical reason to use FMV is for SIMD optimizations, fwiw

Re:Why is Rosetta 2 fast? by ketralnis on Wednesday November 09, 2022 @01:17PM (#33535678)
It means that in this case, the static compiler emitted code that could be further optimised, that's all. It doesn't mean that that's always the case, or that static compilers can't produce optimal code, or that either technique is "better" than the other.

An easy example is code compiled for 386 running on a 586. The A->A compiler can use CPU features that weren't available to the 386. As with PGO you have branch prediction information that's not available to the static compiler. You can statically compile the dynamically linked dependencies, allowing inlining that wasn't previously available.

On the other hand you have to do all of that. That takes warmup time just like a JIT.

I think the road to enlightenment is letting go of phrasing like "is superior". There are lots of upsides and downsides to pretty much every technique.

Re:Why is Rosetta 2 fast? by rowanG077 on Wednesday November 09, 2022 @04:54PM (#33538475)
A JIT can definitely make optimizations that a static compiler can't. Simply by virtue of it having concrete dynamic real-time information.
Re:Why is Rosetta 2 fast? by hamstergene on Wednesday November 09, 2022 @01:28PM (#33535829)
Could it be simply because many binaries were produced by much older, outdated optimizers. Or optimized for size.

Also, optimizers usually target “most common denominator” so native binaries rarely use full power of current instruction set.

Jumping from that peculiar finding to praising runtime JIT feels like a longshot. To me it’s more of an argument towards distributing software in intermediate form (like Apple Bitcode) and compiling on install, tailoring for the current processor.

Re:Why is Rosetta 2 fast? by jasonwatkinspdx on Wednesday November 09, 2022 @03:24PM (#33537326)
All reasonable points, but examples where JIT has an advantage are well supported in research literature. The typical workload that shows this is something with a very large space of conditionals, but where at runtime there's a lot of locality, eg matching and classification engines.
Re:Why is Rosetta 2 fast? by astrange on Wednesday November 09, 2022 @04:08PM (#33537854)
> To me it’s more of an argument towards distributing software in intermediate form (like Apple Bitcode) and compiling on install, tailoring for the current processor.

This turns out to be quite difficult, especially if you're using bitcode as a compiler IL. You have to know what the right "intermediate" level is; if assumptions change too much under you then it's still too specific. And it means you can't use things like inline assembly.

That's why bitcode is dead now.

By the way, I don't know why this thread is about how JITs can optimize programs when this article is about how Rosetta is not a JIT and intentionally chose a design that can't optimize programs.

Re:Why is Rosetta 2 fast? by lmm on Wednesday November 09, 2022 @05:04PM (#33538615)
> This turns out to be quite difficult, especially if you're using bitcode as a compiler IL. You have to know what the right "intermediate" level is; if assumptions change too much under you then it's still too specific. And it means you can't use things like inline assembly.

> That's why bitcode is dead now.

Isn't this what Android does today? Applications are distributed in bytecode form and then optimized for the specific processor at install time.

Re:Why is Rosetta 2 fast? by monocularvision on Wednesday November 09, 2022 @08:00PM (#33540715)
The bitcode Apple used for their platforms was at a much, much lower level than bytecode used on Android.
Re:Why is Rosetta 2 fast? by pjmlp on Thursday November 10, 2022 @02:16AM (#33543252)
Yeah, it was also a custom version, somehow people keep thinking they used LLVM bitcode straight out of the box.
Re:Why is Rosetta 2 fast? by astrange on Wednesday November 09, 2022 @08:51PM (#33541113)
I don't know what Android does… some kind of Java but not Java, right?

In that case it's much less expressive, so developers simply can't do the unsafe/specialized code in the first place. Which means they can't write in C or assembly.

Bitcode was a specific Apple feature that used LLVM's compiler IL and might have promised extra portability, but it didn't really work out and was removed this year. ("LLVM" stands for "low level virtual machine" which is funny because it isn't low level and isn't a virtual machine.)

Re:Why is Rosetta 2 fast? by KMag on Thursday November 10, 2022 @12:08AM (#33542482)
LLVM is lower level than Python or Java bytecode. LLVM is also virtual machine in the sense of an abstract machine, similar in idea to a process virtual machine. Most usages of "virtual machine" today are talking about system virtual machines, but it's important to note that "virtual machine" is an overloaded phrase.
Re:Why is Rosetta 2 fast? by pjmlp on Thursday November 10, 2022 @02:14AM (#33543241)
There is no C or Assembly in IBM and Unisys mainframes and microcomputers.
Re:Why is Rosetta 2 fast? by josephg on Wednesday November 09, 2022 @11:25PM (#33542186)
> That's why bitcode is dead now.

WebAssembly seems alive and well. I'm not sure how similar it is to java bitcode but its the same core idea.

That said, WASM through v8 is ~3x slower than the same code compiled natively. (Some of this might be due to the lack of SIMD in wasm).

Re:Why is Rosetta 2 fast? by astrange on Thursday November 10, 2022 @03:03PM (#33552383)
"Bitcode" is the name of a specific Xcode feature in this case, not a general comment.
Re:Why is Rosetta 2 fast? by pjmlp on Thursday November 10, 2022 @02:12AM (#33543232)
Bitcode is dead because Apple got fed up to keep maintaining their own fork with guarantees that regular LLVM doesn't offer.

Since 1961 plenty of systems have used bytecodes as executable formats, the most sucessfull still in use, IBM and Unisys mainframes and microcomputers.

Re:Why is Rosetta 2 fast? by AceJohnny2 on Wednesday November 09, 2022 @04:46PM (#33538358)
> Or optimized for size.

Note that on gcc (I think) and clang (I'm sure), -Oz is a strict superset of -O2 (the "fast+safe" optimizations, compared to -O3 that can be a bit too aggressive, given C's minefield of Undefined Behavior that compilers can exploit).

I'd guess that, with cache fit considerations, -Oz can even be faster than -O2.

Re:Why is Rosetta 2 fast? by MayeulC on Thursday November 10, 2022 @03:29AM (#33543737)
Interesting, I didn't know about -Oz (only -Os for size). -Oz is reportedly mac-specific https://stackoverflow.com/questions/1778538/how-many-gcc-opt...
Re:Why is Rosetta 2 fast? by kllrnohj on Wednesday November 09, 2022 @07:48PM (#33540604)
> To me it’s more of an argument towards distributing software in intermediate form (like Apple Bitcode) and compiling on install, tailoring for the current processor.

Or distribute it in source form and make compilation part of the install process. Aka, the Gentoo model.

Re:Why is Rosetta 2 fast? by mark_undoio on Wednesday November 09, 2022 @01:50PM (#33536158)
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 to manage - if we could build with lower optimisation and still effectively run at higher levels then that's a whole load of build/test simplification.

Moreover, debugging optimised binaries is fiddly due to information that's discarded. Having the original, unoptimised, version available at all times would give back the fidelity when required (e.g. debugging problems in the field).

Java effectively lives in this world already as it can use high optimisation and then fall back to interpreted mode when debugging is needed. I wish we could have this for C/C++ and other native languages.

Re:Why is Rosetta 2 fast? by saagarjha on Wednesday November 09, 2022 @02:11PM (#33536417)
It depends greatly on which optimization levels you’re going through. —O0 to -O1 can easily be a 2-3x performance improvement, which is going to be hard to get otherwise. -O2 to -O3 might be 15% if you’re lucky, in which case -O+LTO+PGO can absolutely get you wins that beat that.
Re:Why is Rosetta 2 fast? by bluGill on Wednesday November 09, 2022 @03:11PM (#33537177)
-O2 to -O3 has in some benchmarks made things worse. In others it is a massive win, but in generally going above -O2 should not be done without bench marking code. There are some optimizations that can make things worse or better for reasons that compiler cannot know.
Re:Why is Rosetta 2 fast? by astrange on Wednesday November 09, 2022 @04:09PM (#33537871)
Over-optimizing your "cold" code can also make things worse for the "hot" code, eg by growing code size so much that briefly entering the cold space kicks everything out of caches.
Re:Why is Rosetta 2 fast? by hinkley on Wednesday November 09, 2022 @04:43PM (#33538323)
I have often lamented not being able to hint to the JIT when I’ve transitioned from startup code to normal operation. I don’t need my Config file parsing optimized. But the code for interrogating the Config at runtime better be.

Everything before listen() is probably run once. Except not ever program calls listen().

Re:Why is Rosetta 2 fast? by hinkley on Wednesday November 09, 2022 @04:41PM (#33538298)
And then there’s always the outlier where optimizing for size makes the working memory fit into cache and thus the whole thing substantially faster.
Re:Why is Rosetta 2 fast? by foobiekr on Wednesday November 09, 2022 @05:08PM (#33538662)
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 equivalent to an install-time specializer for intermediate code which might work, but that has many problems (for one thing, it breaks upgrades and is very, very problematic for VMs being run on different underlying hosts).

Re:Why is Rosetta 2 fast? by bogomipz on Thursday November 10, 2022 @12:45AM (#33542744)
>"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? by foobiekr on Thursday November 10, 2022 @12:20PM (#33549881)
Sure thing. I’m on mobile but the 2nd one was easy to find and is here -

https://youtu.be/QGw-cy0ylCc

Re:Why is Rosetta 2 fast? by tomcam on Wednesday November 09, 2022 @03:04PM (#33537087)
I’m likely misunderstanding what you said, but I thought pre-compiled headers were pretty much standard these days.
Re:Why is Rosetta 2 fast? by tomcam on Thursday November 10, 2022 @09:07AM (#33546610)
What on earth did I say to merit the downvotes?
Re:Why is Rosetta 2 fast? by chrisseaton on Wednesday November 09, 2022 @03:29PM (#33537396)
I've run Ruby C extensions on a JIT faster than on native, due to things like inlining and profiling working more effectively at runtime.
Re:Why is Rosetta 2 fast? by sergimas15 on Wednesday November 09, 2022 @04:00PM (#33537753)
nice
Re:Why is Rosetta 2 fast? by hawflakes on Wednesday November 09, 2022 @04:02PM (#33537786)
People have mentioned the Dynamo project from HP. But I think you're actually thinking of the Aries project (I worked in a directly adjacent project) that allowed you to run PA-RISC binaries on IA-64.

https://nixdoc.net/man-pages/HP-UX/man5/Aries.5.html

Re:Why is Rosetta 2 fast? by fuckstick on Wednesday November 09, 2022 @04:03PM (#33537793)
> The output was faster than the input.

So if you ran the input back through the output multiple times then that means you could eventually get the runtime down to 0.

Re:Why is Rosetta 2 fast? by twic on Wednesday November 09, 2022 @04:23PM (#33538050)
But unfortunately, the memory use goes to infinity.
Re:Why is Rosetta 2 fast? by avidiax on Wednesday November 09, 2022 @04:05PM (#33537814)
Probably the output of the decade-old compiler that produced the original binary had no optimizations.
Re:Why is Rosetta 2 fast? by hinkley on Wednesday November 09, 2022 @04:10PM (#33537891)
That too but the eternal riddle of optimizer passes is which ones reveal structure and which obscure it. Do I loop unroll or strength reduce first? If there are heuristics about max complexity for unrolling or inlining then it might be “both”.

And then there’s processor family versus this exact model.

Re:Why is Rosetta 2 fast? by AussieWog93 on Wednesday November 09, 2022 @04:10PM (#33537876)
Outside of gaming, or hyper-CPU-critical workflows like video editing, I'm not really sure if people actually even care about that last 10% of performance.

I know most of the time I get frustrated by everyday software, its doing something unnecessary in a long loop, and possibly forgetting to check for Windows messages too.

Re:Why is Rosetta 2 fast? by koala_man on Wednesday November 09, 2022 @05:10PM (#33538699)
Performance also translates into better battery life and cheaper datacenters.
Re:Why is Rosetta 2 fast? by zaphirplane on Wednesday November 09, 2022 @05:20PM (#33538845)
Is this for itanium
Re:Why is Rosetta 2 fast? by vinyl7 on Wednesday November 09, 2022 @08:28PM (#33540942)
> where the compilers had a fast mode for code-build-test cycles and a very slow incremental mode for official builds.

That already exists with c/c++...unity builds aka single translation unit builds. Compiling and linking a ton of object files takes an inordinate amount of time, often the majority of the build time

Re:Why is Rosetta 2 fast? by bogomipz on Thursday November 10, 2022 @12:31AM (#33542633)
>"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.