Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
SIMD and Vectorization: Processing Many Values at Once with Vector128/256/512 and TensorPrimitives
SIMD means processing 4, 8 or 16 values held in a wide register at once with a single instruction; in .NET you use it through the BCL, TensorPrimitives, Vector<T> and Vector128/256/512. Summing a million ints, a single-accumulator vector loop is 2x faster and a four-accumulator one 6.5x; plus vpaddd ymm/zmm in x64 assembly, IsHardwareAccelerated as a JIT constant, and double sums that change with the hardware.
Multi-Core, Hyper-Threading and False Sharing: Why More Cores Don't Scale Linearly
More cores don't scale performance linearly because cores share cache lines, memory bandwidth and execution units. In a four-worker Bookstore counter, a shared Interlocked counter runs 15x slower, adjacent per-worker slots can't beat a single thread because of false sharing, padding and local variables fix it, Environment.ProcessorCount follows container CPU limits, and Hyper-Threading and P/E cores change the picture.
How CPU Caches Work: Cache Lines, Associativity and Cache-Friendly C#
The CPU reads cache lines, not bytes (64 bytes on x64), and looks up an address by splitting it into tag, index and offset and searching a single set; how fast your code runs depends on whether it fits that structure. Walking a 4096 × 4096 table by columns 6.5x slower, a loop 4.6x faster once 16 columns remove the conflict misses, a 5x win from Struct of Arrays, and a struct shrinking from 40 to 24 bytes by field order.
The Memory Hierarchy: Latency Numbers from Registers to SSD and Locality
Memory is not one flat thing: from registers and L1 down to DRAM, SSD and the network, every layer is bigger and slower, and a DRAM read takes about 90 times as long as an L1 read. Summing a 256 MB array in shuffled order is 13.4x slower, you can measure latency on your own machine with pointer chasing, stack and heap are the same RAM, and a struct array scans 6x faster than a List<Book>.
CPU Pipelines and Branch Prediction: Why Is a Sorted Array Processed Faster?
A sorted array is processed faster because the ifs inside the loop become predictable and the CPU doesn't have to flush its pipeline. A 9.4x gap on one million orders, why the JIT won't emit cmov inside a loop, branchless summing with a bit mask, dependency chains and ILP, and why Spectre exists.
How a Line of C# Runs on the CPU: From Source to IL, Assembly and Instructions
A line of C# reaches the CPU through two translations: Roslyn turns it into IL, and at run time the JIT turns that into machine code for the machine's ISA, which the CPU runs in a fetch-decode-execute cycle. We read the 30-byte x64 Tier-1 code of TotalQuantity line by line, compare it with its ARM64 version, the 789-byte decimal version and an unoptimized Tier-0 measurement, and explain the x86-64-v2 baseline in .NET 11.