Merge "Improve the slow query instrumentation." into ics-mr0

This commit is contained in:
Jeff Brown
2011-10-28 18:21:05 -07:00
committed by Android (Google) Code Review
7 changed files with 76 additions and 30 deletions

View File

@@ -55,6 +55,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
public int mWindowPtr; public int mWindowPtr;
private int mStartPos; private int mStartPos;
private final String mName;
private final CloseGuard mCloseGuard = CloseGuard.get(); private final CloseGuard mCloseGuard = CloseGuard.get();
@@ -85,6 +86,8 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
private static native boolean nativePutDouble(int windowPtr, double value, int row, int column); private static native boolean nativePutDouble(int windowPtr, double value, int row, int column);
private static native boolean nativePutNull(int windowPtr, int row, int column); private static native boolean nativePutNull(int windowPtr, int row, int column);
private static native String nativeGetName(int windowPtr);
/** /**
* Creates a new empty cursor window and gives it a name. * Creates a new empty cursor window and gives it a name.
* <p> * <p>
@@ -100,6 +103,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
*/ */
public CursorWindow(String name, boolean localWindow) { public CursorWindow(String name, boolean localWindow) {
mStartPos = 0; mStartPos = 0;
mName = name;
mWindowPtr = nativeCreate(name, sCursorWindowSize, localWindow); mWindowPtr = nativeCreate(name, sCursorWindowSize, localWindow);
if (mWindowPtr == 0) { if (mWindowPtr == 0) {
throw new CursorWindowAllocationException("Cursor window allocation of " + throw new CursorWindowAllocationException("Cursor window allocation of " +
@@ -130,6 +134,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
throw new CursorWindowAllocationException("Cursor window could not be " throw new CursorWindowAllocationException("Cursor window could not be "
+ "created from binder."); + "created from binder.");
} }
mName = nativeGetName(mWindowPtr);
mCloseGuard.open("close"); mCloseGuard.open("close");
} }
@@ -156,6 +161,14 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
} }
} }
/**
* Gets the name of this cursor window.
* @hide
*/
public String getName() {
return mName;
}
/** /**
* Closes the cursor window and frees its underlying resources when all other * Closes the cursor window and frees its underlying resources when all other
* remaining references have been released. * remaining references have been released.
@@ -778,4 +791,9 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString(); String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString();
return "# Open Cursors=" + total + s; return "# Open Cursors=" + total + s;
} }
@Override
public String toString() {
return getName() + " {" + Integer.toHexString(mWindowPtr) + "}";
}
} }

View File

@@ -306,10 +306,6 @@ public class SQLiteDatabase extends SQLiteClosable {
/** Used to find out where this object was created in case it never got closed. */ /** Used to find out where this object was created in case it never got closed. */
private final Throwable mStackTrace; private final Throwable mStackTrace;
// System property that enables logging of slow queries. Specify the threshold in ms.
private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold";
private final int mSlowQueryThreshold;
/** stores the list of statement ids that need to be finalized by sqlite */ /** stores the list of statement ids that need to be finalized by sqlite */
private final ArrayList<Integer> mClosedStatementIds = new ArrayList<Integer>(); private final ArrayList<Integer> mClosedStatementIds = new ArrayList<Integer>();
@@ -1559,11 +1555,6 @@ public class SQLiteDatabase extends SQLiteClosable {
String editTable) { String editTable) {
verifyDbIsOpen(); verifyDbIsOpen();
BlockGuard.getThreadPolicy().onReadFromDisk(); BlockGuard.getThreadPolicy().onReadFromDisk();
long timeStart = 0;
if (false || mSlowQueryThreshold != -1) {
timeStart = System.currentTimeMillis();
}
SQLiteDatabase db = getDbConnection(sql); SQLiteDatabase db = getDbConnection(sql);
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(db, sql, editTable); SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(db, sql, editTable);
@@ -1574,24 +1565,6 @@ public class SQLiteDatabase extends SQLiteClosable {
cursorFactory != null ? cursorFactory : mFactory, cursorFactory != null ? cursorFactory : mFactory,
selectionArgs); selectionArgs);
} finally { } finally {
if (false || mSlowQueryThreshold != -1) {
// Force query execution
int count = -1;
if (cursor != null) {
count = cursor.getCount();
}
long duration = System.currentTimeMillis() - timeStart;
if (false || duration >= mSlowQueryThreshold) {
Log.v(SQLiteCursor.TAG,
"query (" + duration + " ms): " + driver.toString() + ", args are "
+ (selectionArgs != null
? TextUtils.join(",", selectionArgs)
: "<null>") + ", count is " + count);
}
}
releaseDbConnection(db); releaseDbConnection(db);
} }
return cursor; return cursor;
@@ -1967,7 +1940,6 @@ public class SQLiteDatabase extends SQLiteClosable {
setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE); setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE);
mFlags = flags; mFlags = flags;
mPath = path; mPath = path;
mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace(); mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
mFactory = factory; mFactory = factory;
mPrograms = new WeakHashMap<SQLiteClosable,Object>(); mPrograms = new WeakHashMap<SQLiteClosable,Object>();

View File

@@ -18,6 +18,8 @@ package android.database.sqlite;
import java.util.ArrayList; import java.util.ArrayList;
import android.os.Build;
import android.os.SystemProperties;
import android.util.Log; import android.util.Log;
/** /**
@@ -64,6 +66,28 @@ public final class SQLiteDebug {
public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE = public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE =
Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE); Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE);
/**
* True to enable database performance testing instrumentation.
* @hide
*/
public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
/**
* Determines whether a query should be logged.
*
* Reads the "db.log.slow_query_threshold" system property, which can be changed
* by the user at any time. If the value is zero, then all queries will
* be considered slow. If the value does not exist, then no queries will
* be considered slow.
*
* This value can be changed dynamically while the system is running.
* @hide
*/
public static final boolean shouldLogSlowQuery(long elapsedTimeMillis) {
int slowQueryMillis = SystemProperties.getInt("db.log.slow_query_threshold", -1);
return slowQueryMillis >= 0 && elapsedTimeMillis > slowQueryMillis;
}
/** /**
* Contains statistics about the active pagers in the current process. * Contains statistics about the active pagers in the current process.
* *

View File

@@ -18,6 +18,7 @@ package android.database.sqlite;
import android.database.CursorWindow; import android.database.CursorWindow;
import android.os.SystemClock; import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
/** /**
@@ -32,6 +33,7 @@ public class SQLiteQuery extends SQLiteProgram {
private static native int nativeFillWindow(int databasePtr, int statementPtr, int windowPtr, private static native int nativeFillWindow(int databasePtr, int statementPtr, int windowPtr,
int startPos, int offsetParam); int startPos, int offsetParam);
private static native int nativeColumnCount(int statementPtr); private static native int nativeColumnCount(int statementPtr);
private static native String nativeColumnName(int statementPtr, int columnIndex); private static native String nativeColumnName(int statementPtr, int columnIndex);
@@ -80,8 +82,24 @@ public class SQLiteQuery extends SQLiteProgram {
acquireReference(); acquireReference();
try { try {
window.acquireReference(); window.acquireReference();
int startPos = window.getStartPosition();
int numRows = nativeFillWindow(nHandle, nStatement, window.mWindowPtr, int numRows = nativeFillWindow(nHandle, nStatement, window.mWindowPtr,
window.getStartPosition(), mOffsetIndex); startPos, mOffsetIndex);
if (SQLiteDebug.DEBUG_LOG_SLOW_QUERIES) {
long elapsed = SystemClock.uptimeMillis() - timeStart;
if (SQLiteDebug.shouldLogSlowQuery(elapsed)) {
Log.d(TAG, "fillWindow took " + elapsed
+ " ms: window=\"" + window
+ "\", startPos=" + startPos
+ ", offset=" + mOffsetIndex
+ ", filledRows=" + window.getNumRows()
+ ", countedRows=" + numRows
+ ", query=\"" + mSql + "\""
+ ", args=[" + (mBindArgs != null ?
TextUtils.join(", ", mBindArgs.values()) : "")
+ "]");
}
}
mDatabase.logTimeStat(mSql, timeStart); mDatabase.logTimeStat(mSql, timeStart);
return numRows; return numRows;
} catch (IllegalStateException e){ } catch (IllegalStateException e){

View File

@@ -325,6 +325,13 @@ public class Build {
public static final String USER = getString("ro.build.user"); public static final String USER = getString("ro.build.user");
public static final String HOST = getString("ro.build.host"); public static final String HOST = getString("ro.build.host");
/**
* Returns true if we are running a debug build such as "user-debug" or "eng".
* @hide
*/
public static final boolean IS_DEBUGGABLE =
SystemProperties.getInt("ro.debuggable", 0) == 1;
/** /**
* Returns the version string for the radio firmware. May return * Returns the version string for the radio firmware. May return
* null (if, for instance, the radio is not currently on). * null (if, for instance, the radio is not currently on).

View File

@@ -104,6 +104,11 @@ static void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) {
} }
} }
static jstring nativeGetName(JNIEnv* env, jclass clazz, jint windowPtr) {
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
return env->NewStringUTF(window->name().string());
}
static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr, static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr,
jobject parcelObj) { jobject parcelObj) {
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr); CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
@@ -485,6 +490,8 @@ static JNINativeMethod sMethods[] =
(void*)nativeDispose }, (void*)nativeDispose },
{ "nativeWriteToParcel", "(ILandroid/os/Parcel;)V", { "nativeWriteToParcel", "(ILandroid/os/Parcel;)V",
(void*)nativeWriteToParcel }, (void*)nativeWriteToParcel },
{ "nativeGetName", "(I)Ljava/lang/String;",
(void*)nativeGetName },
{ "nativeClear", "(I)V", { "nativeClear", "(I)V",
(void*)nativeClear }, (void*)nativeClear },
{ "nativeGetNumRows", "(I)I", { "nativeGetNumRows", "(I)I",

View File

@@ -211,7 +211,7 @@ uint32_t CursorWindow::alloc(size_t size, bool aligned) {
uint32_t offset = mHeader->freeOffset + padding; uint32_t offset = mHeader->freeOffset + padding;
uint32_t nextFreeOffset = offset + size; uint32_t nextFreeOffset = offset + size;
if (nextFreeOffset > mSize) { if (nextFreeOffset > mSize) {
LOGE("Window is full: requested allocation %d bytes, " LOGW("Window is full: requested allocation %d bytes, "
"free space %d bytes, window size %d bytes", "free space %d bytes, window size %d bytes",
size, freeSpace(), mSize); size, freeSpace(), mSize);
return 0; return 0;