Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (244203 => 244204)
--- trunk/Source/_javascript_Core/ChangeLog 2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-04-12 00:53:12 UTC (rev 244204)
@@ -1,3 +1,28 @@
+2019-04-11 Michael Saboff <msab...@apple.com>
+
+ Improve the Inline Cache Stats code
+ https://bugs.webkit.org/show_bug.cgi?id=196836
+
+ Reviewed by Saam Barati.
+
+ Needed to handle the case where the Identifier could be null, for example with InstanceOfAddAccessCase
+ and InstanceOfReplaceWithJump.
+
+ Added the ability to log the location of a GetBy and PutBy property as either on self or up the
+ protocol chain.
+
+ * jit/ICStats.cpp:
+ (JSC::ICEvent::operator< const):
+ (JSC::ICEvent::dump const):
+ * jit/ICStats.h:
+ (JSC::ICEvent::ICEvent):
+ (JSC::ICEvent::hash const):
+ * jit/JITOperations.cpp:
+ * jit/Repatch.cpp:
+ (JSC::tryCacheGetByID):
+ (JSC::tryCachePutByID):
+ (JSC::tryCacheInByID):
+
2019-04-11 Devin Rousso <drou...@apple.com>
Web Inspector: Timelines: can't reliably stop/start a recording
Modified: trunk/Source/_javascript_Core/jit/ICStats.cpp (244203 => 244204)
--- trunk/Source/_javascript_Core/jit/ICStats.cpp 2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/ICStats.cpp 2019-04-12 00:53:12 UTC (rev 244204)
@@ -40,13 +40,18 @@
if (m_propertyName != other.m_propertyName)
return codePointCompare(m_propertyName.string(), other.m_propertyName.string()) < 0;
-
- return m_kind < other.m_kind;
+
+ if (m_kind != other.m_kind)
+ return m_kind < other.m_kind;
+
+ return m_propertyLocation < other.m_propertyLocation;
}
void ICEvent::dump(PrintStream& out) const
{
out.print(m_kind, "(", m_classInfo ? m_classInfo->className : "<null>", ", ", m_propertyName, ")");
+ if (m_propertyLocation != Unknown)
+ out.print(m_propertyLocation == BaseObject ? " self" : " proto lookup");
}
void ICEvent::log() const
Modified: trunk/Source/_javascript_Core/jit/ICStats.h (244203 => 244204)
--- trunk/Source/_javascript_Core/jit/ICStats.h 2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/ICStats.h 2019-04-12 00:53:12 UTC (rev 244204)
@@ -78,7 +78,13 @@
FOR_EACH_ICEVENT_KIND(ICEVENT_KIND_DECLARATION)
#undef ICEVENT_KIND_DECLARATION
};
-
+
+ enum PropertyLocation {
+ Unknown,
+ BaseObject,
+ ProtoLookup
+ };
+
ICEvent()
{
}
@@ -87,9 +93,18 @@
: m_kind(kind)
, m_classInfo(classInfo)
, m_propertyName(propertyName)
+ , m_propertyLocation(Unknown)
{
}
+ ICEvent(Kind kind, const ClassInfo* classInfo, const Identifier propertyName, bool isBaseProperty)
+ : m_kind(kind)
+ , m_classInfo(classInfo)
+ , m_propertyName(propertyName)
+ , m_propertyLocation(isBaseProperty ? BaseObject : ProtoLookup)
+ {
+ }
+
ICEvent(WTF::HashTableDeletedValueType)
: m_kind(OperationGetById)
{
@@ -123,7 +138,9 @@
unsigned hash() const
{
- return m_kind + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
+ if (m_propertyName.isNull())
+ return m_kind + m_propertyLocation + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo);
+ return m_kind + m_propertyLocation + WTF::PtrHash<const ClassInfo*>::hash(m_classInfo) + StringHash::hash(m_propertyName.string());
}
bool isHashTableDeletedValue() const
@@ -140,6 +157,7 @@
Kind m_kind { InvalidKind };
const ClassInfo* m_classInfo { nullptr };
Identifier m_propertyName;
+ PropertyLocation m_propertyLocation;
};
struct ICEventHash {
Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (244203 => 244204)
--- trunk/Source/_javascript_Core/jit/JITOperations.cpp 2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp 2019-04-12 00:53:12 UTC (rev 244204)
@@ -252,9 +252,11 @@
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
Identifier ident = Identifier::fromUid(vm, uid);
-
- LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(*vm), ident));
- return JSValue::encode(baseValue.get(exec, ident, slot));
+ JSValue result = baseValue.get(exec, ident, slot);
+
+ LOG_IC((ICEvent::OperationGetById, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+
+ return JSValue::encode(result);
}
EncodedJSValue JIT_OPERATION operationGetByIdGeneric(ExecState* exec, EncodedJSValue base, UniquedStringImpl* uid)
@@ -267,8 +269,11 @@
JSValue baseValue = JSValue::decode(base);
PropertySlot slot(baseValue, PropertySlot::InternalMethodType::Get);
Identifier ident = Identifier::fromUid(vm, uid);
- LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(*vm), ident));
- return JSValue::encode(baseValue.get(exec, ident, slot));
+ JSValue result = baseValue.get(exec, ident, slot);
+
+ LOG_IC((ICEvent::OperationGetByIdGeneric, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+
+ return JSValue::encode(result);
}
EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue base, UniquedStringImpl* uid)
@@ -280,9 +285,11 @@
Identifier ident = Identifier::fromUid(vm, uid);
JSValue baseValue = JSValue::decode(base);
- LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(*vm), ident));
return JSValue::encode(baseValue.getPropertySlot(exec, ident, [&] (bool found, PropertySlot& slot) -> JSValue {
+
+ LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+
if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
return found ? slot.getValue(exec, ident) : jsUndefined();
@@ -331,10 +338,11 @@
JSValue baseValue = JSValue::decode(base);
JSValue thisValue = JSValue::decode(thisEncoded);
- LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(*vm), ident));
PropertySlot slot(thisValue, PropertySlot::InternalMethodType::Get);
return JSValue::encode(baseValue.getPropertySlot(exec, ident, slot, [&] (bool found, PropertySlot& slot) -> JSValue {
+ LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
+
if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::WithThis);
return found ? slot.getValue(exec, ident) : jsUndefined();
@@ -439,10 +447,10 @@
JSValue baseValue = JSValue::decode(encodedBase);
Identifier ident = Identifier::fromUid(vm, uid);
- LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(*vm), ident));
-
PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
+
+ LOG_IC((ICEvent::OperationPutByIdStrict, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
}
void JIT_OPERATION operationPutByIdNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -456,9 +464,10 @@
JSValue baseValue = JSValue::decode(encodedBase);
Identifier ident = Identifier::fromUid(vm, uid);
- LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(*vm), ident));
PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
baseValue.putInline(exec, ident, JSValue::decode(encodedValue), slot);
+
+ LOG_IC((ICEvent::OperationPutByIdNonStrict, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
}
void JIT_OPERATION operationPutByIdDirectStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -472,9 +481,10 @@
JSValue baseValue = JSValue::decode(encodedBase);
Identifier ident = Identifier::fromUid(&vm, uid);
- LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(vm), ident));
PutPropertySlot slot(baseValue, true, exec->codeBlock()->putByIdContext());
CommonSlowPaths::putDirectWithReify(vm, exec, asObject(baseValue), ident, JSValue::decode(encodedValue), slot);
+
+ LOG_IC((ICEvent::OperationPutByIdDirectStrict, baseValue.classInfoOrNull(vm), ident, slot.base() == baseValue));
}
void JIT_OPERATION operationPutByIdDirectNonStrict(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -488,9 +498,10 @@
JSValue baseValue = JSValue::decode(encodedBase);
Identifier ident = Identifier::fromUid(&vm, uid);
- LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(vm), ident));
PutPropertySlot slot(baseValue, false, exec->codeBlock()->putByIdContext());
CommonSlowPaths::putDirectWithReify(vm, exec, asObject(baseValue), ident, JSValue::decode(encodedValue), slot);
+
+ LOG_IC((ICEvent::OperationPutByIdDirectNonStrict, baseValue.classInfoOrNull(vm), ident, slot.base() == baseValue));
}
void JIT_OPERATION operationPutByIdStrictOptimize(ExecState* exec, StructureStubInfo* stubInfo, EncodedJSValue encodedValue, EncodedJSValue encodedBase, UniquedStringImpl* uid)
@@ -506,12 +517,14 @@
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
- LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(*vm), ident));
CodeBlock* codeBlock = exec->codeBlock();
PutPropertySlot slot(baseValue, true, codeBlock->putByIdContext());
Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
baseValue.putInline(exec, ident, value, slot);
+
+ LOG_IC((ICEvent::OperationPutByIdStrictOptimize, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
+
RETURN_IF_EXCEPTION(scope, void());
if (accessType != static_cast<AccessType>(stubInfo->accessType))
@@ -534,12 +547,14 @@
JSValue value = JSValue::decode(encodedValue);
JSValue baseValue = JSValue::decode(encodedBase);
- LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(*vm), ident));
CodeBlock* codeBlock = exec->codeBlock();
PutPropertySlot slot(baseValue, false, codeBlock->putByIdContext());
Structure* structure = baseValue.isCell() ? baseValue.asCell()->structure(*vm) : nullptr;
baseValue.putInline(exec, ident, value, slot);
+
+ LOG_IC((ICEvent::OperationPutByIdNonStrictOptimize, baseValue.classInfoOrNull(*vm), ident, slot.base() == baseValue));
+
RETURN_IF_EXCEPTION(scope, void());
if (accessType != static_cast<AccessType>(stubInfo->accessType))
@@ -562,11 +577,13 @@
JSValue value = JSValue::decode(encodedValue);
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
- LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(vm), ident));
CodeBlock* codeBlock = exec->codeBlock();
PutPropertySlot slot(baseObject, true, codeBlock->putByIdContext());
Structure* structure = nullptr;
CommonSlowPaths::putDirectWithReify(vm, exec, baseObject, ident, value, slot, &structure);
+
+ LOG_IC((ICEvent::OperationPutByIdDirectStrictOptimize, baseObject->classInfo(vm), ident, slot.base() == baseObject));
+
RETURN_IF_EXCEPTION(scope, void());
if (accessType != static_cast<AccessType>(stubInfo->accessType))
@@ -589,11 +606,13 @@
JSValue value = JSValue::decode(encodedValue);
JSObject* baseObject = asObject(JSValue::decode(encodedBase));
- LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(vm), ident));
CodeBlock* codeBlock = exec->codeBlock();
PutPropertySlot slot(baseObject, false, codeBlock->putByIdContext());
Structure* structure = nullptr;
CommonSlowPaths::putDirectWithReify(vm, exec, baseObject, ident, value, slot, &structure);
+
+ LOG_IC((ICEvent::OperationPutByIdDirectNonStrictOptimize, baseObject->classInfo(vm), ident, slot.base() == baseObject));
+
RETURN_IF_EXCEPTION(scope, void());
if (accessType != static_cast<AccessType>(stubInfo->accessType))
Modified: trunk/Source/_javascript_Core/jit/Repatch.cpp (244203 => 244204)
--- trunk/Source/_javascript_Core/jit/Repatch.cpp 2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Source/_javascript_Core/jit/Repatch.cpp 2019-04-12 00:53:12 UTC (rev 244204)
@@ -267,7 +267,7 @@
bool generatedCodeInline = InlineAccess::generateSelfPropertyAccess(stubInfo, structure, slot.cachedOffset());
if (generatedCodeInline) {
- LOG_IC((ICEvent::GetByIdSelfPatch, structure->classInfo(), propertyName));
+ LOG_IC((ICEvent::GetByIdSelfPatch, structure->classInfo(), propertyName, slot.slotBase() == baseValue));
structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingGetByIdFunction(kind));
stubInfo.initGetByIdSelf(codeBlock, structure, slot.cachedOffset());
@@ -376,12 +376,12 @@
}
}
- LOG_IC((ICEvent::GetByIdAddAccessCase, baseValue.classInfoOrNull(vm), propertyName));
+ LOG_IC((ICEvent::GetByIdAddAccessCase, baseValue.classInfoOrNull(vm), propertyName, slot.slotBase() == baseValue));
result = stubInfo.addAccessCase(locker, codeBlock, propertyName, WTFMove(newCase));
if (result.generatedSomeCode()) {
- LOG_IC((ICEvent::GetByIdReplaceWithJump, baseValue.classInfoOrNull(vm), propertyName));
+ LOG_IC((ICEvent::GetByIdReplaceWithJump, baseValue.classInfoOrNull(vm), propertyName, slot.slotBase() == baseValue));
RELEASE_ASSERT(result.code());
InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
@@ -475,7 +475,7 @@
bool generatedCodeInline = InlineAccess::generateSelfPropertyReplace(stubInfo, structure, slot.cachedOffset());
if (generatedCodeInline) {
- LOG_IC((ICEvent::PutByIdSelfPatch, structure->classInfo(), ident));
+ LOG_IC((ICEvent::PutByIdSelfPatch, structure->classInfo(), ident, slot.base() == baseValue));
ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), appropriateOptimizingPutByIdFunction(slot, putKind));
stubInfo.initPutByIdReplace(codeBlock, structure, slot.cachedOffset());
return RetryCacheLater;
@@ -588,12 +588,12 @@
}
}
- LOG_IC((ICEvent::PutByIdAddAccessCase, structure->classInfo(), ident));
+ LOG_IC((ICEvent::PutByIdAddAccessCase, structure->classInfo(), ident, slot.base() == baseValue));
result = stubInfo.addAccessCase(locker, codeBlock, ident, WTFMove(newCase));
if (result.generatedSomeCode()) {
- LOG_IC((ICEvent::PutByIdReplaceWithJump, structure->classInfo(), ident));
+ LOG_IC((ICEvent::PutByIdReplaceWithJump, structure->classInfo(), ident, slot.base() == baseValue));
RELEASE_ASSERT(result.code());
@@ -654,7 +654,7 @@
&& !structure->needImpurePropertyWatchpoint()) {
bool generatedCodeInline = InlineAccess::generateSelfInAccess(stubInfo, structure);
if (generatedCodeInline) {
- LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident));
+ LOG_IC((ICEvent::InByIdSelfPatch, structure->classInfo(), ident, slot.slotBase() == base));
structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
ftlThunkAwareRepatchCall(codeBlock, stubInfo.slowPathCallLocation(), operationInByIdOptimize);
stubInfo.initInByIdSelf(codeBlock, structure, slot.cachedOffset());
@@ -692,7 +692,7 @@
if (!conditionSet.isValid())
return GiveUpOnCache;
- LOG_IC((ICEvent::InAddAccessCase, structure->classInfo(), ident));
+ LOG_IC((ICEvent::InAddAccessCase, structure->classInfo(), ident, slot.slotBase() == base));
std::unique_ptr<AccessCase> newCase = AccessCase::create(
vm, codeBlock, wasFound ? AccessCase::InHit : AccessCase::InMiss, wasFound ? slot.cachedOffset() : invalidOffset, structure, conditionSet, WTFMove(prototypeAccessChain));
@@ -700,7 +700,7 @@
result = stubInfo.addAccessCase(locker, codeBlock, ident, WTFMove(newCase));
if (result.generatedSomeCode()) {
- LOG_IC((ICEvent::InReplaceWithJump, structure->classInfo(), ident));
+ LOG_IC((ICEvent::InReplaceWithJump, structure->classInfo(), ident, slot.slotBase() == base));
RELEASE_ASSERT(result.code());
InlineAccess::rewireStubAsJump(stubInfo, CodeLocationLabel<JITStubRoutinePtrTag>(result.code()));
Modified: trunk/Tools/ChangeLog (244203 => 244204)
--- trunk/Tools/ChangeLog 2019-04-11 23:43:10 UTC (rev 244203)
+++ trunk/Tools/ChangeLog 2019-04-12 00:53:12 UTC (rev 244204)
@@ -1,3 +1,24 @@
+2019-04-11 Michael Saboff <msab...@apple.com>
+
+ Improve the Inline Cache Stats code
+ https://bugs.webkit.org/show_bug.cgi?id=196836
+
+ Reviewed by Saam Barati.
+
+ Added a new script to consolidate and arrange the output of --useICStats option.
+
+ This script merges the output from every group into one large table and sorts it from most common to
+ least common. It also counts the slow path GetById and PutById variants and then calculates the
+ percentage of gets or puts for each unique base,property pair compared to all the gets and puts.
+ Put together, this is useful to see what property accesses are not getting cached.
+
+ * Scripts/ic-stats.py: Added.
+ (ICStats):
+ (ICStats.__init__):
+ (ICStats.parse):
+ (ICStats.dumpStats):
+ (usage):
+
2019-04-10 Alex Christensen <achristen...@webkit.org>
WKNavigationResponse._downloadAttribute should be nil when no download attribute is present
Added: trunk/Tools/Scripts/ic-stats.py (0 => 244204)
--- trunk/Tools/Scripts/ic-stats.py (rev 0)
+++ trunk/Tools/Scripts/ic-stats.py 2019-04-12 00:53:12 UTC (rev 244204)
@@ -0,0 +1,125 @@
+#! /usr/bin/python
+
+# Copyright (C) 2019 Apple Inc. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 INC. OR ITS 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.
+
+import re
+import sys
+
+icStatRecord = re.compile(" +(\w+)\(([^,]+), ([^)]+)\)([^:]*): (\d+)")
+getByIdPrefix = "OperationGetById"
+putByIdPrefix = "OperationPutById"
+
+
+class ICStats:
+ def __init__(self):
+ self.combinedRecords = {}
+ self.slowGetById = {}
+ self.slowPutById = {}
+ self.totalSlowGetById = 0
+ self.totalSlowPutById = 0
+
+ def parse(self, file):
+ for line in file:
+ match = re.match(icStatRecord, line)
+ if match:
+ operation = match.group(1)
+ base = match.group(2)
+ property = match.group(3)
+ location = match.group(4).strip()
+ count = int(match.group(5))
+ recordKey = (operation, base, property, location)
+
+ if recordKey not in self.combinedRecords:
+ self.combinedRecords[recordKey] = count
+ else:
+ self.combinedRecords[recordKey] += count
+
+ if operation.startswith(getByIdPrefix):
+ self.totalSlowGetById += count
+
+ slowGetByIdKey = (base, property)
+ if slowGetByIdKey not in self.slowGetById:
+ self.slowGetById[slowGetByIdKey] = count
+ else:
+ self.slowGetById[slowGetByIdKey] += count
+
+ elif operation.startswith(putByIdPrefix):
+ self.totalSlowPutById += count
+
+ slowPutByIdKey = (base, property)
+ if slowPutByIdKey not in self.slowPutById:
+ self.slowPutById[slowPutByIdKey] = count
+ else:
+ self.slowPutById[slowPutByIdKey] += count
+
+ def dumpStats(self):
+ print "Total Slow getById = {0:>13,d}".format(self.totalSlowGetById)
+ print "Total Slow putById = {0:>13,d}".format(self.totalSlowPutById)
+
+ print "Operation Base Property Location Count % tot"
+ print "----------------------------------- -------------------- ------------------------------------ ------------ --------- slow"
+
+ keys = sorted(self.combinedRecords.keys(), key=lambda t: self.combinedRecords[t], reverse=True)
+ for key in keys:
+ count = self.combinedRecords[key]
+ operation = key[0]
+ base = key[1]
+ property = key[2]
+
+ if operation.startswith(getByIdPrefix):
+ slowPercent = " {0:>4.1f}%".format(float(self.slowGetById[(base, property)] * 100) / float(self.totalSlowGetById))
+ elif operation.startswith(putByIdPrefix):
+ slowPercent = " {0:>4.1f}%".format(float(self.slowPutById[(base, property)] * 100) / float(self.totalSlowPutById))
+ else:
+ slowPercent = ""
+
+ if len(property) > 36:
+ property = property[0:32] + "..."
+
+ print "{0:35} {1:20} {2:36} {3:12} {4:>9d}{5}".format(operation[0:34], base, property, key[3], count, slowPercent)
+
+
+def usage():
+ print "Usage: {0} [ic-stats-file]".format(sys.argv[0])
+ print " Where <ic-stats-file> is the results of using the useICStats option."
+ exit(1)
+
+if __name__ == "__main__":
+ if len(sys.argv) > 1:
+ if sys.argv[1] == "-h" or sys.argv[1].lower() == "--help" or sys.argv[1] == "-?":
+ usage()
+ try:
+ file = open(sys.argv[1], "r")
+ except IOError as e:
+ print "Couldn't open {0}, {1}".format(sys.argv[1], e.strerror)
+ usage()
+ except:
+ print "Unexpected error:", sys.exc_info()[0]
+ usage()
+ else:
+ file = sys.stdin
+
+ icStats = ICStats()
+ icStats.parse(file)
+ icStats.dumpStats()
Property changes on: trunk/Tools/Scripts/ic-stats.py
___________________________________________________________________
Added: svn:executable
+*
\ No newline at end of property