Title: [123691] trunk/Source/WebCore
- Revision
- 123691
- Author
- tk...@chromium.org
- Date
- 2012-07-25 18:36:33 -0700 (Wed, 25 Jul 2012)
Log Message
REGRESSION(r121420): Performance regression of form state saving for pages with multiple forms
https://bugs.webkit.org/show_bug.cgi?id=91804
Reviewed by Hajime Morita.
The complexity of FormKeyGenerator::formKey() was O(N) where N is the
number form elements with an identical action URL, and formKey() is
called for every form. So, it's O(N^2). A page in www.reddit.com
contains hundreds of form elements with action="" So FormController::
formElementsState() took a few seconds on a slow machine.
In order to avoid O(N^2) operation, storing a map from form signatures
to next index numbers, instead of storing existing formKey strings.
No new tests. Just a performance improvement.
Note: This is a re-landing of r123191. We rolled it out because of
suspicion of a performance regression. However it was innocent.
* html/FormController.cpp:
(FormKeyGenerator): Remove m_existingKeys. Add a map from a form
signature string to the next index number.
(WebCore::formSignature): Returns a signature string for a form, without
an index number. This is like "actionURL [name1 name2 ]"
(WebCore::FormKeyGenerator::formKey):
Creates a formKey string by concatenating a formSignature and #n. N is
obtained from m_formSignatureToNextIndexMap in O(1).
(WebCore::FormKeyGenerator::willDeleteForm):
Remove the code for m_existingKeys.
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (123690 => 123691)
--- trunk/Source/WebCore/ChangeLog 2012-07-26 01:22:59 UTC (rev 123690)
+++ trunk/Source/WebCore/ChangeLog 2012-07-26 01:36:33 UTC (rev 123691)
@@ -1,3 +1,35 @@
+2012-07-25 Kent Tamura <tk...@chromium.org>
+
+ REGRESSION(r121420): Performance regression of form state saving for pages with multiple forms
+ https://bugs.webkit.org/show_bug.cgi?id=91804
+
+ Reviewed by Hajime Morita.
+
+ The complexity of FormKeyGenerator::formKey() was O(N) where N is the
+ number form elements with an identical action URL, and formKey() is
+ called for every form. So, it's O(N^2). A page in www.reddit.com
+ contains hundreds of form elements with action="" So FormController::
+ formElementsState() took a few seconds on a slow machine.
+
+ In order to avoid O(N^2) operation, storing a map from form signatures
+ to next index numbers, instead of storing existing formKey strings.
+
+ No new tests. Just a performance improvement.
+
+ Note: This is a re-landing of r123191. We rolled it out because of
+ suspicion of a performance regression. However it was innocent.
+
+ * html/FormController.cpp:
+ (FormKeyGenerator): Remove m_existingKeys. Add a map from a form
+ signature string to the next index number.
+ (WebCore::formSignature): Returns a signature string for a form, without
+ an index number. This is like "actionURL [name1 name2 ]"
+ (WebCore::FormKeyGenerator::formKey):
+ Creates a formKey string by concatenating a formSignature and #n. N is
+ obtained from m_formSignatureToNextIndexMap in O(1).
+ (WebCore::FormKeyGenerator::willDeleteForm):
+ Remove the code for m_existingKeys.
+
2012-07-25 Benjamin Poulain <bpoul...@apple.com>
Initialize QualifiedName's strings from the read only data segment
Modified: trunk/Source/WebCore/html/FormController.cpp (123690 => 123691)
--- trunk/Source/WebCore/html/FormController.cpp 2012-07-26 01:22:59 UTC (rev 123690)
+++ trunk/Source/WebCore/html/FormController.cpp 2012-07-26 01:36:33 UTC (rev 123691)
@@ -278,8 +278,9 @@
FormKeyGenerator() { }
typedef HashMap<HTMLFormElement*, AtomicString> FormToKeyMap;
+ typedef HashMap<String, unsigned> FormSignatureToNextIndexMap;
FormToKeyMap m_formToKeyMap;
- HashSet<AtomicString> m_existingKeys;
+ FormSignatureToNextIndexMap m_formSignatureToNextIndexMap;
};
static inline void recordFormStructure(const HTMLFormElement& form, StringBuilder& builder)
@@ -304,10 +305,9 @@
builder.append("]");
}
-static inline AtomicString createKey(HTMLFormElement* form, unsigned index)
+static inline String formSignature(const HTMLFormElement& form)
{
- ASSERT(form);
- KURL actionURL = form->getURLAttribute(actionAttr);
+ KURL actionURL = form.getURLAttribute(actionAttr);
// Remove the query part because it might contain volatile parameters such
// as a session key.
actionURL.setQuery(String());
@@ -315,11 +315,8 @@
if (!actionURL.isEmpty())
builder.append(actionURL.string());
- recordFormStructure(*form, builder);
-
- builder.append(" #");
- builder.append(String::number(index));
- return builder.toAtomicString();
+ recordFormStructure(form, builder);
+ return builder.toString();
}
AtomicString FormKeyGenerator::formKey(const HTMLFormControlElementWithState& control)
@@ -333,13 +330,18 @@
if (it != m_formToKeyMap.end())
return it->second;
- AtomicString candidateKey;
- unsigned index = 0;
- do {
- candidateKey = createKey(form, index++);
- } while (!m_existingKeys.add(candidateKey).isNewEntry);
- m_formToKeyMap.add(form, candidateKey);
- return candidateKey;
+ String signature = formSignature(*form);
+ ASSERT(!signature.isNull());
+ FormSignatureToNextIndexMap::AddResult result = m_formSignatureToNextIndexMap.add(signature, 0);
+ unsigned nextIndex = result.iterator->second++;
+
+ StringBuilder builder;
+ builder.append(signature);
+ builder.append(" #");
+ builder.append(String::number(nextIndex));
+ AtomicString formKey = builder.toAtomicString();
+ m_formToKeyMap.add(form, formKey);
+ return formKey;
}
void FormKeyGenerator::willDeleteForm(HTMLFormElement* form)
@@ -350,7 +352,6 @@
FormToKeyMap::iterator it = m_formToKeyMap.find(form);
if (it == m_formToKeyMap.end())
return;
- m_existingKeys.remove(it->second);
m_formToKeyMap.remove(it);
}
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes