Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0697331e authored by Edgar Arriaga García's avatar Edgar Arriaga García Committed by Android (Google) Code Review
Browse files

Merge "Add sql statement cache miss info and test"

parents a77aa072 506e3f17
Loading
Loading
Loading
Loading
+47 −0
Original line number Diff line number Diff line
@@ -24,10 +24,12 @@ import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.perftests.utils.BenchmarkState;
import android.perftests.utils.PerfStatusReporter;
import android.util.Log;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
import java.io.File;
import java.util.ArrayList;
import java.util.Random;
import org.junit.After;
import org.junit.Before;
@@ -106,6 +108,51 @@ public class SQLiteDatabasePerfTest {
        }
    }

    @Test
    public void testSelectCacheMissRate() {
        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();

        insertT1TestDataSet();

        ArrayList<String> queryPool = new ArrayList<>();
        queryPool.add("SELECT _ID, COL_A, COL_B, COL_C FROM T1 WHERE _ID=?");
        queryPool.add("SELECT _ID FROM T1 WHERE _ID=?");
        queryPool.add("SELECT COL_A FROM T1 WHERE _ID=?");
        queryPool.add("SELECT COL_B FROM T1 WHERE _ID=?");
        queryPool.add("SELECT COL_C FROM T1 WHERE _ID=?");
        queryPool.add("SELECT _ID, COL_A FROM T1 WHERE _ID=?");
        queryPool.add("SELECT _ID, COL_B FROM T1 WHERE _ID=?");
        queryPool.add("SELECT _ID, COL_C FROM T1 WHERE _ID=?");
        queryPool.add("SELECT COL_A, COL_B FROM T1 WHERE _ID=?");
        queryPool.add("SELECT COL_A, COL_C FROM T1 WHERE _ID=?");
        queryPool.add("SELECT COL_B, COL_C FROM T1 WHERE _ID=?");
        while (state.keepRunning()) {
            Random rnd = new Random(0);

            int queries = 1000;
            for (int iQuery = 0; iQuery < queries; ++iQuery) {
                int queryIndex = rnd.nextInt(queryPool.size());
                int index = rnd.nextInt(DEFAULT_DATASET_SIZE);

                try (Cursor cursor = mDatabase.rawQuery(
                             queryPool.get(queryIndex), new String[] {String.valueOf(index)})) {
                    assertTrue(cursor.moveToNext());
                }
            }
        }

        Log.d("testSelectMemory",
                "cacheMissRate: " + mDatabase.getStatementCacheMissRate()
                        + "Total Statements: " + mDatabase.getTotalPreparedStatements()
                        + ". Misses: " + mDatabase.getTotalStatementCacheMisses());

        // Make sure caching is working and our miss rate should definitely be less than 100%
        // however, we would expect this number to be actually closer to 0.
        assertTrue(mDatabase.getStatementCacheMissRate() < 1);
        mDatabase.close();
        mContext.deleteDatabase(DB_NAME);
    }

    @Test
    public void testSelectMultipleRows() {
        insertT1TestDataSet();
+2 −2
Original line number Diff line number Diff line
@@ -975,8 +975,8 @@ package android.database.sqlite {
  }

  public static class SQLiteDebug.DbStats {
    ctor public SQLiteDebug.DbStats(String, long, long, int, int, int, int);
    field public String cache;
    ctor public SQLiteDebug.DbStats(@NonNull String, long, long, int, int, int, int, boolean);
    field public final boolean arePoolStats;
    field public String dbName;
    field public long dbSize;
    field public int lookaside;
+36 −8
Original line number Diff line number Diff line
@@ -1026,7 +1026,10 @@ public final class ActivityThread extends ClientTransactionHandler
    }

    private class ApplicationThread extends IApplicationThread.Stub {
        private static final String DB_INFO_FORMAT = "  %8s %8s %14s %14s  %s";
        private static final String DB_CONNECTION_INFO_HEADER = "  %8s %8s %14s %5s %5s %5s  %s";
        private static final String DB_CONNECTION_INFO_FORMAT = "  %8s %8s %14s %5d %5d %5d  %s";
        private static final String DB_POOL_INFO_HEADER = "  %13s %13s %13s  %s";
        private static final String DB_POOL_INFO_FORMAT = "  %13d %13d %13d  %s";

        public final void scheduleReceiver(Intent intent, ActivityInfo info,
                CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
@@ -1454,8 +1457,9 @@ public final class ActivityThread extends ClientTransactionHandler
                    pw.print(','); pw.print(dbStats.pageSize);
                    pw.print(','); pw.print(dbStats.dbSize);
                    pw.print(','); pw.print(dbStats.lookaside);
                    pw.print(','); pw.print(dbStats.cache);
                    pw.print(','); pw.print(dbStats.cache);
                    pw.print(','); pw.print(dbStats.cacheHits);
                    pw.print(','); pw.print(dbStats.cacheMisses);
                    pw.print(','); pw.print(dbStats.cacheSize);
                }
                pw.println();

@@ -1490,15 +1494,34 @@ public final class ActivityThread extends ClientTransactionHandler
            int N = stats.dbStats.size();
            if (N > 0) {
                pw.println(" DATABASES");
                printRow(pw, DB_INFO_FORMAT, "pgsz", "dbsz", "Lookaside(b)", "cache",
                        "Dbname");
                printRow(pw, DB_CONNECTION_INFO_HEADER, "pgsz", "dbsz", "Lookaside(b)",
                        "cache hits", "cache misses", "cache size", "Dbname");
                pw.println("PER CONNECTION STATS");
                for (int i = 0; i < N; i++) {
                    DbStats dbStats = stats.dbStats.get(i);
                    printRow(pw, DB_INFO_FORMAT,
                    if (dbStats.arePoolStats) {
                        // these will be printed after
                        continue;
                    }
                    printRow(pw, DB_CONNECTION_INFO_FORMAT,
                            (dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
                            (dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
                            (dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
                            dbStats.cache, dbStats.dbName);
                            dbStats.cacheHits, dbStats.cacheMisses, dbStats.cacheSize,
                            dbStats.dbName);
                }
                // Print stats accumulated through all the connections that have existed in the
                // pool since it was opened.
                pw.println("POOL STATS");
                printRow(pw, DB_POOL_INFO_HEADER, "cache hits", "cache misses", "cache size",
                        "Dbname");
                for (int i = 0; i < N; i++) {
                    DbStats dbStats = stats.dbStats.get(i);
                    if (!dbStats.arePoolStats) {
                        continue;
                    }
                    printRow(pw, DB_POOL_INFO_FORMAT, dbStats.cacheHits, dbStats.cacheMisses,
                            dbStats.cacheSize, dbStats.dbName);
                }
            }

@@ -1623,7 +1646,12 @@ public final class ActivityThread extends ClientTransactionHandler
                proto.write(MemInfoDumpProto.AppData.SqlStats.Database.DB_SIZE, dbStats.dbSize);
                proto.write(MemInfoDumpProto.AppData.SqlStats.Database.LOOKASIDE_B,
                        dbStats.lookaside);
                proto.write(MemInfoDumpProto.AppData.SqlStats.Database.CACHE, dbStats.cache);
                proto.write(
                        MemInfoDumpProto.AppData.SqlStats.Database.CACHE_HITS, dbStats.cacheHits);
                proto.write(MemInfoDumpProto.AppData.SqlStats.Database.CACHE_MISSES,
                        dbStats.cacheMisses);
                proto.write(
                        MemInfoDumpProto.AppData.SqlStats.Database.CACHE_SIZE, dbStats.cacheSize);
                proto.end(dToken);
            }
            proto.end(sToken);
+6 −5
Original line number Diff line number Diff line
@@ -1053,6 +1053,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
    }

    private PreparedStatement acquirePreparedStatement(String sql) {
        ++mPool.mTotalPrepareStatements;
        PreparedStatement statement = mPreparedStatementCache.get(sql);
        boolean skipCache = false;
        if (statement != null) {
@@ -1064,7 +1065,7 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
            // statement but do not cache it.
            skipCache = true;
        }

        ++mPool.mTotalPrepareStatementCacheMiss;
        final long statementPtr = nativePrepareStatement(mConnectionPtr, sql);
        try {
            final int numParameters = nativeGetParameterCount(mConnectionPtr, statementPtr);
@@ -1320,7 +1321,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
                if (!path.isEmpty()) {
                    label.append(": ").append(path);
                }
                dbStatsList.add(new DbStats(label.toString(), pageCount, pageSize, 0, 0, 0, 0));
                dbStatsList.add(
                        new DbStats(label.toString(), pageCount, pageSize, 0, 0, 0, 0, false));
            }
        } catch (SQLiteException ex) {
            // Ignore.
@@ -1349,9 +1351,8 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
            label = mConfiguration.path + " (" + mConnectionId + ")";
        }
        return new DbStats(label, pageCount, pageSize, lookaside,
                mPreparedStatementCache.hitCount(),
                mPreparedStatementCache.missCount(),
                mPreparedStatementCache.size());
                mPreparedStatementCache.hitCount(), mPreparedStatementCache.missCount(),
                mPreparedStatementCache.size(), false);
    }

    @Override
+21 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import android.util.Printer;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;

import dalvik.annotation.optimization.NeverCompile;
import dalvik.system.CloseGuard;

import java.io.Closeable;
@@ -103,6 +104,10 @@ public final class SQLiteConnectionPool implements Closeable {
            new ArrayList<SQLiteConnection>();
    private SQLiteConnection mAvailablePrimaryConnection;

    // Prepare statement cache statistics
    public int mTotalPrepareStatementCacheMiss = 0;
    public int mTotalPrepareStatements = 0;

    @GuardedBy("mLock")
    private IdleConnectionHandler mIdleConnectionHandler;

@@ -507,6 +512,12 @@ public final class SQLiteConnectionPool implements Closeable {
            for (SQLiteConnection connection : mAcquiredConnections.keySet()) {
                connection.collectDbStatsUnsafe(dbStatsList);
            }

            // Global pool stats
            DbStats poolStats = new DbStats(mConfiguration.path, 0, 0, 0,
                    mTotalPrepareStatements - mTotalPrepareStatementCacheMiss,
                    mTotalPrepareStatementCacheMiss, mTotalPrepareStatements, true);
            dbStatsList.add(poolStats);
        }
    }

@@ -1203,6 +1214,16 @@ public final class SQLiteConnectionPool implements Closeable {
        }
    }

    /** @hide */
    @NeverCompile
    public double getStatementCacheMissRate() {
        if (mTotalPrepareStatements == 0) {
            // no statements executed thus no miss rate.
            return 0;
        }
        return (double) mTotalPrepareStatementCacheMiss / (double) mTotalPrepareStatements;
    }

    public long getTotalStatementsTime() {
        return mTotalStatementsTime.get();
    }
Loading