Тут мы фиксируем, как по-взрослому мерять пропускную способность, скорость (throughput) и матан-сходимость в нашем PDE-LAB, чтобы джуны не притащили рандомные цифры из System.currentTimeMillis(). Меряем строго, академично, чтобы пруфать оптимизации без шума от JIT компилятора и метрик ради метрик.
Забудьте про System.nanoTime() в хот-пасах (как в ParallelVectorOps.axpy или SpMV), за это архитектор сразу бьет линейкой по рукам на ревью.
JIT'у (Just-In-Time) нужно время на прогрев (warmup), чтобы развернуть циклы (loop unrolling), наглухо выпилить проверки границ массивов (bounds checks) и завести векторизацию (SIMD/AVX2).
Как делать по канону:
- Дергаем джарник JMH:
./gradlew jmh. - Эта тулза сама гоняет форки, прогревает JVM и меряет честные Operations/Second (ops/s) в steady-state. Без сюрпризов.
- Фокус на Memory Bandwidth. Считаем теоретическую пропускную шину железа (
$GB/s$ ) против нашей реальной. Умножение разреженной матрицы на вектор (SpMV) — это всегда Memory Bound задача, а не Compute Bound дичь. Выравнивание памяти в плоских массивах, плотность полезных данных в кэш-линии (cache-line density) и zero-allocation — вот наш Priority Zero.
Для профильного анализа всего флоу (end-to-end execution) юзаем JFR, никаких детских игрушек.
Как делать по канону:
- Выкидываем сэмпл-профайлеры типа VisualVM на мороз. У них дикий safepoint bias (ошибка точек останова), они внаглую врут про то, что реально творится в нативных матан-циклах под капотом.
- Натравливаем на кластер
async-profilerили нативный JFR:java -XX:StartFlightRecording=duration=60s,filename=profile.jfr -jar artifacts/pdelab-all.jar run --config config.json
- Скармливаем
.jfrфайл в JDK Mission Control (JMC). - Жестко мониторим GC Pauses (Паузы сборщика мусора).
TimeStepperиPCGнаписаны так, чтобы вообще ничего (от слова "совсем") не аллоцировать в главном математическом цикле. Если видите спайкиG1GCво время работы steady-state солвера — значит, кто-то протек сквозь барьерParallelVectorOps, ищите аллокацию и сжигайте ее на ревью.
Корректность и матан должны работать как швейцарские часы. Наш солвер гарантирует математикам
Как делать по канону:
- Гоняем
./gradlew verificationTest. - Эта тяжелая артиллерия крутит жирные матрицы (от
$N=32$ до$256$ ) и пишет$L_2$ ошибки против аналитического MMS (Method of Manufactured Solutions). - Дальше делается жесткая
$log_2-log_2$ линейная регрессия (Least Squares). - Если у вас
$R^2 < 0.995$ или наклон (slope) уезжает от законов физики ($>2.2$ или$<1.8$ ) — значит, солвер сломан на уровне абстракций, математика не сошлась, откатываем коммит, идем курить мануалы и плакать.