Skip to content

Latest commit

 

History

History
36 lines (26 loc) · 4.45 KB

File metadata and controls

36 lines (26 loc) · 4.45 KB

Замеряем перформанс в PDE-LAB по хардкору

Тут мы фиксируем, как по-взрослому мерять пропускную способность, скорость (throughput) и матан-сходимость в нашем PDE-LAB, чтобы джуны не притащили рандомные цифры из System.currentTimeMillis(). Меряем строго, академично, чтобы пруфать оптимизации без шума от JIT компилятора и метрик ради метрик.

1. Микро-бенчмарки (JMH - Java Microbenchmark Harness)

Забудьте про System.nanoTime() в хот-пасах (как в ParallelVectorOps.axpy или SpMV), за это архитектор сразу бьет линейкой по рукам на ревью. JIT'у (Just-In-Time) нужно время на прогрев (warmup), чтобы развернуть циклы (loop unrolling), наглухо выпилить проверки границ массивов (bounds checks) и завести векторизацию (SIMD/AVX2).

Как делать по канону:

  1. Дергаем джарник JMH: ./gradlew jmh.
  2. Эта тулза сама гоняет форки, прогревает JVM и меряет честные Operations/Second (ops/s) в steady-state. Без сюрпризов.
  3. Фокус на Memory Bandwidth. Считаем теоретическую пропускную шину железа ($GB/s$) против нашей реальной. Умножение разреженной матрицы на вектор (SpMV) — это всегда Memory Bound задача, а не Compute Bound дичь. Выравнивание памяти в плоских массивах, плотность полезных данных в кэш-линии (cache-line density) и zero-allocation — вот наш Priority Zero.

2. JFR (Java Flight Recorder) и Async-Profiler

Для профильного анализа всего флоу (end-to-end execution) юзаем JFR, никаких детских игрушек.

Как делать по канону:

  1. Выкидываем сэмпл-профайлеры типа VisualVM на мороз. У них дикий safepoint bias (ошибка точек останова), они внаглую врут про то, что реально творится в нативных матан-циклах под капотом.
  2. Натравливаем на кластер async-profiler или нативный JFR:
    java -XX:StartFlightRecording=duration=60s,filename=profile.jfr -jar artifacts/pdelab-all.jar run --config config.json
  3. Скармливаем .jfr файл в JDK Mission Control (JMC).
  4. Жестко мониторим GC Pauses (Паузы сборщика мусора). TimeStepper и PCG написаны так, чтобы вообще ничего (от слова "совсем") не аллоцировать в главном математическом цикле. Если видите спайки G1GC во время работы steady-state солвера — значит, кто-то протек сквозь барьер ParallelVectorOps, ищите аллокацию и сжигайте ее на ревью.

3. Проверка Асимптотики (Сходимость матана)

Корректность и матан должны работать как швейцарские часы. Наш солвер гарантирует математикам $O(h^2)$ и $O(\Delta t^2)$ адекватно и аналитически.

Как делать по канону:

  1. Гоняем ./gradlew verificationTest.
  2. Эта тяжелая артиллерия крутит жирные матрицы (от $N=32$ до $256$) и пишет $L_2$ ошибки против аналитического MMS (Method of Manufactured Solutions).
  3. Дальше делается жесткая $log_2-log_2$ линейная регрессия (Least Squares).
  4. Если у вас $R^2 < 0.995$ или наклон (slope) уезжает от законов физики ($>2.2$ или $<1.8$) — значит, солвер сломан на уровне абстракций, математика не сошлась, откатываем коммит, идем курить мануалы и плакать.