This is mostly a post to try and get me to start blogging a bit more again, but I will try and make it potentially useful…
When I returned to the United Kingdom from New Zealand last year, I had four laptops (and some other smaller electronic gear) in total I ideally
wanted to bring back with me in some way or another.
One of the laptops was my then-replaced and barely-used older Intel MacBook Pro 15 - which I had replaced with an M2 Pro in 2023 - but I did
still occasionally use as it could run some old x86 Mac software (although the machine itself barely ran due to fans not working), and I didn’t really want to install Rosetta 2 on my M2 Pro.
The other older laptop was my very-regularly-used ThinkPad T480s, which I got in 2019 and generally liked a lot for Linux, but was quite anemic on the CPU-performance front, so I had been tempted anyway to replace it with a newer version.
When I looked into shipping my “stuff” back to the UK, several shipping companies mentioned I couldn’t ship electronics with Lithium-ion
batteries in for safety reasons, which I had envisaged doing for these two older laptops (and then I’d just take the other two newer laptops
with me on the plane back). I enquired with several other companies and the situation was a bit ambiguous, as some companies at first said
it wouldn’t be an issue to send them back, but when I asked someone else at the same company they then said it was an issue,
so I decided it wasn’t worth risking it using this method of getting them back.
I did also look into shipping them back with DHL or something, just as an individual isolated shipment of the two laptops (and other smaller
devices), which while technically possible was expensive and was also a bit complicated, as if I wanted it to get through customs
on the UK side, I seemed to need to address the shipment to myself and not a third-party, which was a bit impractical, as I was planning on
stopping off in Vancouver for a week, and didn’t really want to get relatives to pretend to be me or something.
So I decided to just dispose of the older two laptops, and only bring the two newer ones back with me on the plane, and then I’d get a new ThinkPad
for Linux use when I was back in the UK.
Once back in the UK, I decided to get a ThinkPad T14s AMD, but wasn’t quite sure whether to risk going with the newer Gen 6 version, which didn’t
seem to have as-good Linux kernel compatibility, or stick with the older Gen 5 one which had better compatibility at the time. I also noted in
reviews that there was mention of fans running quite a bit with the Gen 6 AMD. I decided to risk going for the Gen 6 version in the end though.
Once it arrived towards the end of July, I couldn’t easily get Linux Mint or Ubuntu to run on it, as the stock distro kernel was too old for the newer
AMD hardware (I think support had only landed in the kernel in around April). It looked like Linux Mint would within a couple of months release a
newer kernel with better hardware compatibility, so I temporarily installed Fedora on the laptop and used it with that distro for a while.
That experience with the laptop was reasonably good: compared to the T480s, the screen was a lot nicer (a bit brighter and also 16:10 aspect
ratio!) while still being matte, the machine in general was a lot more powerful (CPU and GPU) and the speakers were noticeably better.
Waking from sleep was also faster than the T480s was (still not as quick as the MacBook Pros though!).
On the downsides, the keyboard wasn’t quite as good - there was less key travel, and Lenovo had decided to swap the position of the Ctrl and Fn keys,
which was quite frustrating due to muscle memory (there’s an option to swap them in the BIOS), and the lack of the built-in Ethernet port was
mildly annoying (especially at first with Wifi support not existing in earlier Linux kernels), but is somewhat understandable. Another minor irritation
was that the hinge is quite a bit stiffer to open than on the T480s, which in practice means it’s a lot more difficult to open the lid one-handed when
it’s closed on a desk for example: you end up lifting up the entire front of the laptop instead of the screen just opening.
But the biggest annoyance was the fans: compared to the T480s - where to my knowledge I didn’t have to install or configure anything to get the fans to
behave “normally” - i.e. no air movement or noise when the machine is idle and fans ramp up when the thermal temp increases - it seems with the T14s
Gen 6 AMD, the fans are always on “medium”, even with the machine at idle with temps in the 45 degC range (i.e. even in the BIOS), and the fans speed
up even more as the temps increase when the CPU/GPU is used heavily (understandably).
When Linux Mint 22.2 was released in September (and moved to kernel 6.14 which included better support for the newer AMD chipsets), I re-installed
the machine with that distro from that point on. Unfortunately, it turns out that with this new setup of Linux Mint and kernel 6.14, XOrg would randomly
lock up (although the mouse cursor would still move), although the machine was still running okay in the background, but Xorg/UI-started applications
would crash/close.
This was quite frustrating, as the issue would generally happen every ten minutes or so, and normally happened when I was trying to select text with the
mouse or scroll with the trackpad. If I just left the machine running a UI terminal session doing nothing else, or didn’t use the mouse as much
it seemed far less prone to happening.
I eventually discovered the cause and a work-around for this issue: it turns out that AMD made a GPU driver change with Kernel 6.14 which turned a
feature called Panel Self Refresh (PSR) on, and there was a bug in the implementation with this kernel version which was causing the GPU driver
to lock-up.
A forum post regarding the issue and work-arounds for it can be found on the Framework community forum here.
Implementing the amdgpu.dcdebugmask=0x12 kernel boot parameter mitigation to turn PSR off again solves the issue for me completely.
I had hoped (given the kernel fix for the PSR issue was submitted upstream back in August 2025) that kernel 6.17 (which Linux Mint has just started supporting)
would have included the full fix, meaning the above kernel boot parameter work-around wouldn’t be needed any more, but today I’ve tested that theory
by commenting out the work-around and rebooting, but unfortunately even with kernel 6.17 active the issue still happens, so I still need the
work-around by the looks of things.
All in all though, other than the issue with the fans being persistent and overly-enthusiastic, the laptop’s pretty good, although I do miss the fact
that the T480s “just worked” from my perspective, and I didn’t need to configure anything with the older machine. Battery life on this new T14s Gen 6
also isn’t great - partly I think due to the fans always running, and possibly due a tiny bit to the PSR-disabling work-around. I can get just over
four hours of use with low-CPU usage and medium display brightness (this is after tuning things a bit with powertop), which is worse than my older T480s could do even with a 5-year-old battery.
In terms of the fans, I have tried messing around with thinkfan to try and control the fans a bit more and slow them down when not needed,
and while that sort of works to a limited degree, thinkfan doesn’t seem that stable in practice and often seems to crash or get stuck after
awakening from sleep, so for the moment I’m just putting up with the fans always being on.
This month I bought and received a new Apple MacBook Pro (M2 Pro, 14-inch, 2023) with the aim of replacing my own Apple MacBook Pro 15-inch (Intel) 2015 model which I bought in 2016. The MacBook Pro 15 still does work, but the battery life is awful now (I could have it replaced, which I’ve done several times with laptops in the past), the internal fans barely work, and the rubber around the screen is disintegrating, so with a trip back to the Northern Hemisphere planned next month, I thought it was time for a replacement.
A year ago I was provided (on loan) a work-provided MacBook Pro 14 M1 Pro (see previous benchmarks) which I’ve been using a bit, so I knew mostly what to expect in terms of performance and from the laptop in general, but I was curious to compare the performance of the M2 Pro against the M1 Pro (and the old Intel machine).
It’s not going to be a completely fair apples-to-apples comparison, as the work-provided MacBook Pro 14 M1 Pro processor is the 10-core version which has two extra performance cores than the baseline did - having eight performance cores and two efficiency cores - and the M2 Pro I’ve just bought is the baseline model - with six performance cores and four efficiency cores - but it should provide a rough indication of what performance to expect.
The Xcode / Apple Clang compiler versions are also different: My MacBook Pro 15 (Intel) is still running quite an old MacOS version, with an older compiler which I don’t want to update, and while I did install Xcode 14.3 on the 2021 MacBook Pro M1 Pro (as well as the command line tools) in order to attempt to match what I’d just installed on my new 2023 MacBook Pro M2 Pro, clang --version still shows version 13.1.6, whereas my new 2023 M2 Pro MacBook Pro shows 14.0.3 being used, so I’m not really sure what’s going on there, as Xcode -> About Xcode shows Version 14.3.1 as I’d expect on both MacBook Pro 14 machines (and both have the command line tools for that version of Xcode installed).
The MacBook Pro 14s are both running MacOS Ventura 13.4.
Tests:
Copying what I did in the test last year, I’ll be using two of my apps as benchmarks: my Mint interpreter language VM (originally based off Robert Nystrom’s excellent Crafting Interpreters Lox language tutorial) but with additional functionality and performance improvements, which I’ll use to benchmark two Mint scripts as single-threaded tests, and also my Imagine pathtracing renderer, which has native SSE intrinsics support for Intel and native Neon intrinsics support for ARM, which I’ll run in both single- and multi-threaded scenarios.
Both apps will be compiled with -march=native on the Intel side and -mcpu=native on the Apple Silicon / ARM side, using the clang version on the machine in question, as well as optimisation level: -O3.
The two Mint script tests will be loop value calculation as Test 1:
var a = 1;
for (var i = 0; i < 100000000; i += 1)
{
a = (i + i + 3 * 2 + i + 1 - 0.42) / a;
}
print a;
and a variation of Project Euler 21 to calculate the sum of all Amicable numbers under 15,000 as Test 2.
The Imagine rendering tests will render three different scenes in both single- and multi-threaded mode.
The first render will be the same maze scene with spherical area lights that I used in the test last year (example image above), but with different settings:
resolution will be 256 x 256, 256 samples-per-pixel will be used, but this time only one next-event light sample will be taken each path vertex.
The general ray traversal and ray intersection will utilise SIMD, but the (fairly expensive) perfect light sphere sampling is scalar, and very unlikely
to be vectorised by the compilers themselves.
The second render will be a 450 x 338 resolution render of a Signed Distance Field primitive of a Julia Fractal (example image above, although with different settings), which is quite expensive to evaluate,
and also does not have any SIMD utilisation for the SDF evaluation / intersection. There’s a physical Sky IBL in the scene as a light, and 144 samples-per-pixel will be used, with 3x3 Blackman Harris pixel filtering being used.
The third render will be a 450 x 338 resolution render of 2,326,299 instanced mesh cubes in the (pre-calculated) shape of a Julia Fractal, which will
fully-utilise SIMD instructions for ray traversal in the BVH and for ray / primitive intersections. Again, there’s a physical Sky IBL in the scene,
144 samples-per-pixel will be used, but this time no pixel reconstruction filtering will be used (so effectively Box 1x1).
These tests will all be done on (close to fully-charged) battery power - I discovered in the tests last year that Apple doesn’t seem to down-clock on battery power - and I will also wait between test runs for the processor temperatures to be below 50 degC before running the next test, to try and reduce the impact of thermal throttling.
All tests will be run three times, and results below will show the mean average of those numbers.
Results
Single-threaded Mint VM interpreter:
Single-threaded Mint interpreter VM benchmarks, smaller values are better:
For these single-threaded tests, the M2 Pro has a small improvement over the M1 Pro’s performance, which itself is around 10-16% faster than the eight year old Intel i7 processor. As mentioned last year however, I think this is very likely because the Mint VM execution is often branch-prediction constrained within the main VM bytecode interpreter loop, so there’s a limit to the amount of Instruction-Level Parallelism that’s achievable from the eight-wide M1 Pro and M2 Pro.
Single-threaded Imagine rendering:
Single-threaded Imagine rendering benchmarks, smaller values are better:
The single-threaded rendering tests, which have a lot more floating point calculations and SIMD usage, show a small performance improvement for the M2 Pro over the M1 Pro. Intriguingly, the Maze Lights scene is the test with the biggest performance increase (almost 2x faster) from the Intel machine to the Apple M1 Pro: the other tests show slightly smaller gains, which I wouldn’t have expected. Without further microbenchmarks of various isolated parts of those tests, it’s difficult to guess why that might be, but the different render tests do exercise different calculations and code paths.
Multi-threaded Imagine rendering:
Multi-threaded Imagine rendering benchmarks, smaller values are better:
The multi-threaded rendering tests show that due to the fact the M1 Pro machine has eight performance cores and two efficiency cores, whilst the M2 Pro
machine only has six performance cores and four efficiency cores, the M2 Pro machine is only very slightly faster in the SDF Julia Fractal render scene than the M1 Pro machine, and ties in the other two tests. Once again, the Maze Lights scene shows the biggest performance increase - almost 4x faster - from the Intel CPU to the Apple Silicon ones, with the other two tests showing a less dramatic difference (between 2x to 3x faster).
Conclusion
I think a not too bad showing for the baseline model: the M2 Pro can beat the M1 Pro by a small margin in all single-threaded tests, and can either just about equal or slightly beat the M1 Pro which has more performance cores (but two less efficiency cores) in the multi-threaded tests.
Last week I received a work-provided (on loan) new Apple MacBook Pro (14-inch, 2021) with the Apple M1 Pro 10-core processor, so I was very curious to see how it performed with some of my code, given the generally excellent reviews and reports I’d seen by people with it online.
I have my own MacBook Pro 15-inch 2015 (Intel i7) model which I’ll be comparing it against as a basic benchmark performance test, although it won’t be a completely fair test as the two machines are running different versions of MacOS and the clang compiler, and I didn’t want to upgrade my own machine’s MacOS version to a newer version (for various reasons). So the code being executed on the different machines will be generated by different versions of clang, but given the micro-architecture is totally different anyway, I think it’s still a meaningful test and at least will show the performance difference between the two laptops.
My old MacBook Pro 15-inch 2015 is a 2.5 GHz Intel Core i7, with four cores, eight threads, and 1600 Mhz DDR3 memory, running macOS 10.14.5 (Mojave), with Xcode 10.2.1 installed which has clang version 10.0.1.
The new MacBook Pro 14-inch 2021 is the M1 Pro 10-core version, with 8 performance cores and 2 efficiency cores, running macOS 12.3 (Monterey), with Xcode 13.4.1 installed which has clang version 13.1.6.
Tests:
I’ll be using two of my apps as benchmarks: my Mint interpreter language VM (originally based off Robert Nystrom’s excellent Crafting Interpreters Lox language tutorial) but with additional functionality and performance improvements, which I’ll use to benchmark two Mint scripts as single-threaded tests, and also my Imagine pathtracing renderer, which has native SSE intrinsics support for Intel and native Neon intrinsics support for ARM, which I’ll run in both single- and multi-threaded scenarios.
Both apps will be compiled with -march=native on the Intel side and -mcpu=native on the Apple M1 Pro ARM side, using the clang version on the machine in question, as well as optimisation level: -O3.
The two Mint script tests will be loop value calculation as Test 1:
var a = 1;
for (var i = 0; i < 100000000; i += 1)
{
a = (i + i + 3 * 2 + i + 1 - 0.42) / a;
}
print a;
and a variation of Project Euler 21 to calculate the sum of all Amicable numbers under 15,000 as Test 2.
The Imagine rendering tests will render the below example scene of a basic maze with 12 spherical area lights and one hemisphere light, with four Next Event Estimation samples being taken each bounce to evaluate the lighting, and using Cone sampling to perfectly sample each spherical area light from each hitpoint, with 256 samples-per-pixel being done, using stratified sampling and a ray depth of 6 diffuse bounces. Depending on the setup of the tests (single-threaded, multi-threaded, etc), I’ll render the scene at resolutions of: 150 x 150, 300 x 300 and 600 x 600.
For all tests, I’ll run them on battery power and then mains power, in case that affects the clocking of the processors, and will also wait between test runs for the processor temperatures to be below 50 degC before running the next test, to try and reduce the impact of thermal throttling. However, for the longer-running multi-threaded Imagine rendering tests I’m fairly sure thermal throttling will start to take place on the Intel 2015 machine given how fast the fans start to spin in longer-running scenarios.
All tests will be run three times, and results below will show the mean average of those numbers.
Results
Single-threaded Mint VM interpreter:
Single-threaded Mint interpreter VM benchmarks, smaller values are better:
For these single-threaded tests, the M1 Pro has fairly modest (~11% faster in Test 1, ~16% faster in Test 2) improvements over the seven year old Intel i7, however as the Mint VM execution is often branch-prediction constrained within the main VM bytecode interpreter loop, I expect this doesn’t really allow the M1 Pro’s eight-wide design to really stretch its legs running these benchmarks, as there’s a limit to the amount of Instruction-Level Parallelism that’s achievable.
It’s interesting to see that there’s no apparent difference in performance between running on battery vs running connected to the mains: I was expecting to see a difference - even if only on the Intel i7 MBP - as I know my Thinkpad T480s running Linux shows significant performance differences between the two states, but Apple clearly don’t seem to be implementing that strategy.
Single-threaded Imagine rendering:
Single-threaded Imagine rendering benchmarks, smaller values are better:
Things start to look more impressive for the M1 Pro in the single-threaded rendering tests, as here there are a lot more floating point calculations being done with a lot less branching, and there’s a fair amount of SIMD use (i.e. ray intersection / traversal code, which uses native SSE or Neon instructions for the respective platform architectures) allowing the M1 Pro to show what it can do.
For both the 150 x 150 resolution and 300 x 300 resolution renders, the M1 Pro machine completed the tasks in ~46% less time, so it’s close to twice as fast as the older Intel machine. Again, there was no apparent performance difference between running powered off the battery compared to running with the machines plugged into the mains power.
Multi-threaded Imagine rendering:
Multi-threaded Imagine rendering benchmarks, smaller values are better:
The multi-threaded rendering tests show that for the shorter-duration 300 x 300 resolution render, the M1 Pro was more than three times faster (render time was less than a 1/3 of the Intel MBP’s i7 render time), and for the longer-duration 600 x 600 resolution render this ratio was slightly better still - I suspect because of the fact the Apple M1 Pro has significantly better thermal performance than the Intel i7, so is not throttling as much - if at all - although watching the temps on the M1 Pro machine towards the end of the test shows it did reach 84 degC, so it’s possible throttling is happening a bit.
Conclusion
So for most code that’s likely not branch/dependency-bound, it would seem the almost one year-old M1 Pro being tested here is around three times faster than the seven year-old Intel i7 model (although the base M1 Pro model with two less performance cores will not be as fast), and for multi-threaded code that parallelises well it can be more than three times faster, with much better thermal performance (which means less fan noise) and battery life, which is exactly what you’d want from a laptop, and I think shows that the Apple M1 processors are something to be excited about.