StatsStore.java revision f6c387128427e121477c1b32ad35cdcaa5101ba3
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
17package com.google.coretests;
18
19
20import junit.framework.Test;
21
22import java.io.File;
23import java.sql.Connection;
24import java.sql.DriverManager;
25import java.sql.PreparedStatement;
26import java.sql.ResultSet;
27import java.sql.SQLException;
28import java.sql.Statement;
29
30
31public 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