Skip to content

Commit 2d280f7

Browse files
Jeff BrownAndroid (Google) Code Review
authored andcommitted
Merge "Improve the slow query instrumentation." into ics-mr0
2 parents 2cc1c5d + 89101cd commit 2d280f7

File tree

7 files changed

+76
-30
lines changed

7 files changed

+76
-30
lines changed

core/java/android/database/CursorWindow.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
5555
public int mWindowPtr;
5656

5757
private int mStartPos;
58+
private final String mName;
5859

5960
private final CloseGuard mCloseGuard = CloseGuard.get();
6061

@@ -85,6 +86,8 @@ private static native void nativeCopyStringToBuffer(int windowPtr, int row, int
8586
private static native boolean nativePutDouble(int windowPtr, double value, int row, int column);
8687
private static native boolean nativePutNull(int windowPtr, int row, int column);
8788

89+
private static native String nativeGetName(int windowPtr);
90+
8891
/**
8992
* Creates a new empty cursor window and gives it a name.
9093
* <p>
@@ -100,6 +103,7 @@ private static native void nativeCopyStringToBuffer(int windowPtr, int row, int
100103
*/
101104
public CursorWindow(String name, boolean localWindow) {
102105
mStartPos = 0;
106+
mName = name;
103107
mWindowPtr = nativeCreate(name, sCursorWindowSize, localWindow);
104108
if (mWindowPtr == 0) {
105109
throw new CursorWindowAllocationException("Cursor window allocation of " +
@@ -130,6 +134,7 @@ private CursorWindow(Parcel source) {
130134
throw new CursorWindowAllocationException("Cursor window could not be "
131135
+ "created from binder.");
132136
}
137+
mName = nativeGetName(mWindowPtr);
133138
mCloseGuard.open("close");
134139
}
135140

@@ -156,6 +161,14 @@ private void dispose() {
156161
}
157162
}
158163

164+
/**
165+
* Gets the name of this cursor window.
166+
* @hide
167+
*/
168+
public String getName() {
169+
return mName;
170+
}
171+
159172
/**
160173
* Closes the cursor window and frees its underlying resources when all other
161174
* remaining references have been released.
@@ -778,4 +791,9 @@ private String printStats() {
778791
String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString();
779792
return "# Open Cursors=" + total + s;
780793
}
794+
795+
@Override
796+
public String toString() {
797+
return getName() + " {" + Integer.toHexString(mWindowPtr) + "}";
798+
}
781799
}

core/java/android/database/sqlite/SQLiteDatabase.java

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -306,10 +306,6 @@ synchronized void setLastSqlStatement(String sql) {
306306
/** Used to find out where this object was created in case it never got closed. */
307307
private final Throwable mStackTrace;
308308

309-
// System property that enables logging of slow queries. Specify the threshold in ms.
310-
private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold";
311-
private final int mSlowQueryThreshold;
312-
313309
/** stores the list of statement ids that need to be finalized by sqlite */
314310
private final ArrayList<Integer> mClosedStatementIds = new ArrayList<Integer>();
315311

@@ -1559,11 +1555,6 @@ public Cursor rawQueryWithFactory(
15591555
String editTable) {
15601556
verifyDbIsOpen();
15611557
BlockGuard.getThreadPolicy().onReadFromDisk();
1562-
long timeStart = 0;
1563-
1564-
if (false || mSlowQueryThreshold != -1) {
1565-
timeStart = System.currentTimeMillis();
1566-
}
15671558

15681559
SQLiteDatabase db = getDbConnection(sql);
15691560
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(db, sql, editTable);
@@ -1574,24 +1565,6 @@ public Cursor rawQueryWithFactory(
15741565
cursorFactory != null ? cursorFactory : mFactory,
15751566
selectionArgs);
15761567
} finally {
1577-
if (false || mSlowQueryThreshold != -1) {
1578-
1579-
// Force query execution
1580-
int count = -1;
1581-
if (cursor != null) {
1582-
count = cursor.getCount();
1583-
}
1584-
1585-
long duration = System.currentTimeMillis() - timeStart;
1586-
1587-
if (false || duration >= mSlowQueryThreshold) {
1588-
Log.v(SQLiteCursor.TAG,
1589-
"query (" + duration + " ms): " + driver.toString() + ", args are "
1590-
+ (selectionArgs != null
1591-
? TextUtils.join(",", selectionArgs)
1592-
: "<null>") + ", count is " + count);
1593-
}
1594-
}
15951568
releaseDbConnection(db);
15961569
}
15971570
return cursor;
@@ -1967,7 +1940,6 @@ private SQLiteDatabase(String path, CursorFactory factory, int flags,
19671940
setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE);
19681941
mFlags = flags;
19691942
mPath = path;
1970-
mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
19711943
mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
19721944
mFactory = factory;
19731945
mPrograms = new WeakHashMap<SQLiteClosable,Object>();

core/java/android/database/sqlite/SQLiteDebug.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.util.ArrayList;
2020

21+
import android.os.Build;
22+
import android.os.SystemProperties;
2123
import android.util.Log;
2224

2325
/**
@@ -64,6 +66,28 @@ public final class SQLiteDebug {
6466
public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE =
6567
Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE);
6668

69+
/**
70+
* True to enable database performance testing instrumentation.
71+
* @hide
72+
*/
73+
public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
74+
75+
/**
76+
* Determines whether a query should be logged.
77+
*
78+
* Reads the "db.log.slow_query_threshold" system property, which can be changed
79+
* by the user at any time. If the value is zero, then all queries will
80+
* be considered slow. If the value does not exist, then no queries will
81+
* be considered slow.
82+
*
83+
* This value can be changed dynamically while the system is running.
84+
* @hide
85+
*/
86+
public static final boolean shouldLogSlowQuery(long elapsedTimeMillis) {
87+
int slowQueryMillis = SystemProperties.getInt("db.log.slow_query_threshold", -1);
88+
return slowQueryMillis >= 0 && elapsedTimeMillis > slowQueryMillis;
89+
}
90+
6791
/**
6892
* Contains statistics about the active pagers in the current process.
6993
*

core/java/android/database/sqlite/SQLiteQuery.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import android.database.CursorWindow;
2020
import android.os.SystemClock;
21+
import android.text.TextUtils;
2122
import android.util.Log;
2223

2324
/**
@@ -32,6 +33,7 @@ public class SQLiteQuery extends SQLiteProgram {
3233

3334
private static native int nativeFillWindow(int databasePtr, int statementPtr, int windowPtr,
3435
int startPos, int offsetParam);
36+
3537
private static native int nativeColumnCount(int statementPtr);
3638
private static native String nativeColumnName(int statementPtr, int columnIndex);
3739

@@ -80,8 +82,24 @@ private static native int nativeFillWindow(int databasePtr, int statementPtr, in
8082
acquireReference();
8183
try {
8284
window.acquireReference();
85+
int startPos = window.getStartPosition();
8386
int numRows = nativeFillWindow(nHandle, nStatement, window.mWindowPtr,
84-
window.getStartPosition(), mOffsetIndex);
87+
startPos, mOffsetIndex);
88+
if (SQLiteDebug.DEBUG_LOG_SLOW_QUERIES) {
89+
long elapsed = SystemClock.uptimeMillis() - timeStart;
90+
if (SQLiteDebug.shouldLogSlowQuery(elapsed)) {
91+
Log.d(TAG, "fillWindow took " + elapsed
92+
+ " ms: window=\"" + window
93+
+ "\", startPos=" + startPos
94+
+ ", offset=" + mOffsetIndex
95+
+ ", filledRows=" + window.getNumRows()
96+
+ ", countedRows=" + numRows
97+
+ ", query=\"" + mSql + "\""
98+
+ ", args=[" + (mBindArgs != null ?
99+
TextUtils.join(", ", mBindArgs.values()) : "")
100+
+ "]");
101+
}
102+
}
85103
mDatabase.logTimeStat(mSql, timeStart);
86104
return numRows;
87105
} catch (IllegalStateException e){

core/java/android/os/Build.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,13 @@ public static class VERSION_CODES {
325325
public static final String USER = getString("ro.build.user");
326326
public static final String HOST = getString("ro.build.host");
327327

328+
/**
329+
* Returns true if we are running a debug build such as "user-debug" or "eng".
330+
* @hide
331+
*/
332+
public static final boolean IS_DEBUGGABLE =
333+
SystemProperties.getInt("ro.debuggable", 0) == 1;
334+
328335
/**
329336
* Returns the version string for the radio firmware. May return
330337
* null (if, for instance, the radio is not currently on).

core/jni/android_database_CursorWindow.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ static void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) {
104104
}
105105
}
106106

107+
static jstring nativeGetName(JNIEnv* env, jclass clazz, jint windowPtr) {
108+
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
109+
return env->NewStringUTF(window->name().string());
110+
}
111+
107112
static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr,
108113
jobject parcelObj) {
109114
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
@@ -485,6 +490,8 @@ static JNINativeMethod sMethods[] =
485490
(void*)nativeDispose },
486491
{ "nativeWriteToParcel", "(ILandroid/os/Parcel;)V",
487492
(void*)nativeWriteToParcel },
493+
{ "nativeGetName", "(I)Ljava/lang/String;",
494+
(void*)nativeGetName },
488495
{ "nativeClear", "(I)V",
489496
(void*)nativeClear },
490497
{ "nativeGetNumRows", "(I)I",

libs/binder/CursorWindow.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ uint32_t CursorWindow::alloc(size_t size, bool aligned) {
211211
uint32_t offset = mHeader->freeOffset + padding;
212212
uint32_t nextFreeOffset = offset + size;
213213
if (nextFreeOffset > mSize) {
214-
LOGE("Window is full: requested allocation %d bytes, "
214+
LOGW("Window is full: requested allocation %d bytes, "
215215
"free space %d bytes, window size %d bytes",
216216
size, freeSpace(), mSize);
217217
return 0;

0 commit comments

Comments
 (0)