1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.coretests; 18 19 20 import junit.framework.Test; 21 22 import java.io.File; 23 import java.sql.Connection; 24 import java.sql.DriverManager; 25 import java.sql.PreparedStatement; 26 import java.sql.ResultSet; 27 import java.sql.SQLException; 28 import java.sql.Statement; 29 30 31 public class StatsStore { 32 33 static final String sysVersion = "1.0"; 34 35 static Connection conn; 36 static Statement stmt; 37 static PreparedStatement insertStmt, selectByNameStmt, updateStmt; 38 static PreparedStatement insertDetStmt, insertEventStmt; 39 static PreparedStatement selectAllStmt; 40 41 public static long now; 42 43 static int compareDuration(long dur, long refDur) { 44 long diff = dur - refDur; 45 if (diff <= 0) { 46 if ((double)-diff / refDur > 0.5) return 1; // remarkably faster 47 else return 0; // equivalent duration (maybe a bit faster) 48 } 49 else if (diff < 20) return 0; // not measurably slower: equivalent duration 50 else if ((double)diff / refDur < 0.2) return 0; // just little slower: equivalent duration 51 else return -1; // relevantly SLOWer 52 } 53 54 static void initStats(PerfStatCollector.Item a) { 55 a.statMinDuration = a.duration; 56 a.statMaxDuration = a.duration; 57 a.statAvgDuration = a.duration; 58 a.statCount = 1; 59 } 60 61 static void adjustStats(PerfStatCollector.Item a) { 62 if (a.duration < a.statMinDuration) a.statMinDuration = a.duration; 63 else 64 if (a.duration > a.statMaxDuration) a.statMaxDuration = a.duration; 65 a.statAvgDuration = ((a.statAvgDuration * a.statCount + a.duration) / (a.statCount + 1)); 66 a.statCount++; 67 } 68 69 static void adjustStatsOptimistic(PerfStatCollector.Item a) { 70 adjustStats(a); 71 // Could consider reducing a.statMaxDuration. 72 } 73 74 static void use1(PerfStatCollector.Item a) { 75 Test test; 76 int pos; 77 PreparedStatement selectStmt = selectByNameStmt; 78 try { 79 try { 80 insertStmt.setString(1, a.test.toString()); 81 insertStmt.execute(); 82 } catch (SQLException e) {} 83 selectStmt.setString(1, a.test.toString()); 84 ResultSet row = selectStmt.executeQuery(); 85 row.first(); 86 pos = 1; 87 a.id = row.getInt(pos); pos++; 88 a.bestRes = row.getInt(pos); pos++; 89 a.lastBestAt = row.getLong(pos); pos++; 90 a.lastRes = row.getInt(pos); pos++; 91 a.lastDuration = row.getLong(pos); pos++; 92 a.statCount = row.getInt(pos); pos++; 93 a.statAvgDuration = row.getDouble(pos); pos++; 94 a.statMinDuration = row.getLong(pos); pos++; 95 a.statMaxDuration = row.getLong(pos); pos++; 96 if (a.res == 0) { 97 if (a.bestRes == 100) { 98 a.bestRes = 0; a.lastBestAt = now; 99 a.histRelevance = 0; // Good from scratch. 100 a.isTransition = false; 101 initStats(a); 102 } else if (a.bestRes != 0) { 103 a.bestRes = 0; a.lastBestAt = now; 104 a.histRelevance = 4; // "Good" for the first time: 105 a.isTransition = true; // was bad before. 106 initStats(a); 107 } else if (a.lastRes != 0) { 108 a.bestRes = 0; a.lastBestAt = now; 109 a.histRelevance = 3; // "good" again: 110 a.isTransition = true; // was bad in between. 111 adjustStats(a); 112 } else { 113 // res == lastRes == bestRes == 0: 114 int cmp = compareDuration(a.duration, a.statMinDuration); 115 if (cmp >= 0) { 116 a.bestRes = 0; a.lastBestAt = now; 117 if (cmp > 0) { 118 a.histRelevance = 2; // "Fast"er than ever before. 119 a.isTransition = true; 120 adjustStatsOptimistic(a); 121 } else if (compareDuration(a.duration, a.lastDuration) > 0) { 122 // As fast as best but faster than last run: 123 a.histRelevance = 1; // "fast" again. 124 a.isTransition = true; 125 adjustStatsOptimistic(a); 126 } else { 127 a.histRelevance = 0; // Equivalent Duration: 128 a.isTransition = false; // usual good case. 129 adjustStats(a); 130 } 131 } else { 132 if (compareDuration(a.duration, a.lastDuration) < 0) { 133 a.histRelevance = -2; // "SLOW"!!! 134 a.isTransition = true; 135 adjustStats(a); 136 } else { 137 a.histRelevance = -2; // Still "SLOW"!!! 138 a.isTransition = false; // (But NO transition!) 139 adjustStats(a); 140 } 141 } 142 } 143 } else if (a.bestRes == 0) { 144 if (a.lastRes == 0) { 145 a.histRelevance = -4; // "VBAD"!!! 146 a.isTransition = true; 147 } else { 148 a.histRelevance = -4; // Still "VBAD"!!! 149 a.isTransition = false; // (But NO transition!) 150 } 151 // DON'T adjust statistics: they should reflect good runs, only. 152 } else if (a.bestRes == 100) { 153 a.bestRes = -3; // Just mark as NOT good. 154 a.histRelevance = -3; // Bad (initial run). 155 a.isTransition = true; 156 initStats(a); 157 } else { 158 a.histRelevance = 0; // Still Failure or Error: 159 a.isTransition = false; // usual bad case. 160 adjustStats(a); 161 } 162 pos = 1; 163 updateStmt.setInt(pos, a.bestRes); pos++; 164 updateStmt.setLong(pos, a.lastBestAt); pos++; 165 updateStmt.setInt(pos, a.res); pos++; 166 updateStmt.setLong(pos, a.duration); pos++; 167 updateStmt.setInt(pos, a.statCount); pos++; 168 updateStmt.setDouble(pos, a.statAvgDuration); pos++; 169 updateStmt.setLong(pos, a.statMinDuration); pos++; 170 updateStmt.setLong(pos, a.statMaxDuration); pos++; 171 updateStmt.setInt(pos, a.id); pos++; 172 updateStmt.execute(); 173 pos = 1; 174 insertDetStmt.setInt(pos, a.id); pos++; 175 insertDetStmt.setLong(pos, now); pos++; 176 insertDetStmt.setInt(pos, a.statCount); pos++; 177 insertDetStmt.setInt(pos, a.res); pos++; 178 insertDetStmt.setLong(pos, a.duration); pos++; 179 insertDetStmt.execute(); 180 if (a.isTransition) { 181 pos = 1; 182 insertEventStmt.setInt(pos, a.id); pos++; 183 insertEventStmt.setLong(pos, now); pos++; 184 insertEventStmt.setInt(pos, a.histRelevance); pos++; 185 insertEventStmt.setInt(pos, a.res); pos++; 186 insertEventStmt.setLong(pos, a.duration); pos++; 187 insertEventStmt.execute(); 188 } 189 } 190 catch (SQLException e) { 191 int x = 0; 192 } 193 } 194 195 // static void use2(PerfStatCollector.Item a) { 196 // } 197 198 static void execOrIgnore(String sql) { 199 try { stmt.execute(sql); } 200 catch (SQLException e) {} 201 } 202 203 static void open(String jdbcDriver, String connectionURL) 204 throws Exception { 205 // try { 206 Class.forName(jdbcDriver).newInstance(); 207 conn = DriverManager.getConnection(connectionURL); 208 stmt = conn.createStatement(); 209 String dbVersion; 210 try { 211 ResultSet res = stmt.executeQuery("SELECT id FROM Version"); 212 res.first(); 213 dbVersion = res.getString(1); 214 } 215 catch (SQLException e) { 216 dbVersion = ""; 217 } 218 if (!dbVersion.equals(sysVersion)) { 219 execOrIgnore("DROP TABLE Test_Cases;"); 220 stmt.execute("CREATE TABLE Test_Cases (" + 221 " id INTEGER PRIMARY KEY AUTOINCREMENT, " + 222 " name VARCHAR(255) UNIQUE, " + 223 // (best_Res != 0) ==> (last_Best_At == 0) never ran good! 224 " best_Res INTEGER, last_Best_At INTEGER, " + 225 " last_Res INTEGER, last_Duration INTEGER, " + 226 " stat_Cnt INTEGER, stat_Avg NUMBER(20, 2), " + 227 " stat_Min INTEGER, stat_Max INTEGER);"); 228 execOrIgnore("DROP TABLE Test_Case_Runs;"); 229 stmt.execute("CREATE TABLE Test_Case_Runs (" + 230 " test_Id INTEGER, run_At INTEGER, " + 231 " iteration INTEGER, res INTEGER, duration INTEGER, " + 232 " PRIMARY KEY (test_Id, run_At));"); 233 execOrIgnore("DROP TABLE Test_Case_Events;"); 234 stmt.execute("CREATE TABLE Test_Case_Events (" + 235 " test_Id INTEGER, run_At INTEGER, " + 236 " relevance INTEGER, " + 237 " res INTEGER, duration INTEGER, " + 238 " PRIMARY KEY (test_Id, run_At));"); 239 // stmt.execute("CREATE PROCEDURE useSample (IN pName TEXT, " + 240 // "pRes INTEGER, pDuration INTEGER, pTime INTEGER) " + 241 // "BEGIN " + 242 // " INSERT OR IGNORE INTO TestCases (name)" + 243 // " VALUES (pName);" + 244 // "END;"); 245 execOrIgnore("DROP TABLE Version;"); 246 stmt.execute("CREATE TABLE Version(id VARCHAR(31));"); 247 stmt.execute("INSERT INTO Version (id) VALUES ('" + sysVersion + "');"); 248 } 249 // updateStmt = conn.prepareStatement("useSample(:name, :res, :duration, :time)"); 250 // firstConnection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); 251 // firstStmt = firstConnection.createStatement(); 252 // firstStmt.execute("create table tbl1(one varchar(10), two smallint)"); 253 insertStmt = conn.prepareStatement("INSERT " + 254 "INTO Test_Cases (name, stat_Cnt) VALUES (?, 0);"); 255 selectByNameStmt = conn.prepareStatement("SELECT id, " + 256 " IFNULL(best_Res, 100), IFNULL(last_Best_At, 0), " + 257 " IFNULL(last_Res, 100), IFNULL(last_Duration, 0), " + 258 " IFNULL(stat_Cnt, 0), IFNULL(stat_Avg, 0), " + 259 " IFNULL(stat_Min, 0), IFNULL(stat_Max, 0) " + 260 "FROM Test_Cases WHERE name = ?;"); 261 updateStmt = conn.prepareStatement("UPDATE Test_Cases SET " + 262 " best_Res = ?, last_Best_At = ?, " + 263 " last_Res = ?, last_Duration = ?, " + 264 " stat_Cnt = ?, stat_Avg = ?, " + 265 " stat_Min = ?, stat_Max = ? " + 266 "WHERE id = ?;"); 267 insertDetStmt = conn.prepareStatement("INSERT " + 268 "INTO Test_Case_Runs (test_Id, run_At, iteration, res, duration) " + 269 "VALUES (?, ?, ?, ?, ?);"); 270 insertEventStmt = conn.prepareStatement("INSERT " + 271 "INTO Test_Case_Events (test_Id, run_At, relevance, res, duration) " + 272 "VALUES (?, ?, ?, ?, ?);"); 273 selectAllStmt = conn.prepareStatement("SELECT id, name, " + 274 "last_Res, stat_Cnt, " + 275 "last_Duration, stat_Avg, stat_Min, stat_Max " + 276 "FROM Test_Cases;"); 277 278 try { 279 // ResultSet res = stmt.executeQuery("PRAGMA CACHE_SIZE;"); 280 // res.first(); 281 // System.out.print("CACHE_SIZE = "); 282 // System.out.println(res.getString(1)); 283 // stmt.execute("PRAGMA CACHE_SIZE = 5000;"); 284 stmt.execute("PRAGMA SYNCHRONOUS = OFF;"); 285 stmt.execute("PRAGMA temp_store = MEMORY;"); 286 } 287 catch (SQLException e) { 288 dbVersion = ""; 289 } 290 stmt.close(); 291 conn.commit(); 292 // } 293 // catch (Exception e) { 294 // conn = null; 295 // } 296 // return conn != null; 297 } 298 299 static void close() { 300 try { 301 conn.commit(); 302 conn.close(); 303 conn = null; 304 } 305 catch (Exception e) { 306 conn = null; 307 } 308 } 309 } 310