blob: 2c18ab3af548acb51112e03585c8bac0fc75218c [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.coretests;
import junit.framework.Test;
import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class StatsStore {
static final String sysVersion = "1.0";
static Connection conn;
static Statement stmt;
static PreparedStatement insertStmt, selectByNameStmt, updateStmt;
static PreparedStatement insertDetStmt, insertEventStmt;
static PreparedStatement selectAllStmt;
public static long now;
static int compareDuration(long dur, long refDur) {
long diff = dur - refDur;
if (diff <= 0) {
if ((double)-diff / refDur > 0.5) return 1; // remarkably faster
else return 0; // equivalent duration (maybe a bit faster)
}
else if (diff < 20) return 0; // not measurably slower: equivalent duration
else if ((double)diff / refDur < 0.2) return 0; // just little slower: equivalent duration
else return -1; // relevantly SLOWer
}
static void initStats(PerfStatCollector.Item a) {
a.statMinDuration = a.duration;
a.statMaxDuration = a.duration;
a.statAvgDuration = a.duration;
a.statCount = 1;
}
static void adjustStats(PerfStatCollector.Item a) {
if (a.duration < a.statMinDuration) a.statMinDuration = a.duration;
else
if (a.duration > a.statMaxDuration) a.statMaxDuration = a.duration;
a.statAvgDuration = ((a.statAvgDuration * a.statCount + a.duration) / (a.statCount + 1));
a.statCount++;
}
static void adjustStatsOptimistic(PerfStatCollector.Item a) {
adjustStats(a);
// Could consider reducing a.statMaxDuration.
}
static void use1(PerfStatCollector.Item a) {
Test test;
int pos;
PreparedStatement selectStmt = selectByNameStmt;
try {
try {
insertStmt.setString(1, a.test.toString());
insertStmt.execute();
} catch (SQLException e) {}
selectStmt.setString(1, a.test.toString());
ResultSet row = selectStmt.executeQuery();
row.first();
pos = 1;
a.id = row.getInt(pos); pos++;
a.bestRes = row.getInt(pos); pos++;
a.lastBestAt = row.getLong(pos); pos++;
a.lastRes = row.getInt(pos); pos++;
a.lastDuration = row.getLong(pos); pos++;
a.statCount = row.getInt(pos); pos++;
a.statAvgDuration = row.getDouble(pos); pos++;
a.statMinDuration = row.getLong(pos); pos++;
a.statMaxDuration = row.getLong(pos); pos++;
if (a.res == 0) {
if (a.bestRes == 100) {
a.bestRes = 0; a.lastBestAt = now;
a.histRelevance = 0; // Good from scratch.
a.isTransition = false;
initStats(a);
} else if (a.bestRes != 0) {
a.bestRes = 0; a.lastBestAt = now;
a.histRelevance = 4; // "Good" for the first time:
a.isTransition = true; // was bad before.
initStats(a);
} else if (a.lastRes != 0) {
a.bestRes = 0; a.lastBestAt = now;
a.histRelevance = 3; // "good" again:
a.isTransition = true; // was bad in between.
adjustStats(a);
} else {
// res == lastRes == bestRes == 0:
int cmp = compareDuration(a.duration, a.statMinDuration);
if (cmp >= 0) {
a.bestRes = 0; a.lastBestAt = now;
if (cmp > 0) {
a.histRelevance = 2; // "Fast"er than ever before.
a.isTransition = true;
adjustStatsOptimistic(a);
} else if (compareDuration(a.duration, a.lastDuration) > 0) {
// As fast as best but faster than last run:
a.histRelevance = 1; // "fast" again.
a.isTransition = true;
adjustStatsOptimistic(a);
} else {
a.histRelevance = 0; // Equivalent Duration:
a.isTransition = false; // usual good case.
adjustStats(a);
}
} else {
if (compareDuration(a.duration, a.lastDuration) < 0) {
a.histRelevance = -2; // "SLOW"!!!
a.isTransition = true;
adjustStats(a);
} else {
a.histRelevance = -2; // Still "SLOW"!!!
a.isTransition = false; // (But NO transition!)
adjustStats(a);
}
}
}
} else if (a.bestRes == 0) {
if (a.lastRes == 0) {
a.histRelevance = -4; // "VBAD"!!!
a.isTransition = true;
} else {
a.histRelevance = -4; // Still "VBAD"!!!
a.isTransition = false; // (But NO transition!)
}
// DON'T adjust statistics: they should reflect good runs, only.
} else if (a.bestRes == 100) {
a.bestRes = -3; // Just mark as NOT good.
a.histRelevance = -3; // Bad (initial run).
a.isTransition = true;
initStats(a);
} else {
a.histRelevance = 0; // Still Failure or Error:
a.isTransition = false; // usual bad case.
adjustStats(a);
}
pos = 1;
updateStmt.setInt(pos, a.bestRes); pos++;
updateStmt.setLong(pos, a.lastBestAt); pos++;
updateStmt.setInt(pos, a.res); pos++;
updateStmt.setLong(pos, a.duration); pos++;
updateStmt.setInt(pos, a.statCount); pos++;
updateStmt.setDouble(pos, a.statAvgDuration); pos++;
updateStmt.setLong(pos, a.statMinDuration); pos++;
updateStmt.setLong(pos, a.statMaxDuration); pos++;
updateStmt.setInt(pos, a.id); pos++;
updateStmt.execute();
pos = 1;
insertDetStmt.setInt(pos, a.id); pos++;
insertDetStmt.setLong(pos, now); pos++;
insertDetStmt.setInt(pos, a.statCount); pos++;
insertDetStmt.setInt(pos, a.res); pos++;
insertDetStmt.setLong(pos, a.duration); pos++;
insertDetStmt.execute();
if (a.isTransition) {
pos = 1;
insertEventStmt.setInt(pos, a.id); pos++;
insertEventStmt.setLong(pos, now); pos++;
insertEventStmt.setInt(pos, a.histRelevance); pos++;
insertEventStmt.setInt(pos, a.res); pos++;
insertEventStmt.setLong(pos, a.duration); pos++;
insertEventStmt.execute();
}
}
catch (SQLException e) {
int x = 0;
}
}
// static void use2(PerfStatCollector.Item a) {
// }
static void execOrIgnore(String sql) {
try { stmt.execute(sql); }
catch (SQLException e) {}
}
static void open(String jdbcDriver, String connectionURL)
throws Exception {
// try {
Class.forName(jdbcDriver).newInstance();
conn = DriverManager.getConnection(connectionURL);
stmt = conn.createStatement();
String dbVersion;
try {
ResultSet res = stmt.executeQuery("SELECT id FROM Version");
res.first();
dbVersion = res.getString(1);
}
catch (SQLException e) {
dbVersion = "";
}
if (!dbVersion.equals(sysVersion)) {
execOrIgnore("DROP TABLE Test_Cases;");
stmt.execute("CREATE TABLE Test_Cases (" +
" id INTEGER PRIMARY KEY AUTOINCREMENT, " +
" name VARCHAR(255) UNIQUE, " +
// (best_Res != 0) ==> (last_Best_At == 0) never ran good!
" best_Res INTEGER, last_Best_At INTEGER, " +
" last_Res INTEGER, last_Duration INTEGER, " +
" stat_Cnt INTEGER, stat_Avg NUMBER(20, 2), " +
" stat_Min INTEGER, stat_Max INTEGER);");
execOrIgnore("DROP TABLE Test_Case_Runs;");
stmt.execute("CREATE TABLE Test_Case_Runs (" +
" test_Id INTEGER, run_At INTEGER, " +
" iteration INTEGER, res INTEGER, duration INTEGER, " +
" PRIMARY KEY (test_Id, run_At));");
execOrIgnore("DROP TABLE Test_Case_Events;");
stmt.execute("CREATE TABLE Test_Case_Events (" +
" test_Id INTEGER, run_At INTEGER, " +
" relevance INTEGER, " +
" res INTEGER, duration INTEGER, " +
" PRIMARY KEY (test_Id, run_At));");
// stmt.execute("CREATE PROCEDURE useSample (IN pName TEXT, " +
// "pRes INTEGER, pDuration INTEGER, pTime INTEGER) " +
// "BEGIN " +
// " INSERT OR IGNORE INTO TestCases (name)" +
// " VALUES (pName);" +
// "END;");
execOrIgnore("DROP TABLE Version;");
stmt.execute("CREATE TABLE Version(id VARCHAR(31));");
stmt.execute("INSERT INTO Version (id) VALUES ('" + sysVersion + "');");
}
// updateStmt = conn.prepareStatement("useSample(:name, :res, :duration, :time)");
// firstConnection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
// firstStmt = firstConnection.createStatement();
// firstStmt.execute("create table tbl1(one varchar(10), two smallint)");
insertStmt = conn.prepareStatement("INSERT " +
"INTO Test_Cases (name, stat_Cnt) VALUES (?, 0);");
selectByNameStmt = conn.prepareStatement("SELECT id, " +
" IFNULL(best_Res, 100), IFNULL(last_Best_At, 0), " +
" IFNULL(last_Res, 100), IFNULL(last_Duration, 0), " +
" IFNULL(stat_Cnt, 0), IFNULL(stat_Avg, 0), " +
" IFNULL(stat_Min, 0), IFNULL(stat_Max, 0) " +
"FROM Test_Cases WHERE name = ?;");
updateStmt = conn.prepareStatement("UPDATE Test_Cases SET " +
" best_Res = ?, last_Best_At = ?, " +
" last_Res = ?, last_Duration = ?, " +
" stat_Cnt = ?, stat_Avg = ?, " +
" stat_Min = ?, stat_Max = ? " +
"WHERE id = ?;");
insertDetStmt = conn.prepareStatement("INSERT " +
"INTO Test_Case_Runs (test_Id, run_At, iteration, res, duration) " +
"VALUES (?, ?, ?, ?, ?);");
insertEventStmt = conn.prepareStatement("INSERT " +
"INTO Test_Case_Events (test_Id, run_At, relevance, res, duration) " +
"VALUES (?, ?, ?, ?, ?);");
selectAllStmt = conn.prepareStatement("SELECT id, name, " +
"last_Res, stat_Cnt, " +
"last_Duration, stat_Avg, stat_Min, stat_Max " +
"FROM Test_Cases;");
try {
// ResultSet res = stmt.executeQuery("PRAGMA CACHE_SIZE;");
// res.first();
// System.out.print("CACHE_SIZE = ");
// System.out.println(res.getString(1));
// stmt.execute("PRAGMA CACHE_SIZE = 5000;");
stmt.execute("PRAGMA SYNCHRONOUS = OFF;");
stmt.execute("PRAGMA temp_store = MEMORY;");
}
catch (SQLException e) {
dbVersion = "";
}
stmt.close();
conn.commit();
// }
// catch (Exception e) {
// conn = null;
// }
// return conn != null;
}
static void close() {
try {
conn.commit();
conn.close();
conn = null;
}
catch (Exception e) {
conn = null;
}
}
}