Trace解析

今天在讀關于圖片解析的源碼,看到這樣的代碼:

/**
     * Decode an input stream into a bitmap. If the input stream is null, or
     * cannot be used to decode a bitmap, the function returns null.
     * The stream's position will be where ever it was after the encoded data
     * was read.
     *
     * @param is The input stream that holds the raw data to be decoded into a
     *           bitmap.
     * @param outPadding If not null, return the padding rect for the bitmap if
     *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
     *                   no bitmap is returned (null) then padding is
     *                   unchanged.
     * @param opts null-ok; Options that control downsampling and whether the
     *             image should be completely decoded, or just is size returned.
     * @return The decoded bitmap, or null if the image data could not be
     *         decoded, or, if opts is non-null, if opts requested only the
     *         size be returned (in opts.outWidth and opts.outHeight)
     *
     * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT},
     * if {@link InputStream#markSupported is.markSupported()} returns true,
     * <code>is.mark(1024)</code> would be called. As of
     * {@link android.os.Build.VERSION_CODES#KITKAT}, this is no longer the case.</p>
     */
    public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
        // we don't throw in this case, thus allowing the caller to only check
        // the cache, and not force the image to be decoded.
        if (is == null) {
            return null;
        }

        Bitmap bm = null;

        Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
        try {
            if (is instanceof AssetManager.AssetInputStream) {
                final long asset = ((AssetManager.AssetInputStream) is).getNativeAsset();
                bm = nativeDecodeAsset(asset, outPadding, opts);
            } else {
                bm = decodeStreamInternal(is, outPadding, opts);
            }

            if (bm == null && opts != null && opts.inBitmap != null) {
                throw new IllegalArgumentException("Problem decoding into existing bitmap");
            }

            setDensityFromOptions(bm, opts);
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);
        }

        return bm;
    }

其中有兩句代碼:

 Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
 
 Trace.traceEnd(Trace.TRACE_TAG_GRAPHICS);

很好奇,這個Trace是干嘛的?之前接觸到有一個TraceView!TraceView 是 Android 平臺配備一個很好的性能分析的工具。它可以通過圖形化的方式讓我們了解我們要跟蹤的程序的性能,并且能具體到 method!

跟進源碼瞧個究竟,看到這個代碼的文件注釋:


/**
 * Writes trace events to the system trace buffer.  These trace events can be
 * collected and visualized using the Systrace tool.
 *
 * <p>This tracing mechanism is independent of the method tracing mechanism
 * offered by {@link Debug#startMethodTracing}.  In particular, it enables
 * tracing of events that occur across multiple processes.
 * <p>For information about using the Systrace tool, read <a
 * href="{@docRoot}tools/debugging/systrace.html">Analyzing Display and Performance
 * with Systrace</a>.
 */

翻譯過來就是:

將跟蹤事件寫入系統跟蹤緩沖區。 可以使用Systrace工具收集和可視化這些跟蹤事件。

此跟蹤機制獨立于startMethodTracing()提供的方法跟蹤機制。 特別地,它使得能夠跟蹤跨多個進程發生的事件。

有關使用Systrace工具的信息,請參閱使用Systrace分析顯示和性能。

哈哈,出來一個東西—— Systrace。等我完了研究下這個Systrace.

接下來看著兩個方法:

Trace.traceBegin

    /**
     * Writes a trace message to indicate that a given section of code has
     * begun. Must be followed by a call to {@link #traceEnd} using the same
     * tag.
     *
     * @param traceTag The trace tag.
     * @param methodName The method name to appear in the trace.
     *
     * @hide
     */
    public static void traceBegin(long traceTag, String methodName) {
        if (isTagEnabled(traceTag)) {
            nativeTraceBegin(traceTag, methodName);
        }
    }

寫入跟蹤信息這標志著要追蹤的代碼已經開始運行。必須在后面調用traceEnd,并且使用相同的tag.

參數一:根據的標記tag;
參數二:在追蹤路徑中顯示的方法名。

Trace.traceEnd

 /**
     * Writes a trace message to indicate that the current method has ended.
     * Must be called exactly once for each call to {@link #traceBegin} using the same tag.
     *
     * @param traceTag The trace tag.
     *
     * @hide
     */
    public static void traceEnd(long traceTag) {
        if (isTagEnabled(traceTag)) {
            nativeTraceEnd(traceTag);
        }
    }

寫入追蹤信息標志著當前方法已經結束。必須和traceBegin成對的調用并且使用同一個tag.

參數:追蹤tag和traceBegin傳入的要一致。

至此為止,明白了圖片解析里的這兩句代碼是干嘛的:

/* * Writes trace events to the kernel trace buffer. These trace events can be * collected using the "atrace" program for offline analysis. */

將這些追蹤時間寫入內部追蹤緩存中。這些追蹤事件可以被“atrace”程序收集起來,進行離線分析。

但是,再往里面走的話,發現了這東西竟然也走到了Native層:

private static native void nativeTraceBegin(long tag, String name);
private static native void nativeTraceEnd(long tag);

這兩個方法是在哪兒呢?仔細看看了文件發現了有在各種tag上有兩句注釋:

// These tags must be kept in sync with system/core/include/cutils/trace.h.
// They should also be added to frameworks/native/cmds/atrace/atrace.cpp.

好吧,原來這東西到最后也給C++去做了!

那么問題了,我有什么理由不去好好學下C++,NDK 呢?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容