Что такое cache line в компьютерной архитектуре?

«Что такое cache line в компьютерной архитектуре?» — вопрос из категории Алгоритмы и структуры данных, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Cache line (кэш-линия) — это минимальная единица данных, которой оперирует кэш процессора. При чтении из памяти в кэш загружается не один байт, а целая линия фиксированного размера.

Основные характеристики:

  • Размер — обычно 64 байта на современных x86/x64 процессорах
  • Выравнивание — адрес начала линии кратен её размеру
  • Атомарность — операции с линией атомарны на уровне кэша

Как это работает:

// Пример проблемы false sharing (ложного разделения)
struct Data {
    int a;  // Поток 1 постоянно пишет сюда
    int b;  // Поток 2 постоянно пишет сюда
};

// Если a и b попадают в одну кэш-линию (64 байта),
// то при изменении a в потоке 1, вся линия помечается невалидной
// в кэшах других ядер, вызывая постоянную синхронизацию кэшей.

Пример на Java с @Contended (Java 8+):

import sun.misc.Contended;

public class FalseSharingExample {
    // Аннотация гарантирует, что поля будут в разных кэш-линиях
    @Contended
    public volatile long value1 = 0L;

    @Contended  
    public volatile long value2 = 0L;

    // Без @Contended оба long (по 8 байт) поместятся в одну линию (64 байта)
    // С @Contended JVM добавит padding между полями
}

Практическое значение:

  1. Ложное разделение (False Sharing) — основная причина проблем с производительностью в многопоточных приложениях
  2. Выравнивание структур — оптимизация доступа к памяти
  3. Размер структур данных — проектирование с учётом размера кэш-линии

Оптимизация доступа:

// Плохо: массив структур (AoS)
class Point { float x, y, z; }
Point[] points = new Point[1000];
// При обработке только координаты x, в кэш загружаются ненужные y и z

// Лучше: структура массивов (SoA) для векторной обработки
class Points {
    float[] x = new float[1000];
    float[] y = new float[1000];
    float[] z = new float[1000];
}
// При обработке x[] кэш-линии содержат только нужные данные

Размеры на разных архитектурах:

  • x86/x64: 64 байта
  • ARM: обычно 32 или 64 байта
  • IBM POWER: 128 байт