In our newsletter this month we are talking about migrating from x86 to Arm64 and I was wondering if anyone had some stories about something that they had to over come to do the migration or was it just simply testing everything?
I know that we have had stories from Falco and Open Telemetry people that things just worked or that there might have been some low level dependency that they had to fix, but they were quite surprised that it just worked.
In my experience, when I first daily drove Arm back in ~2015 vs the past 2 years, Nix and NixOS makes Arm much better. With how many packages there are, you don’t have to worry about a package not supporting your system. Btw, 17.4% of the Nix community are running Linux on Arm.
I think that the state of things varies from one language ecosystem to another - compiled languages like Zig, Go, Java are cross-platform by design, and while runtime performance can vary from one architecture to another, everything basically just works. The C and C++ ecosystems, especially in fields like HPC, AI, and scientific computing, can have significant performance differences - often related to the maturity of SIMD implementations of algorithms. But as NEON and SVE2 have become more widespread, that problem is going away quite fast.
There are a few common GOTCHAs in the C/C++ world that you should be aware of - the default “char” type is different on Arm64 and x86, for example - code that relies on integer overflow behaviour on x86 (which is undefined behaviour anyway and should be avoided) can fail on Arm64 because the default char type on x86 is signed char, but on Arm64 is unsigned char. There is also a very common motif that people use with fgetc() or getchar() (which return an int) - when it read an EOF character, the function typically returns -1 - but if you are assigning this to an unsigned char, it will get wrapped to 255. The following code, which looks very reasonable, is incorrect on Arm64:
char c;
FILE * f = fopen(filename, "r");
while(1) {
c = fgetc(f);
if (c == EOF) {
// This is never true on Arm64 (comparing 255 with (int) -1)
break;
}
// Do something with c here
}
fclose(f);
There are a few other common architecture differences to watch out for - this one can be particularly hard to spot, though!
I agree and Zig actually makes cross platform programming even easier. If you never need a system library or have Nix, you can cross compile as easy as zig build -Dtarget=s390x-linux. It uses LLVM but they’re writing their own codegen backend so I’m not sure what future targets they will support but Arm is for certain one to remain. iirc, the Arm backend is in a very good state.