Skip to content

Commit fb0a308

Browse files
committed
Fix stats
1 parent 4df0a88 commit fb0a308

3 files changed

Lines changed: 58 additions & 11 deletions

File tree

core/src/main/kotlin/org/evomaster/core/search/service/Statistics.kt

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,11 @@ class Statistics : SearchListener {
8787
private val sqlRowsAverageCalculator = IncrementalAverage()
8888

8989
// Z3-based SQL data generation statistics
90-
private var sqlZ3TotalQueriesProcessed = 0
90+
// Invariant: sqlZ3QueriesSeenCount == sqlZ3CacheHitCount + sqlZ3CacheMissCount
91+
// (every solve() call is either served from the memoization cache or handled as a miss).
92+
private var sqlZ3QueriesSeenCount = 0
93+
private var sqlZ3CacheHitCount = 0
94+
private var sqlZ3CacheMissCount = 0
9195
private var sqlZ3SatCount = 0
9296
private var sqlZ3UnsatCount = 0
9397
private var sqlZ3UnknownCount = 0
@@ -244,31 +248,31 @@ class Statistics : SearchListener {
244248
}
245249

246250
fun reportSqlZ3Sat(z3TimeMs: Long) {
247-
sqlZ3TotalQueriesProcessed++
251+
sqlZ3CacheMissCount++
248252
sqlZ3SatCount++
249253
sqlZ3TimeMs += z3TimeMs
250254
}
251255

252256
fun reportSqlZ3Unsat(z3TimeMs: Long) {
253-
sqlZ3TotalQueriesProcessed++
257+
sqlZ3CacheMissCount++
254258
sqlZ3UnsatCount++
255259
sqlZ3TimeMs += z3TimeMs
256260
}
257261

258262
fun reportSqlZ3Unknown(z3TimeMs: Long) {
259-
sqlZ3TotalQueriesProcessed++
263+
sqlZ3CacheMissCount++
260264
sqlZ3UnknownCount++
261265
sqlZ3TimeMs += z3TimeMs
262266
}
263267

264268
fun reportSqlZ3Error(z3TimeMs: Long) {
265-
sqlZ3TotalQueriesProcessed++
269+
sqlZ3CacheMissCount++
266270
sqlZ3ErrorCount++
267271
sqlZ3TimeMs += z3TimeMs
268272
}
269273

270274
fun reportSqlZ3ParseFailure() {
271-
sqlZ3TotalQueriesProcessed++
275+
sqlZ3CacheMissCount++
272276
sqlZ3ParseFailureCount++
273277
}
274278

@@ -278,11 +282,22 @@ class Statistics : SearchListener {
278282
}
279283

280284
fun reportSqlZ3QuerySeen(queryHash: Int) {
285+
sqlZ3QueriesSeenCount++
281286
if (sqlZ3SeenQueryHashes.add(queryHash)) {
282287
sqlZ3UniqueQueriesCount++
283288
}
284289
}
285290

291+
fun reportSqlZ3CacheHit() {
292+
sqlZ3CacheHitCount++
293+
}
294+
295+
// Exposed for tests: verify the memoization accounting invariant
296+
// (seen == cacheHits + cacheMisses).
297+
internal fun getSqlZ3QueriesSeenCount() = sqlZ3QueriesSeenCount
298+
internal fun getSqlZ3CacheHitCount() = sqlZ3CacheHitCount
299+
internal fun getSqlZ3CacheMissCount() = sqlZ3CacheMissCount
300+
286301
fun reportSqlZ3CorrectnessDistance(sqlDistance: Double, evaluationFailure: Boolean) {
287302
sqlZ3CorrectnessCheckCount++
288303
if (evaluationFailure) {
@@ -459,9 +474,11 @@ class Statistics : SearchListener {
459474

460475
// statistics info for Z3-based SQL data generation (only emitted when collectSqlZ3Stats=true)
461476
if (config.collectSqlZ3Stats) {
462-
add(Pair("sqlZ3TotalQueries", "$sqlZ3TotalQueriesProcessed"))
477+
add(Pair("sqlZ3QueriesSeen", "$sqlZ3QueriesSeenCount"))
463478
add(Pair("sqlZ3UniqueQueries", "$sqlZ3UniqueQueriesCount"))
464-
add(Pair("sqlZ3DuplicateQueries", "${sqlZ3TotalQueriesProcessed - sqlZ3ParseFailureCount - sqlZ3UniqueQueriesCount}"))
479+
add(Pair("sqlZ3DuplicateQueries", "${sqlZ3QueriesSeenCount - sqlZ3UniqueQueriesCount}"))
480+
add(Pair("sqlZ3CacheHits", "$sqlZ3CacheHitCount"))
481+
add(Pair("sqlZ3CacheMisses", "$sqlZ3CacheMissCount"))
465482
add(Pair("sqlZ3Sat", "$sqlZ3SatCount"))
466483
add(Pair("sqlZ3Unsat", "$sqlZ3UnsatCount"))
467484
add(Pair("sqlZ3Unknown", "$sqlZ3UnknownCount"))

core/src/main/kotlin/org/evomaster/core/solver/SMTLibZ3DbConstraintSolver.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,11 +139,14 @@ class SMTLibZ3DbConstraintSolver() : DbConstraintSolver {
139139
val collectStats = ::config.isInitialized && config.collectSqlZ3Stats
140140
val stats: Statistics? = if (collectStats) statisticsRef?.get() else null
141141

142-
stats?.reportSqlZ3QuerySeen(sqlQuery.hashCode())
143-
144142
val cacheKey = Pair(sqlQuery, numberOfRows)
143+
// Track "seen" against the same key the cache uses, so unique/duplicate counts
144+
// line up with actual cache granularity.
145+
stats?.reportSqlZ3QuerySeen(cacheKey.hashCode())
146+
145147
val cached = z3ResultCache?.get(cacheKey)
146148
if (cached != null) {
149+
stats?.reportSqlZ3CacheHit()
147150
return when (cached.status) {
148151
Z3Result.Status.SAT -> toSqlActionList(schemaDto, cached.solution)
149152
else -> emptyList()

core/src/test/kotlin/org/evomaster/core/search/service/StatisticsTest.kt

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package org.evomaster.core.search.service
22

3-
import org.junit.Test
3+
import org.junit.jupiter.api.Test
44
import org.junit.jupiter.api.Assertions.assertEquals
55

66
class StatisticsTest {
@@ -36,4 +36,31 @@ class StatisticsTest {
3636
assertEquals((5 + 7 + 11 + 13).toDouble() / 4, statistics.averageNumberOfEvaluatedRowsForSqlHeuristics())
3737
}
3838

39+
@Test
40+
fun testSqlZ3CacheAccountingInvariant() {
41+
val statistics = Statistics()
42+
43+
// Query #1: first sighting -> cache miss, solved as SAT
44+
statistics.reportSqlZ3QuerySeen(1)
45+
statistics.reportSqlZ3Sat(10)
46+
47+
// Query #2: first sighting -> cache miss, solved as UNSAT
48+
statistics.reportSqlZ3QuerySeen(2)
49+
statistics.reportSqlZ3Unsat(5)
50+
51+
// Query #1 seen again -> served from the memoization cache (a hit, not a miss)
52+
statistics.reportSqlZ3QuerySeen(1)
53+
statistics.reportSqlZ3CacheHit()
54+
55+
assertEquals(3, statistics.getSqlZ3QueriesSeenCount())
56+
assertEquals(1, statistics.getSqlZ3CacheHitCount())
57+
assertEquals(2, statistics.getSqlZ3CacheMissCount())
58+
59+
// Every solve() is either a cache hit or a miss.
60+
assertEquals(
61+
statistics.getSqlZ3QueriesSeenCount(),
62+
statistics.getSqlZ3CacheHitCount() + statistics.getSqlZ3CacheMissCount()
63+
)
64+
}
65+
3966
}

0 commit comments

Comments
 (0)