JVM Performance Fuzzer использует комплексный подход к измерению производительности и верификации аномалий, который включает:
- Двухуровневый механизм измерений - разные настройки JMH для быстрых и подробных замеров
- Двухуровневую систему верификации - разные пороги для обнаружения и подтверждения аномалий
- Механизм периодической верификации - регулярная проверка наиболее перспективных сидов
- Интеграцию с системой эволюции сидов - обратная связь для корректировки ценности сидов
Система использует Java Microbenchmark Harness (JMH) с двумя основными конфигурациями:
// Для быстрых измерений в процессе эволюции сидов
val evolutionJmhOptions = OptionBuilder()
.include(".*")
.warmupIterations(1)
.warmupTime(TimeValue.seconds(4))
.measurementIterations(3)
.measurementTime(TimeValue.seconds(5))
.forks(1)
.build()
// Для детальной верификации обнаруженных аномалий
val verificationJmhOptions = OptionBuilder()
.include(".*")
.warmupIterations(2)
.warmupTime(TimeValue.seconds(10))
.measurementIterations(4)
.measurementTime(TimeValue.seconds(15))
.forks(1)
.build()Система согласует уровни измерений с уровнями верификации:
-
SEED_EVOLUTION → быстрые измерения (
evolutionJmhOptions)- Меньше прогревов и итераций
- Цель: быстрый скрининг большого количества мутаций
-
REPORTING → подробные измерения (
verificationJmhOptions)- Больше прогревов и итераций для стабильных результатов
- Цель: детальная проверка выявленных аномалий
fun measure(bytecode: ByteArray, significanceLevel: SignificanceLevel): List<Pair<JvmExecutor, PerformanceMetrics>> {
val jmhOptions = when (significanceLevel) {
SignificanceLevel.SEED_EVOLUTION -> evolutionJmhOptions
SignificanceLevel.REPORTING -> verificationJmhOptions
}
return executeJmhBenchmark(bytecode, jmhOptions)
} ┌─────────────────┐
│ Измерение │
│ производитель- │
│ ности мутации │
└────────┬────────┘
│
▼
┌──────────────────┐
│ Анализ отклонений│
└─────────┬────────┘
│
▼
┌──────────────────┐ ┌──────────────────────┐
│ Отбрасываем │ │ Соответствует │
│ мутацию │◄───────────────│ минимальному порогу? │──────┐
└──────────────────┘ Нет │ │ Да │
└──────────────────────┘ │
│
▼
┌───────────────────────┐
│ Сохраняем как │
│ новый сид │
└──────────┬────────────┘
│
▼
┌────────────────────────┐ ┌────────────────────────────┐
│ Классифицируем как │ │ Соответствует строгому │
│ "интересный сид" │ ◄─────│ порогу верификации? │
│ без полной верификации │ Нет └──────────────┬─────────────┘
└────────────────────────┘ │ Да
▼
┌─────────────────────────┐
│ Запускаем полную │
│ верификацию │
└────────────┬────────────┘
│
▼
┌────────────────────────┐ ┌────────────────────────────┐
│ Не верифицируем │ │ Соответствует строгому │
│ Уменьшаем интересность │ ◄─────│ порогу верификации? │
│ сида, но не выкидываем │ Нет └──────────────┬─────────────┘
└────────────────────────┘ │ Да
│
┌─────────────────────────────┐ │
│ Сохраняем в репозиторий │◄─────────────────────────────────┘
│ как проверенную аномалию │
│ с полным анализом и отчетом │
└─────────────────────────────┘
Фаззер не только проверяет каждую мутацию на уровне SEED_EVOLUTION, но и периодически выбирает наиболее перспективные сиды для детальной верификации:
Этот механизм обеспечивает:
- Периодическую проверку ~ 3 лучших сидов после накопления ~ 10 новых
- Исключение ложноположительных результатов
- Более эффективное использование ресурсов (детальная верификация только самых перспективных сидов)
Верифицированные сиды имеют повышенный приоритет при выборе для мутации:
// Коэффициент увеличения вероятности для верифицированных сидов
val verificationBonus = 2.0
// Создаём взвешенный список, где верифицированные сиды имеют больший вес
val weightedPool = activeSeeds.map { seed ->
seed to if (seed.verified) (seed.energy * verificationBonus).toInt() else seed.energy
}Верифицированные сиды защищены от удаления при переполнении пула:
// Находим сиды, которые не являются начальными и не верифицированы
val removeCandidates = seedPool
.filter { seed ->
!seed.verified && initialSeeds.none { it.bytecodeEntry.bytecode.contentEquals(seed.bytecodeEntry.bytecode) }
}
.sortedBy { it.energy * (1.0 + it.interestingness) }Верифицированные сиды получают приоритет при восстановлении энергии:
// Сначала восстанавливаем верифицированные сиды с низкой энергией
val verifiedLowEnergySeeds = seedPool.filter { it.verified && it.energy <= minEnergyThreshold }
// Определяем сколько еще сидов нужно восстановить
val additionalSeedsNeeded = minActiveSeedsThreshold - verifiedLowEnergySeeds.size- Сид получает статус
verified = true - Его интересность может быть увеличена (в зависимости от значимости подтвержденной аномалии)
- Сохраняется в репозитории аномалий для дальнейшего анализа
- Получает повышенный приоритет при выборе для мутации (множитель 2.0)
- Становится более защищенным от удаления при очистке пула
- Интересность сида может быть снижена
- Сид не получает статус
verified - Становится более уязвимым к удалению при очистке пула
- Имеет стандартную вероятность выбора для мутации (без бонуса)
Система измерения и верификации в JVM Performance Fuzzer представляет собой комплексное решение, где:
-
Двухуровневые измерения (быстрые и подробные) соответствуют двум уровням верификации (SEED_EVOLUTION и REPORTING)
-
Периодическая верификация наиболее перспективных сидов (~3 лучших после накопления ~10 новых) обеспечивает эффективное использование ресурсов
-
Успешно верифицированные сиды получают особый статус, который влияет на все аспекты их жизненного цикла:
- Защита от удаления
- Приоритет при выборе
- Приоритет при восстановлении энергии
-
Механизм обратной связи через свойства
verifiedиinterestingnessнаправляет процесс эволюции в сторону наиболее перспективных направлений поиска аномалий
Такой подход позволяет фаззеру эффективно исследовать пространство возможных мутаций, концентрируясь на направлениях с подтвержденным потенциалом обнаружения аномалий производительности между различными реализациями JVM.