/* * 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; } } }