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