| /* |
| * Copyright 2009, The Android Open Source Project |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #define LOG_TAG "WebCore" |
| |
| #include "config.h" |
| #include "TimeCounter.h" |
| |
| #include "CString.h" |
| #include "Cache.h" |
| #include "KURL.h" |
| #include "Node.h" |
| #include "SystemTime.h" |
| #include "StyleBase.h" |
| |
| #if USE(JSC) |
| #include "JSDOMWindow.h" |
| #include <runtime/JSGlobalObject.h> |
| #include <runtime/JSLock.h> |
| #endif |
| |
| #include <utils/Log.h> |
| |
| using namespace WebCore; |
| using namespace WTF; |
| |
| namespace android { |
| |
| #ifdef ANDROID_INSTRUMENT |
| |
| static double sStartTotalTime; |
| static uint32_t sStartThreadTime; |
| static double sLastTotalTime; |
| static uint32_t sLastThreadTime; |
| |
| uint32_t TimeCounter::sStartWebCoreThreadTime; |
| uint32_t TimeCounter::sEndWebCoreThreadTime; |
| bool TimeCounter::sRecordWebCoreTime; |
| uint32_t TimeCounter::sTotalTimeUsed[TimeCounter::TotalTimeCounterCount]; |
| uint32_t TimeCounter::sLastTimeUsed[TimeCounter::TotalTimeCounterCount]; |
| uint32_t TimeCounter::sCounter[TimeCounter::TotalTimeCounterCount]; |
| uint32_t TimeCounter::sLastCounter[TimeCounter::TotalTimeCounterCount]; |
| uint32_t TimeCounter::sStartTime[TimeCounter::TotalTimeCounterCount]; |
| |
| static const char* timeCounterNames[] = { |
| "css parsing", |
| "javascript", |
| "calculate style", |
| "Java callback (frame bridge)", |
| "parsing (may include calcStyle or Java callback)", |
| "layout", |
| "native 1 (frame bridge)", |
| "native 2 (resource load)", |
| "native 3 (shared timer)", |
| "build nav (webview core)", |
| "record content (webview core)", |
| "native 4 (webview core)", |
| "draw content (webview ui)", |
| }; |
| |
| void TimeCounter::record(enum Type type, const char* functionName) |
| { |
| recordNoCounter(type, functionName); |
| sCounter[type]++; |
| } |
| |
| void TimeCounter::recordNoCounter(enum Type type, const char* functionName) |
| { |
| uint32_t time = sEndWebCoreThreadTime = get_thread_msec(); |
| uint32_t elapsed = time - sStartTime[type]; |
| sTotalTimeUsed[type] += elapsed; |
| if (elapsed > 1000) |
| LOGW("***** %s() used %d ms\n", functionName, elapsed); |
| } |
| |
| void TimeCounter::report(const KURL& url, int live, int dead, size_t arenaSize) |
| { |
| String urlString = url; |
| int totalTime = static_cast<int>((currentTime() - sStartTotalTime) * 1000); |
| int threadTime = get_thread_msec() - sStartThreadTime; |
| LOGD("*-* Total load time: %d ms, thread time: %d ms for %s\n", |
| totalTime, threadTime, urlString.utf8().data()); |
| for (Type type = (Type) 0; type < TotalTimeCounterCount; type |
| = (Type) (type + 1)) { |
| char scratch[256]; |
| int index = sprintf(scratch, "*-* Total %s time: %d ms", |
| timeCounterNames[type], sTotalTimeUsed[type]); |
| if (sCounter[type] > 0) |
| sprintf(&scratch[index], " called %d times", sCounter[type]); |
| LOGD("%s", scratch); |
| } |
| LOGD("Current cache has %d bytes live and %d bytes dead", live, dead); |
| LOGD("Current render arena takes %d bytes", arenaSize); |
| #if USE(JSC) |
| JSLock lock(false); |
| Heap::Statistics jsHeapStatistics = JSDOMWindow::commonJSGlobalData()->heap.statistics(); |
| LOGD("Current JavaScript heap size is %d and has %d bytes free", |
| jsHeapStatistics.size, jsHeapStatistics.free); |
| LOGD("Current JavaScript nodes use %d bytes", JSC::Node::reportJavaScriptNodesSize()); |
| #endif |
| LOGD("Current CSS styles use %d bytes", StyleBase::reportStyleSize()); |
| LOGD("Current DOM nodes use %d bytes", WebCore::Node::reportDOMNodesSize()); |
| } |
| |
| void TimeCounter::reportNow() |
| { |
| double current = currentTime(); |
| uint32_t currentThread = get_thread_msec(); |
| int elapsedTime = static_cast<int>((current - sLastTotalTime) * 1000); |
| int elapsedThreadTime = currentThread - sLastThreadTime; |
| LOGD("*-* Elapsed time: %d ms, ui thread time: %d ms, webcore thread time:" |
| " %d ms\n", elapsedTime, elapsedThreadTime, sEndWebCoreThreadTime - |
| sStartWebCoreThreadTime); |
| for (Type type = (Type) 0; type < TotalTimeCounterCount; type |
| = (Type) (type + 1)) { |
| if (sTotalTimeUsed[type] == sLastTimeUsed[type]) |
| continue; |
| char scratch[256]; |
| int index = sprintf(scratch, "*-* Diff %s time: %d ms", |
| timeCounterNames[type], sTotalTimeUsed[type] - sLastTimeUsed[type]); |
| if (sCounter[type] > sLastCounter[type]) |
| sprintf(&scratch[index], " called %d times", sCounter[type] |
| - sLastCounter[type]); |
| LOGD("%s", scratch); |
| } |
| memcpy(sLastTimeUsed, sTotalTimeUsed, sizeof(sTotalTimeUsed)); |
| memcpy(sLastCounter, sCounter, sizeof(sCounter)); |
| sLastTotalTime = current; |
| sLastThreadTime = currentThread; |
| sRecordWebCoreTime = true; |
| } |
| |
| void TimeCounter::reset() { |
| bzero(sTotalTimeUsed, sizeof(sTotalTimeUsed)); |
| bzero(sCounter, sizeof(sCounter)); |
| LOGD("*-* Start browser instrument\n"); |
| sStartTotalTime = currentTime(); |
| sStartThreadTime = get_thread_msec(); |
| } |
| |
| void TimeCounter::start(enum Type type) |
| { |
| uint32_t time = get_thread_msec(); |
| if (sRecordWebCoreTime) { |
| sStartWebCoreThreadTime = time; |
| sRecordWebCoreTime = false; |
| } |
| sStartTime[type] = time; |
| } |
| |
| #endif |
| |
| } |