ProfileNode.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * Copyright (C) 2008 Apple Inc. All rights reserved.
  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. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #include "ProfileNode.h"
  30. #include "LegacyProfiler.h"
  31. #include <stdio.h>
  32. #include <wtf/DateMath.h>
  33. #include <wtf/DataLog.h>
  34. #include <wtf/text/StringHash.h>
  35. #if OS(WINDOWS)
  36. #include <windows.h>
  37. #endif
  38. using namespace WTF;
  39. namespace JSC {
  40. static double getCount()
  41. {
  42. #if OS(WINDOWS)
  43. static LARGE_INTEGER frequency;
  44. if (!frequency.QuadPart)
  45. QueryPerformanceFrequency(&frequency);
  46. LARGE_INTEGER counter;
  47. QueryPerformanceCounter(&counter);
  48. return static_cast<double>(counter.QuadPart) / frequency.QuadPart;
  49. #else
  50. return currentTimeMS();
  51. #endif
  52. }
  53. ProfileNode::ProfileNode(ExecState* callerCallFrame, const CallIdentifier& callIdentifier, ProfileNode* headNode, ProfileNode* parentNode)
  54. : m_callerCallFrame(callerCallFrame)
  55. , m_callIdentifier(callIdentifier)
  56. , m_head(headNode)
  57. , m_parent(parentNode)
  58. , m_nextSibling(0)
  59. , m_startTime(0.0)
  60. , m_actualTotalTime(0.0)
  61. , m_visibleTotalTime(0.0)
  62. , m_actualSelfTime(0.0)
  63. , m_visibleSelfTime(0.0)
  64. , m_numberOfCalls(0)
  65. , m_visible(true)
  66. {
  67. startTimer();
  68. }
  69. ProfileNode::ProfileNode(ExecState* callerCallFrame, ProfileNode* headNode, ProfileNode* nodeToCopy)
  70. : m_callerCallFrame(callerCallFrame)
  71. , m_callIdentifier(nodeToCopy->callIdentifier())
  72. , m_head(headNode)
  73. , m_parent(nodeToCopy->parent())
  74. , m_nextSibling(0)
  75. , m_startTime(0.0)
  76. , m_actualTotalTime(nodeToCopy->actualTotalTime())
  77. , m_visibleTotalTime(nodeToCopy->totalTime())
  78. , m_actualSelfTime(nodeToCopy->actualSelfTime())
  79. , m_visibleSelfTime(nodeToCopy->selfTime())
  80. , m_numberOfCalls(nodeToCopy->numberOfCalls())
  81. , m_visible(nodeToCopy->visible())
  82. {
  83. }
  84. ProfileNode* ProfileNode::willExecute(ExecState* callerCallFrame, const CallIdentifier& callIdentifier)
  85. {
  86. for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild) {
  87. if ((*currentChild)->callIdentifier() == callIdentifier) {
  88. (*currentChild)->startTimer();
  89. return (*currentChild).get();
  90. }
  91. }
  92. RefPtr<ProfileNode> newChild = ProfileNode::create(callerCallFrame, callIdentifier, m_head ? m_head : this, this); // If this ProfileNode has no head it is the head.
  93. if (m_children.size())
  94. m_children.last()->setNextSibling(newChild.get());
  95. m_children.append(newChild.release());
  96. return m_children.last().get();
  97. }
  98. ProfileNode* ProfileNode::didExecute()
  99. {
  100. endAndRecordCall();
  101. return m_parent;
  102. }
  103. void ProfileNode::addChild(PassRefPtr<ProfileNode> prpChild)
  104. {
  105. RefPtr<ProfileNode> child = prpChild;
  106. child->setParent(this);
  107. if (m_children.size())
  108. m_children.last()->setNextSibling(child.get());
  109. m_children.append(child.release());
  110. }
  111. ProfileNode* ProfileNode::findChild(ProfileNode* node) const
  112. {
  113. if (!node)
  114. return 0;
  115. for (size_t i = 0; i < m_children.size(); ++i) {
  116. if (*node == m_children[i].get())
  117. return m_children[i].get();
  118. }
  119. return 0;
  120. }
  121. void ProfileNode::removeChild(ProfileNode* node)
  122. {
  123. if (!node)
  124. return;
  125. for (size_t i = 0; i < m_children.size(); ++i) {
  126. if (*node == m_children[i].get()) {
  127. m_children.remove(i);
  128. break;
  129. }
  130. }
  131. resetChildrensSiblings();
  132. }
  133. void ProfileNode::insertNode(PassRefPtr<ProfileNode> prpNode)
  134. {
  135. RefPtr<ProfileNode> node = prpNode;
  136. for (unsigned i = 0; i < m_children.size(); ++i)
  137. node->addChild(m_children[i].release());
  138. m_children.clear();
  139. m_children.append(node.release());
  140. }
  141. void ProfileNode::stopProfiling()
  142. {
  143. if (m_startTime)
  144. endAndRecordCall();
  145. m_visibleTotalTime = m_actualTotalTime;
  146. ASSERT(m_actualSelfTime == 0.0 && m_startTime == 0.0);
  147. // Because we iterate in post order all of our children have been stopped before us.
  148. for (unsigned i = 0; i < m_children.size(); ++i)
  149. m_actualSelfTime += m_children[i]->totalTime();
  150. ASSERT(m_actualSelfTime <= m_actualTotalTime);
  151. m_actualSelfTime = m_actualTotalTime - m_actualSelfTime;
  152. m_visibleSelfTime = m_actualSelfTime;
  153. }
  154. ProfileNode* ProfileNode::traverseNextNodePostOrder() const
  155. {
  156. ProfileNode* next = m_nextSibling;
  157. if (!next)
  158. return m_parent;
  159. while (ProfileNode* firstChild = next->firstChild())
  160. next = firstChild;
  161. return next;
  162. }
  163. ProfileNode* ProfileNode::traverseNextNodePreOrder(bool processChildren) const
  164. {
  165. if (processChildren && m_children.size())
  166. return m_children[0].get();
  167. if (m_nextSibling)
  168. return m_nextSibling;
  169. ProfileNode* nextParent = m_parent;
  170. if (!nextParent)
  171. return 0;
  172. ProfileNode* next;
  173. for (next = m_parent->nextSibling(); !next; next = nextParent->nextSibling()) {
  174. nextParent = nextParent->parent();
  175. if (!nextParent)
  176. return 0;
  177. }
  178. return next;
  179. }
  180. void ProfileNode::setTreeVisible(ProfileNode* node, bool visible)
  181. {
  182. ProfileNode* nodeParent = node->parent();
  183. ProfileNode* nodeSibling = node->nextSibling();
  184. node->setParent(0);
  185. node->setNextSibling(0);
  186. for (ProfileNode* currentNode = node; currentNode; currentNode = currentNode->traverseNextNodePreOrder())
  187. currentNode->setVisible(visible);
  188. node->setParent(nodeParent);
  189. node->setNextSibling(nodeSibling);
  190. }
  191. void ProfileNode::calculateVisibleTotalTime()
  192. {
  193. double sumOfVisibleChildrensTime = 0.0;
  194. for (unsigned i = 0; i < m_children.size(); ++i) {
  195. if (m_children[i]->visible())
  196. sumOfVisibleChildrensTime += m_children[i]->totalTime();
  197. }
  198. m_visibleTotalTime = m_visibleSelfTime + sumOfVisibleChildrensTime;
  199. }
  200. bool ProfileNode::focus(const CallIdentifier& callIdentifier)
  201. {
  202. if (!m_visible)
  203. return false;
  204. if (m_callIdentifier != callIdentifier) {
  205. m_visible = false;
  206. return true;
  207. }
  208. for (ProfileNode* currentParent = m_parent; currentParent; currentParent = currentParent->parent())
  209. currentParent->setVisible(true);
  210. return false;
  211. }
  212. void ProfileNode::exclude(const CallIdentifier& callIdentifier)
  213. {
  214. if (m_visible && m_callIdentifier == callIdentifier) {
  215. setTreeVisible(this, false);
  216. m_parent->setVisibleSelfTime(m_parent->selfTime() + m_visibleTotalTime);
  217. }
  218. }
  219. void ProfileNode::restore()
  220. {
  221. m_visibleTotalTime = m_actualTotalTime;
  222. m_visibleSelfTime = m_actualSelfTime;
  223. m_visible = true;
  224. }
  225. void ProfileNode::endAndRecordCall()
  226. {
  227. m_actualTotalTime += m_startTime ? getCount() - m_startTime : 0.0;
  228. m_startTime = 0.0;
  229. ++m_numberOfCalls;
  230. }
  231. void ProfileNode::startTimer()
  232. {
  233. if (!m_startTime)
  234. m_startTime = getCount();
  235. }
  236. void ProfileNode::resetChildrensSiblings()
  237. {
  238. unsigned size = m_children.size();
  239. for (unsigned i = 0; i < size; ++i)
  240. m_children[i]->setNextSibling(i + 1 == size ? 0 : m_children[i + 1].get());
  241. }
  242. #ifndef NDEBUG
  243. void ProfileNode::debugPrintData(int indentLevel) const
  244. {
  245. // Print function names
  246. for (int i = 0; i < indentLevel; ++i)
  247. dataLogF(" ");
  248. dataLogF("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n",
  249. functionName().utf8().data(),
  250. m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(),
  251. m_visibleSelfTime, m_visibleTotalTime,
  252. (m_visible ? "True" : "False"),
  253. m_nextSibling ? m_nextSibling->functionName().utf8().data() : "");
  254. ++indentLevel;
  255. // Print children's names and information
  256. for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
  257. (*currentChild)->debugPrintData(indentLevel);
  258. }
  259. // print the profiled data in a format that matches the tool sample's output.
  260. double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashCount& countedFunctions) const
  261. {
  262. dataLogF(" ");
  263. // Print function names
  264. const char* name = functionName().utf8().data();
  265. double sampleCount = m_actualTotalTime * 1000;
  266. if (indentLevel) {
  267. for (int i = 0; i < indentLevel; ++i)
  268. dataLogF(" ");
  269. countedFunctions.add(functionName().impl());
  270. dataLogF("%.0f %s\n", sampleCount ? sampleCount : 1, name);
  271. } else
  272. dataLogF("%s\n", name);
  273. ++indentLevel;
  274. // Print children's names and information
  275. double sumOfChildrensCount = 0.0;
  276. for (StackIterator currentChild = m_children.begin(); currentChild != m_children.end(); ++currentChild)
  277. sumOfChildrensCount += (*currentChild)->debugPrintDataSampleStyle(indentLevel, countedFunctions);
  278. sumOfChildrensCount *= 1000; //
  279. // Print remainder of samples to match sample's output
  280. if (sumOfChildrensCount < sampleCount) {
  281. dataLogF(" ");
  282. while (indentLevel--)
  283. dataLogF(" ");
  284. dataLogF("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().utf8().data());
  285. }
  286. return m_actualTotalTime;
  287. }
  288. #endif
  289. } // namespace JSC