• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2009, The Android Open Source Project
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *  * Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  *  * Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #define LOG_TAG "WebCore"
27 
28 #include "config.h"
29 #include "TimeCounter.h"
30 
31 #include "CString.h"
32 #include "Cache.h"
33 #include "KURL.h"
34 #include "Node.h"
35 #include "SystemTime.h"
36 #include "StyleBase.h"
37 
38 #if USE(JSC)
39 #include "JSDOMWindow.h"
40 #include <runtime/JSGlobalObject.h>
41 #include <runtime/JSLock.h>
42 #endif
43 
44 #include <utils/Log.h>
45 
46 using namespace WebCore;
47 using namespace WTF;
48 using namespace JSC;
49 
50 namespace android {
51 
52 #ifdef ANDROID_INSTRUMENT
53 
54 static double sStartTotalTime;
55 static uint32_t sStartThreadTime;
56 static double sLastTotalTime;
57 static uint32_t sLastThreadTime;
58 
59 uint32_t TimeCounter::sStartWebCoreThreadTime;
60 uint32_t TimeCounter::sEndWebCoreThreadTime;
61 bool TimeCounter::sRecordWebCoreTime;
62 uint32_t TimeCounter::sTotalTimeUsed[TimeCounter::TotalTimeCounterCount];
63 uint32_t TimeCounter::sLastTimeUsed[TimeCounter::TotalTimeCounterCount];
64 uint32_t TimeCounter::sCounter[TimeCounter::TotalTimeCounterCount];
65 uint32_t TimeCounter::sLastCounter[TimeCounter::TotalTimeCounterCount];
66 uint32_t TimeCounter::sStartTime[TimeCounter::TotalTimeCounterCount];
67 
68 int QemuTracerAuto::reentry_count = 0;
69 
70 static const char* timeCounterNames[] = {
71     "css parsing",
72     "javascript",
73     "javascript init",
74     "javascript parsing",
75     "javascript execution",
76     "calculate style",
77     "Java callback (frame bridge)",
78     "parsing (may include calcStyle or Java callback)",
79     "layout",
80     "native 1 (frame bridge)",
81     "native 2 (resource load)",
82     "native 3 (shared timer)",
83     "build nav (webview core)",
84     "record content (webview core)",
85     "native 4 (webview core)",
86     "draw content (webview ui)",
87 };
88 
record(enum Type type,const char * functionName)89 void TimeCounter::record(enum Type type, const char* functionName)
90 {
91     recordNoCounter(type, functionName);
92     sCounter[type]++;
93 }
94 
recordNoCounter(enum Type type,const char * functionName)95 void TimeCounter::recordNoCounter(enum Type type, const char* functionName)
96 {
97     uint32_t time = sEndWebCoreThreadTime = get_thread_msec();
98     uint32_t elapsed = time - sStartTime[type];
99     sTotalTimeUsed[type] += elapsed;
100     if (elapsed > 1000)
101         LOGW("***** %s() used %d ms\n", functionName, elapsed);
102 }
103 
report(const KURL & url,int live,int dead,size_t arenaSize)104 void TimeCounter::report(const KURL& url, int live, int dead, size_t arenaSize)
105 {
106     String urlString = url;
107     int totalTime = static_cast<int>((currentTime() - sStartTotalTime) * 1000);
108     int threadTime = get_thread_msec() - sStartThreadTime;
109     LOGD("*-* Total load time: %d ms, thread time: %d ms for %s\n",
110         totalTime, threadTime, urlString.utf8().data());
111     for (Type type = (Type) 0; type < TotalTimeCounterCount; type
112             = (Type) (type + 1)) {
113         char scratch[256];
114         int index = sprintf(scratch, "*-* Total %s time: %d ms",
115             timeCounterNames[type], sTotalTimeUsed[type]);
116         if (sCounter[type] > 0)
117             sprintf(&scratch[index], " called %d times", sCounter[type]);
118         LOGD("%s", scratch);
119     }
120     LOGD("Current cache has %d bytes live and %d bytes dead", live, dead);
121     LOGD("Current render arena takes %d bytes", arenaSize);
122 #if USE(JSC)
123     JSLock lock(false);
124     Heap::Statistics jsHeapStatistics = JSDOMWindow::commonJSGlobalData()->heap.statistics();
125     LOGD("Current JavaScript heap size is %d and has %d bytes free",
126             jsHeapStatistics.size, jsHeapStatistics.free);
127 #endif
128     LOGD("Current CSS styles use %d bytes", StyleBase::reportStyleSize());
129     LOGD("Current DOM nodes use %d bytes", WebCore::Node::reportDOMNodesSize());
130 }
131 
reportNow()132 void TimeCounter::reportNow()
133 {
134     double current = currentTime();
135     uint32_t currentThread = get_thread_msec();
136     int elapsedTime = static_cast<int>((current - sLastTotalTime) * 1000);
137     int elapsedThreadTime = currentThread - sLastThreadTime;
138     LOGD("*-* Elapsed time: %d ms, ui thread time: %d ms, webcore thread time:"
139         " %d ms\n", elapsedTime, elapsedThreadTime, sEndWebCoreThreadTime -
140         sStartWebCoreThreadTime);
141     for (Type type = (Type) 0; type < TotalTimeCounterCount; type
142             = (Type) (type + 1)) {
143         if (sTotalTimeUsed[type] == sLastTimeUsed[type])
144             continue;
145         char scratch[256];
146         int index = sprintf(scratch, "*-* Diff %s time: %d ms",
147             timeCounterNames[type], sTotalTimeUsed[type] - sLastTimeUsed[type]);
148         if (sCounter[type] > sLastCounter[type])
149             sprintf(&scratch[index], " called %d times", sCounter[type]
150                 - sLastCounter[type]);
151         LOGD("%s", scratch);
152     }
153     memcpy(sLastTimeUsed, sTotalTimeUsed, sizeof(sTotalTimeUsed));
154     memcpy(sLastCounter, sCounter, sizeof(sCounter));
155     sLastTotalTime = current;
156     sLastThreadTime = currentThread;
157     sRecordWebCoreTime = true;
158 }
159 
reset()160 void TimeCounter::reset() {
161     bzero(sTotalTimeUsed, sizeof(sTotalTimeUsed));
162     bzero(sCounter, sizeof(sCounter));
163     LOGD("*-* Start browser instrument\n");
164     sStartTotalTime = currentTime();
165     sStartThreadTime = get_thread_msec();
166 }
167 
start(enum Type type)168 void TimeCounter::start(enum Type type)
169 {
170     uint32_t time = get_thread_msec();
171     if (sRecordWebCoreTime) {
172         sStartWebCoreThreadTime = time;
173         sRecordWebCoreTime = false;
174     }
175     sStartTime[type] = time;
176 }
177 
178 #endif
179 
180 }
181