Commit f02ca0ab authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

[IC] Java CachedImageFetcher metrics reporting

Reports metrics occurring in Java to the native CachedImageFetcher
reporting infra.

Bug: 905732
Change-Id: I9f25527fa9459bf1e433f6169de0640b6600248a
Reviewed-on: https://chromium-review.googlesource.com/c/1347510
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarTheresa <twellington@chromium.org>
Reviewed-by: default avatarFilip Gorski <fgorski@chromium.org>
Reviewed-by: default avatarSky Malice <skym@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613390}
parent 181b0c85
...@@ -367,6 +367,7 @@ android_library("chrome_java") { ...@@ -367,6 +367,7 @@ android_library("chrome_java") {
"//components/favicon_base:favicon_base_enums_java", "//components/favicon_base:favicon_base_enums_java",
"//components/dom_distiller/core:distiller_type_java", "//components/dom_distiller/core:distiller_type_java",
"//components/infobars/core:infobar_enums_java", "//components/infobars/core:infobar_enums_java",
"//components/image_fetcher/core:cached_image_fetcher_java_enums_srcjar",
"//components/ntp_snippets:ntp_snippets_java_enums_srcjar", "//components/ntp_snippets:ntp_snippets_java_enums_srcjar",
"//components/ntp_tiles:ntp_tiles_enums_java", "//components/ntp_tiles:ntp_tiles_enums_java",
"//components/offline_pages/core:offline_page_model_enums_java", "//components/offline_pages/core:offline_page_model_enums_java",
......
...@@ -19,6 +19,13 @@ public interface CachedImageFetcher { ...@@ -19,6 +19,13 @@ public interface CachedImageFetcher {
return CachedImageFetcherImpl.getInstance(); return CachedImageFetcherImpl.getInstance();
} }
/**
* Report an event metric.
*
* @param eventId The event to be reported
*/
void reportEvent(@CachedImageFetcherEvent int eventId);
/** /**
* Fetches the image at url with the desired size. Image is null if not * Fetches the image at url with the desired size. Image is null if not
* found or fails decoding. * found or fails decoding.
......
...@@ -56,10 +56,34 @@ class CachedImageFetcherBridge { ...@@ -56,10 +56,34 @@ class CachedImageFetcherBridge {
nativeFetchImage(mNativeCachedImageFetcherBridge, url, width, height, callback); nativeFetchImage(mNativeCachedImageFetcherBridge, url, width, height, callback);
} }
/**
* Report a metrics event.
*
* @param eventId The event to report.
*/
public void reportEvent(@CachedImageFetcherEvent int eventId) {
assert mNativeCachedImageFetcherBridge != 0;
nativeReportEvent(mNativeCachedImageFetcherBridge, eventId);
}
/**
* Report a timing event for a cache hit.
*
* @param startTimeMillis The start time (in milliseconds) of the request, used to measure the
* total duration.
*/
public void reportCacheHitTime(long startTimeMillis) {
assert mNativeCachedImageFetcherBridge != 0;
nativeReportCacheHitTime(mNativeCachedImageFetcherBridge, startTimeMillis);
}
// Native methods // Native methods
private static native long nativeInit(Profile profile); private static native long nativeInit(Profile profile);
private native void nativeDestroy(long nativeCachedImageFetcherBridge); private native void nativeDestroy(long nativeCachedImageFetcherBridge);
private native String nativeGetFilePath(long nativeCachedImageFetcherBridge, String url); private native String nativeGetFilePath(long nativeCachedImageFetcherBridge, String url);
private native void nativeFetchImage(long nativeCachedImageFetcherBridge, String url, private native void nativeFetchImage(long nativeCachedImageFetcherBridge, String url,
int widthPx, int heightPx, Callback<Bitmap> callback); int widthPx, int heightPx, Callback<Bitmap> callback);
private native void nativeReportEvent(long nativeCachedImageFetcherBridge, int eventId);
private native void nativeReportCacheHitTime(
long nativeCachedImageFetcherBridge, long startTimeMillis);
} }
...@@ -21,7 +21,7 @@ import java.io.File; ...@@ -21,7 +21,7 @@ import java.io.File;
public class CachedImageFetcherImpl implements CachedImageFetcher { public class CachedImageFetcherImpl implements CachedImageFetcher {
private static CachedImageFetcherImpl sInstance; private static CachedImageFetcherImpl sInstance;
public static CachedImageFetcher getInstance() { public static CachedImageFetcherImpl getInstance() {
ThreadUtils.assertOnUiThread(); ThreadUtils.assertOnUiThread();
if (sInstance == null) { if (sInstance == null) {
...@@ -53,6 +53,11 @@ public class CachedImageFetcherImpl implements CachedImageFetcher { ...@@ -53,6 +53,11 @@ public class CachedImageFetcherImpl implements CachedImageFetcher {
mCachedImageFetcherBridge = bridge; mCachedImageFetcherBridge = bridge;
} }
@Override
public void reportEvent(@CachedImageFetcherEvent int eventId) {
mCachedImageFetcherBridge.reportEvent(eventId);
}
@Override @Override
public void destroy() { public void destroy() {
// Do nothing, this lives for the lifetime of the application. // Do nothing, this lives for the lifetime of the application.
...@@ -79,6 +84,7 @@ public class CachedImageFetcherImpl implements CachedImageFetcher { ...@@ -79,6 +84,7 @@ public class CachedImageFetcherImpl implements CachedImageFetcher {
*/ */
@VisibleForTesting @VisibleForTesting
void fetchImageImpl(String url, int width, int height, Callback<Bitmap> callback) { void fetchImageImpl(String url, int width, int height, Callback<Bitmap> callback) {
long startTimeMillis = System.currentTimeMillis();
String filePath = mCachedImageFetcherBridge.getFilePath(url); String filePath = mCachedImageFetcherBridge.getFilePath(url);
new AsyncTask<Bitmap>() { new AsyncTask<Bitmap>() {
@Override @Override
...@@ -90,11 +96,12 @@ public class CachedImageFetcherImpl implements CachedImageFetcher { ...@@ -90,11 +96,12 @@ public class CachedImageFetcherImpl implements CachedImageFetcher {
protected void onPostExecute(Bitmap bitmap) { protected void onPostExecute(Bitmap bitmap) {
if (bitmap != null) { if (bitmap != null) {
callback.onResult(bitmap); callback.onResult(bitmap);
return; reportEvent(CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT);
} mCachedImageFetcherBridge.reportCacheHitTime(startTimeMillis);
} else {
mCachedImageFetcherBridge.fetchImage(url, width, height, callback); mCachedImageFetcherBridge.fetchImage(url, width, height, callback);
} }
}
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
} }
......
...@@ -14,12 +14,13 @@ import org.chromium.chrome.browser.BitmapCache; ...@@ -14,12 +14,13 @@ import org.chromium.chrome.browser.BitmapCache;
import org.chromium.chrome.browser.util.ConversionUtils; import org.chromium.chrome.browser.util.ConversionUtils;
/** /**
* A wrapper around the static CachedImageFetcher that also provides in-memory cahcing. * A wrapper around the CachedImageFetcher that also provides in-memory caching.
*/ */
public class InMemoryCachedImageFetcher implements CachedImageFetcher { public class InMemoryCachedImageFetcher implements CachedImageFetcher {
private static final int DEFAULT_CACHE_SIZE = 20 * ConversionUtils.BYTES_PER_MEGABYTE; // 20mb private static final int DEFAULT_CACHE_SIZE = 20 * ConversionUtils.BYTES_PER_MEGABYTE; // 20mb
private static final float PORTION_OF_AVAILABLE_MEMORY = 1.f / 8.f; private static final float PORTION_OF_AVAILABLE_MEMORY = 1.f / 8.f;
// Will do the work if the image isn't cached in memory.
private CachedImageFetcher mCachedImageFetcher; private CachedImageFetcher mCachedImageFetcher;
private BitmapCache mBitmapCache; private BitmapCache mBitmapCache;
...@@ -45,6 +46,11 @@ public class InMemoryCachedImageFetcher implements CachedImageFetcher { ...@@ -45,6 +46,11 @@ public class InMemoryCachedImageFetcher implements CachedImageFetcher {
mCachedImageFetcher = CachedImageFetcher.getInstance(); mCachedImageFetcher = CachedImageFetcher.getInstance();
} }
@Override
public void reportEvent(@CachedImageFetcherEvent int eventId) {
mCachedImageFetcher.reportEvent(eventId);
}
@Override @Override
public void destroy() { public void destroy() {
mCachedImageFetcher.destroy(); mCachedImageFetcher.destroy();
...@@ -69,6 +75,7 @@ public class InMemoryCachedImageFetcher implements CachedImageFetcher { ...@@ -69,6 +75,7 @@ public class InMemoryCachedImageFetcher implements CachedImageFetcher {
callback.onResult(bitmap); callback.onResult(bitmap);
}); });
} else { } else {
reportEvent(CachedImageFetcherEvent.JAVA_IN_MEMORY_CACHE_HIT);
callback.onResult(cachedBitmap); callback.onResult(cachedBitmap);
} }
} }
......
...@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.cached_image_fetcher; ...@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.cached_image_fetcher;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyObject; import static org.mockito.ArgumentMatchers.anyObject;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doAnswer;
...@@ -84,6 +85,11 @@ public class CachedImageFetcherImplTest { ...@@ -84,6 +85,11 @@ public class CachedImageFetcherImplTest {
verify(mCachedImageFetcher).fetchImageImpl(eq(URL), eq(WIDTH_PX), eq(HEIGHT_PX), any()); verify(mCachedImageFetcher).fetchImageImpl(eq(URL), eq(WIDTH_PX), eq(HEIGHT_PX), any());
verify(mCachedImageFetcherBridge, never()) // Should never make it to native. verify(mCachedImageFetcherBridge, never()) // Should never make it to native.
.fetchImage(eq(URL), anyInt(), anyInt(), any()); .fetchImage(eq(URL), anyInt(), anyInt(), any());
// Verify metrics have been reported.
verify(mCachedImageFetcherBridge)
.reportEvent(eq(CachedImageFetcherEvent.JAVA_DISK_CACHE_HIT));
verify(mCachedImageFetcherBridge).reportCacheHitTime(anyLong());
} }
@Test @Test
......
...@@ -117,6 +117,10 @@ public class InMemoryCachedImageFetcherTest { ...@@ -117,6 +117,10 @@ public class InMemoryCachedImageFetcherTest {
verify(mCachedImageFetcherImpl, /* Should only go to native the first time. */ times(1)) verify(mCachedImageFetcherImpl, /* Should only go to native the first time. */ times(1))
.fetchImage(eq(URL), eq(WIDTH_PX), eq(HEIGHT_PX), any()); .fetchImage(eq(URL), eq(WIDTH_PX), eq(HEIGHT_PX), any());
// Verify metrics are reported.
verify(mCachedImageFetcherImpl)
.reportEvent(CachedImageFetcherEvent.JAVA_IN_MEMORY_CACHE_HIT);
} }
@Test @Test
......
...@@ -115,6 +115,23 @@ void CachedImageFetcherBridge::FetchImage(JNIEnv* j_env, ...@@ -115,6 +115,23 @@ void CachedImageFetcherBridge::FetchImage(JNIEnv* j_env,
kTrafficAnnotation); kTrafficAnnotation);
} }
void CachedImageFetcherBridge::ReportEvent(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jint j_event_id) {
CachedImageFetcherEvent event =
static_cast<CachedImageFetcherEvent>(j_event_id);
CachedImageFetcherMetricsReporter::ReportEvent(event);
}
void CachedImageFetcherBridge::ReportCacheHitTime(
JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jlong start_time_millis) {
base::Time start_time = base::Time::FromJavaTime(start_time_millis);
CachedImageFetcherMetricsReporter::ReportImageLoadFromCacheTime(start_time);
}
void CachedImageFetcherBridge::OnImageFetched( void CachedImageFetcherBridge::OnImageFetched(
base::android::ScopedJavaGlobalRef<jobject> callback, base::android::ScopedJavaGlobalRef<jobject> callback,
const std::string& id, const std::string& id,
......
...@@ -41,6 +41,14 @@ class CachedImageFetcherBridge { ...@@ -41,6 +41,14 @@ class CachedImageFetcherBridge {
const jint height_px, const jint height_px,
const base::android::JavaRef<jobject>& j_callback); const base::android::JavaRef<jobject>& j_callback);
void ReportEvent(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jint j_event_id);
void ReportCacheHitTime(JNIEnv* j_env,
const base::android::JavaRef<jobject>& j_this,
const jlong start_time_millis);
private: private:
void OnImageFetched(base::android::ScopedJavaGlobalRef<jobject> callback, void OnImageFetched(base::android::ScopedJavaGlobalRef<jobject> callback,
const std::string& id, const std::string& id,
......
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be # Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file. # found in the LICENSE file.
if (is_android) {
import("//build/config/android/rules.gni")
}
static_library("core") { static_library("core") {
sources = [ sources = [
"cached_image_fetcher.cc", "cached_image_fetcher.cc",
...@@ -75,3 +79,11 @@ source_set("unit_tests") { ...@@ -75,3 +79,11 @@ source_set("unit_tests") {
"//ui/gfx:test_support", "//ui/gfx:test_support",
] ]
} }
if (is_android) {
java_cpp_enum("cached_image_fetcher_java_enums_srcjar") {
sources = [
"cache/cached_image_fetcher_metrics_reporter.h",
]
}
}
...@@ -12,6 +12,8 @@ namespace image_fetcher { ...@@ -12,6 +12,8 @@ namespace image_fetcher {
// Enum for the result of the fetch, reported through UMA. Present in enums.xml // Enum for the result of the fetch, reported through UMA. Present in enums.xml
// as CachedImageFetcherEvent. New values should be added at the end and things // as CachedImageFetcherEvent. New values should be added at the end and things
// should not be renumbered. // should not be renumbered.
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.chrome.browser.cached_image_fetcher)
enum class CachedImageFetcherEvent { enum class CachedImageFetcherEvent {
kImageRequest = 0, kImageRequest = 0,
kCacheHit = 1, kCacheHit = 1,
...@@ -21,7 +23,9 @@ enum class CachedImageFetcherEvent { ...@@ -21,7 +23,9 @@ enum class CachedImageFetcherEvent {
kTotalFailure = 5, kTotalFailure = 5,
kCacheStartupEvictionStarted = 6, kCacheStartupEvictionStarted = 6,
kCacheStartupEvictionFinished = 7, kCacheStartupEvictionFinished = 7,
kMaxValue = kCacheStartupEvictionFinished, kJavaInMemoryCacheHit = 8,
kJavaDiskCacheHit = 9,
kMaxValue = kJavaDiskCacheHit,
}; };
class CachedImageFetcherMetricsReporter { class CachedImageFetcherMetricsReporter {
...@@ -29,10 +33,17 @@ class CachedImageFetcherMetricsReporter { ...@@ -29,10 +33,17 @@ class CachedImageFetcherMetricsReporter {
// Report cache events, used by CachedImageFetcher and composing classes. // Report cache events, used by CachedImageFetcher and composing classes.
static void ReportEvent(CachedImageFetcherEvent event); static void ReportEvent(CachedImageFetcherEvent event);
// Report timing for various Cache events related to CachedImageFetcher. // Report the time it takes to load an image from the cache in native code.
static void ReportImageLoadFromCacheTime(base::Time start_time); static void ReportImageLoadFromCacheTime(base::Time start_time);
// Report the time it takes to load an image from the network.
static void ReportImageLoadFromNetworkTime(base::Time start_time); static void ReportImageLoadFromNetworkTime(base::Time start_time);
// Report the time it takes to load an image from the network after a cache
// hit.
static void ReportImageLoadFromNetworkAfterCacheHit(base::Time start_time); static void ReportImageLoadFromNetworkAfterCacheHit(base::Time start_time);
// Report the time between cache evictions.
static void ReportTimeSinceLastCacheLRUEviction(base::Time start_time); static void ReportTimeSinceLastCacheLRUEviction(base::Time start_time);
}; };
......
...@@ -5484,6 +5484,10 @@ uploading your change for review. These are checked by presubmit scripts. ...@@ -5484,6 +5484,10 @@ uploading your change for review. These are checked by presubmit scripts.
<int value="3" label="Cache decoding error"/> <int value="3" label="Cache decoding error"/>
<int value="4" label="Network transcoding error"/> <int value="4" label="Network transcoding error"/>
<int value="5" label="Failure to fetch the image from the network"/> <int value="5" label="Failure to fetch the image from the network"/>
<int value="6" label="Cache startup eviction began"/>
<int value="7" label="Cache startup eviction finished"/>
<int value="8" label="Java in-memory cache hit"/>
<int value="9" label="Java disk cache hit"/>
</enum> </enum>
<enum name="CacheResult"> <enum name="CacheResult">
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment