これはWebKitのパフォーマンス バグまたはICUの解析バグ、おそらくその両方のようですが、問題は WebKit にあると考えがちです。
OS X でソースから Chromium をビルドし、ビルドで問題が発生することを確認しました。OS X の Chrome に表示されない理由は明らかではありません。テスト ページでレンダラー プロセスをプロファイリングしたところ、ほとんどの時間を ICU の関数RuleBasedBreakIterator::handleNext()
とで費やしていることがわかりましたRuleBasedBreakIterator::handlePrevious()
。典型的なスタック トレースを次に示します。
Program received signal SIGINT, Interrupt.
icu_46::RuleBasedBreakIterator::handleNext (this=0x6a1f4600, statetable=0xafdbb50) at ../../third_party/icu/source/common/rbbi.cpp:1085
1085 if (state == STOP_STATE) {
(gdb) where
#0 icu_46::RuleBasedBreakIterator::handleNext (this=0x6a1f4600, statetable=0xafdbb50) at ../../third_party/icu/source/common/rbbi.cpp:1085
#1 0x09c2048f in icu_46::RuleBasedBreakIterator::next (this=0x6a1f4600) at ../../third_party/icu/source/common/rbbi.cpp:535
#2 0x09c23a30 in icu_46::RuleBasedBreakIterator::following (this=0x6a1f4600, offset=2377) at ../../third_party/icu/source/common/rbbi.cpp:693
#3 0x09c50399 in ubrk_following_46 (bi=0x6a1f4600, offset=2377) at ../../third_party/icu/source/common/ubrk.cpp:254
#4 0x03112489 in WebCore::textBreakFollowing (iterator=0x6a1f4600, pos=2377) at ../../third_party/WebKit/Source/WebCore/platform/text/TextBreakIteratorICU.cpp:380
#5 0x03111276 in WebCore::findNextWordFromIndex (chars=0x69a7a000, len=2848, position=2377, forward=true) at ../../third_party/WebKit/Source/WebCore/platform/text/TextBoundaries.cpp:77
#6 0x016352d3 in WebCore::nextWordPositionBoundary (characters=0x69a7a000, length=2848, offset=0, mayHaveMoreContext=WebCore::MayHaveMoreContext, needMoreContext=@0xc00078b2) at ../../third_party/WebKit/Source/WebCore/editing/VisibleUnits.cpp:695
#7 0x0163498a in WebCore::nextBoundary (c=@0xc0008440, searchFunction=0x1635220 <WebCore::nextWordPositionBoundary(unsigned short const*, unsigned int, unsigned int, WebCore::BoundarySearchContextAvailability, bool&)>) at ../../third_party/WebKit/Source/WebCore/editing/VisibleUnits.cpp:575
#8 0x016351c5 in WebCore::nextWordPosition (c=@0xc0008440) at ../../third_party/WebKit/Source/WebCore/editing/VisibleUnits.cpp:700
#9 0x0159d2ce in WebCore::Editor::updateMarkersForWordsAffectedByEditing (this=0x6abca710, doNotRemoveIfSelectionAtWordBoundary=true) at ../../third_party/WebKit/Source/WebCore/editing/Editor.cpp:2398
#10 0x0159ce7c in WebCore::Editor::respondToChangedContents (this=0x6abca710, endingSelection=@0xc0008578) at ../../third_party/WebKit/Source/WebCore/editing/Editor.cpp:556
#11 0x0159fa81 in WebCore::Editor::appliedEditing (this=0x6abca710, cmd=@0xc00085f0) at ../../third_party/WebKit/Source/WebCore/editing/Editor.cpp:863
#12 0x0162597a in WebCore::TypingCommand::typingAddedToOpenCommand (this=0x6a570fb0, commandTypeForAddedTyping=WebCore::TypingCommand::DeleteKey) at ../../third_party/WebKit/Source/WebCore/editing/TypingCommand.cpp:347
#13 0x01622e05 in WebCore::TypingCommand::deleteKeyPressed (this=0x6a570fb0, granularity=WebCore::CharacterGranularity, killRing=false) at ../../third_party/WebKit/Source/WebCore/editing/TypingCommand.cpp:525
#14 0x01621bfa in WebCore::TypingCommand::deleteKeyPressed (document=0x6abcc200, options=0, granularity=WebCore::CharacterGranularity) at ../../third_party/WebKit/Source/WebCore/editing/TypingCommand.cpp:120
#15 0x0159b945 in WebCore::Editor::deleteWithDirection (this=0x6abca710, direction=WebCore::DirectionBackward, granularity=WebCore::CharacterGranularity, killRing=false, isTypingAction=true) at ../../third_party/WebKit/Source/WebCore/editing/Editor.cpp:382
#16 0x015b5cc8 in WebCore::executeDeleteBackward (frame=0x6abca200) at ../../third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp:339
#17 0x015b4e7f in WebCore::Editor::Command::execute (this=0xc0008c28, parameter=@0xc0008c20, triggeringEvent=0x0) at ../../third_party/WebKit/Source/WebCore/editing/EditorCommand.cpp:1706
#18 0x0419f8c4 in WebKit::WebFrameImpl::executeCommand (this=0x6a31f770, name=@0xc0008ca0, value=@0xc0008c98) at ../../third_party/WebKit/Source/WebKit/chromium/src/WebFrameImpl.cpp:1245
#19 0x07d5e3a1 in content::RenderViewImpl::handleCurrentKeyboardEvent (this=0x6a998000) at ../../content/renderer/render_view_impl.cc:2189
#20 0x07d5e452 in non-virtual thunk to content::RenderViewImpl::handleCurrentKeyboardEvent() (this=0x6a998314) at ../../content/renderer/render_view_impl.cc:2195
#21 0x040f97dc in WebKit::EditorClientImpl::handleKeyboardEvent (this=0x6a9ba674, evt=0x190468e0) at ../../third_party/WebKit/Source/WebKit/chromium/src/EditorClientImpl.cpp:645
#22 0x01599799 in WebCore::Editor::handleKeyboardEvent (this=0x6abca710, event=0x190468e0) at ../../third_party/WebKit/Source/WebCore/editing/Editor.cpp:212
#23 0x01a9713d in WebCore::EventHandler::defaultKeyboardEventHandler (this=0x6abca854, event=0x190468e0) at ../../third_party/WebKit/Source/WebCore/page/EventHandler.cpp:3325
#24 0x07790701 in WebCore::Node::defaultEventHandler (this=0x19049eb0, event=0x190468e0) at ../../third_party/WebKit/Source/WebCore/dom/Node.cpp:2475
#25 0x048aa253 in WebCore::HTMLTextFormControlElement::defaultEventHandler (this=0x19049eb0, event=0x190468e0) at ../../third_party/WebKit/Source/WebCore/html/HTMLTextFormControlElement.cpp:111
#26 0x0480cf5f in WebCore::HTMLInputElement::defaultEventHandler (this=0x19049eb0, evt=0x190468e0) at ../../third_party/WebKit/Source/WebCore/html/HTMLInputElement.cpp:1159
#27 0x0772ac59 in WebCore::EventDispatcher::dispatchEventPostProcess (this=0xc0009048, preDispatchEventHandlerResult=0x0) at ../../third_party/WebKit/Source/WebCore/dom/EventDispatcher.cpp:208
#28 0x07729cc6 in WebCore::EventDispatcher::dispatch (this=0xc0009048) at ../../third_party/WebKit/Source/WebCore/dom/EventDispatcher.cpp:127
#29 0x07728b03 in WebCore::EventDispatchMediator::dispatchEvent (this=0x190f6f90, dispatcher=0xc0009048) at ../../third_party/WebKit/Source/WebCore/dom/EventDispatchMediator.cpp:54
#30 0x07728f50 in WebCore::EventDispatcher::dispatchEvent (node=0x19049eb0, mediator=@0xc0009130) at ../../third_party/WebKit/Source/WebCore/dom/EventDispatcher.cpp:56
#31 0x0778f078 in WebCore::Node::dispatchEvent (this=0x19049eb0, event=@0xc0009198) at ../../third_party/WebKit/Source/WebCore/dom/Node.cpp:2351
#32 0x077405e1 in WebCore::EventTarget::dispatchEvent (this=0x19049eb0, event=@0xc00092e8, ec=@0xc00092e0) at ../../third_party/WebKit/Source/WebCore/dom/EventTarget.cpp:147
#33 0x01a9688a in WebCore::EventHandler::keyEvent (this=0x6abca854, initialKeyEvent=@0xc00093c0) at ../../third_party/WebKit/Source/WebCore/page/EventHandler.cpp:3207
#34 0x04236521 in WebKit::WebViewImpl::handleKeyEvent (this=0x6a9ba600, event=@0x1900f2e8) at ../../third_party/WebKit/Source/WebKit/chromium/src/WebViewImpl.cpp:1003
#35 0x04236def in non-virtual thunk to WebKit::WebViewImpl::handleKeyEvent(WebKit::WebKeyboardEvent const&) (this=0x6a9ba628, event=@0x1900f2e8) at ../../third_party/WebKit/Source/WebKit/chromium/src/WebViewImpl.cpp:1015
#36 0x0413554d in WebKit::PageWidgetDelegate::handleInputEvent (page=0x6a9baa00, handler=@0x6a9ba628, event=@0x1900f2e8) at ../../third_party/WebKit/Source/WebKit/chromium/src/PageWidgetDelegate.cpp:144
#37 0x0423bebb in WebKit::WebViewImpl::handleInputEvent (this=0x6a9ba600, inputEvent=@0x1900f2e8) at ../../third_party/WebKit/Source/WebKit/chromium/src/WebViewImpl.cpp:2058
#38 0x07db4d90 in content::RenderWidget::OnHandleInputEvent (this=0x6a998000, input_event=0x1900f2e8, is_keyboard_shortcut=true) at ../../content/renderer/render_widget.cc:732
#39 0x07dca53b in DispatchToMethod<content::RenderWidget, void (content::RenderWidget::*)(WebKit::WebInputEvent const*, bool), WebKit::WebInputEvent const*, bool> (obj=0x6a998000, method=not implemented: member type in c_val_print
) at tuple.h:553
#40 0x07dc2235 in ViewMsg_HandleInputEvent::Dispatch<content::RenderWidget, content::RenderWidget, void (content::RenderWidget::*)(WebKit::WebInputEvent const*, bool)> (msg=0x190279c8, obj=0x6a998000, sender=0x6a998000, func=not implemented: member type in c_val_print
) at view_messages.h:867
#41 0x07db3488 in content::RenderWidget::OnMessageReceived (this=0x6a998000, message=@0x190279c8) at ../../content/renderer/render_widget.cc:307
#42 0x07d50bae in content::RenderViewImpl::OnMessageReceived (this=0x6a998000, message=@0x190279c8) at ../../content/renderer/render_view_impl.cc:1136
#43 0x082c9133 in content::MessageRouter::RouteMessage (this=0x190a252c, msg=@0x190279c8) at ../../content/common/message_router.cc:49
#44 0x082c9085 in content::MessageRouter::OnMessageReceived (this=0x190a252c, msg=@0x190279c8) at ../../content/common/message_router.cc:41
#45 0x07f410b9 in content::ChildThread::OnMessageReceived (this=0x190a2514, msg=@0x190279c8) at ../../content/common/child_thread.cc:274
#46 0x03fec745 in IPC::ChannelProxy::Context::OnDispatchMessage (this=0x19098a40, message=@0x190279c8) at ../../ipc/ipc_channel_proxy.cc:261
#47 0x03ff5920 in base::internal::RunnableAdapter<void (IPC::ChannelProxy::Context::*)(IPC::Message const&)>::Run (this=0xc000b1d0, object=0x19098a40, a1=@0x190279c8) at bind_internal.h:190
#48 0x03ff580f in base::internal::InvokeHelper<false, void, base::internal::RunnableAdapter<void (IPC::ChannelProxy::Context::*)(IPC::Message const&)>, void ()(IPC::ChannelProxy::Context* const&, IPC::Message const&)>::MakeItSo (runnable=Unexpected type (16) encountered for integer constant.
) at bind_internal.h:899
#49 0x03ff5744 in base::internal::Invoker<2, base::internal::BindState<base::internal::RunnableAdapter<void (IPC::ChannelProxy::Context::*)(IPC::Message const&)>, void ()(IPC::ChannelProxy::Context*, IPC::Message const&), void ()(IPC::ChannelProxy::Context*, IPC::Message)>, void ()(IPC::ChannelProxy::Context*, IPC::Message const&)>::Run (base=0x190279b0) at bind_internal.h:1257
#50 0x026c51fb in base::Callback<void ()()>::Run (this=0xc000b464) at callback.h:396
#51 0x0438583a in base::MessageLoop::RunTask (this=0xc000d058, pending_task=@0xc000b450) at ../../base/message_loop.cc:474
#52 0x04385c92 in base::MessageLoop::DeferOrRunPendingTask (this=0xc000d058, pending_task=@0xc000b450) at ../../base/message_loop.cc:486
#53 0x04385e92 in base::MessageLoop::DoWork (this=0xc000d058) at ../../base/message_loop.cc:669
#54 0x042e280b in base::MessagePumpCFRunLoopBase::RunWork (this=0x6a16ef60) at ../../base/message_pump_mac.mm:252
#55 0x042e1fc2 in base::MessagePumpCFRunLoopBase::RunWorkSource (info=0x6a16ef60) at ../../base/message_pump_mac.mm:230
#56 0x9bc7e13f in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
#57 0x9bc7daf6 in __CFRunLoopDoSources0 ()
#58 0x9bca79c8 in __CFRunLoopRun ()
#59 0x9bca71dc in CFRunLoopRunSpecific ()
#60 0x9bca7088 in CFRunLoopRunInMode ()
#61 0x92f83543 in RunCurrentEventLoopInMode ()
#62 0x92f8a8ab in ReceiveNextEventCommon ()
#63 0x92f8a71a in BlockUntilNextEventMatchingListInMode ()
#64 0x99b31ee8 in _DPSNextEvent ()
#65 0x99b31752 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] ()
#66 0x99b2dac1 in -[NSApplication run] ()
#67 0x042e372e in base::MessagePumpNSApplication::DoRun (this=0x6a16ef60, delegate=0xc000d058) at ../../base/message_pump_mac.mm:576
#68 0x042e2578 in base::MessagePumpCFRunLoopBase::Run (this=0x6a16ef60, delegate=0xc000d058) at ../../base/message_pump_mac.mm:171
#69 0x043850a2 in base::MessageLoop::RunInternal (this=0xc000d058) at ../../base/message_loop.cc:431
#70 0x04384f5b in base::MessageLoop::RunHandler (this=0xc000d058) at ../../base/message_loop.cc:404
#71 0x043ea808 in base::RunLoop::Run (this=0xc000ccc0) at ../../base/run_loop.cc:45
#72 0x04384357 in base::MessageLoop::Run (this=0xc000d058) at ../../base/message_loop.cc:311
#73 0x07dd3a14 in content::RendererMain (parameters=@0xc000d348) at ../../content/renderer/renderer_main.cc:226
#74 0x086f4324 in content::RunNamedProcessTypeMain (process_type=@0xc000d368, main_function_params=@0xc000d348, delegate=0xc000d5a0) at ../../content/app/content_main_runner.cc:459
#75 0x086f5788 in content::ContentMainRunnerImpl::Run (this=0x6a16c080) at ../../content/app/content_main_runner.cc:764
#76 0x086f3457 in content::ContentMain (argc=7, argv=0xc000d620, delegate=0xc000d5a0) at ../../content/app/content_main.cc:35
#77 0x00017d2c in ChromeMain (argc=7, argv=0xc000d620) at ../../chrome/app/chrome_main.cc:32
#78 0x0000ff7b in main (argc=7, argv=0xc000d620) at ../../chrome/app/chrome_exe_main_mac.cc:16
(gdb)
バグはレイアウトにあるようには見えません (レイアウトが更新されているように見えますが)。問題はスペル チェック マーカーの更新にあるようWebCore::Editor::updateMarkersForWordsAffectedByEditing()
です。更新するコンテンツの範囲を把握するために時間が費やされていますRuleBasedBreakIterator
。範囲が「単語」境界で開始および終了することを確認するために を使用しています。境界の検索は基本的に文字を追加し続け、「これは完全な単語ですか?」と尋ねます。それは単語の長さでO(n ^ 2)ですが、何らかの理由で完全な単語のテストが失敗し続け、nは数千です...動作が実際にO(n ^ 2)であることをタイミングで確認しましたテーブルの行数。WebCore::nextBoundary()
( searchFunction
isWebCore::nextWordPositionBoundary
と is は完全な単語をテストするものです)の検索ループは次のとおりです。
while (!it.atEnd()) {
// Keep asking the iterator for chunks until the search function
// returns an end value not equal to the length of the string passed to it.
if (!inTextSecurityMode)
string.append(it.characters(), it.length());
else {
// Treat bullets used in the text security mode as regular characters when looking for boundaries
String iteratorString(it.characters(), it.length());
iteratorString.fill('x');
string.append(iteratorString.characters(), iteratorString.length());
}
next = searchFunction(string.data(), string.size(), prefixLength, MayHaveMoreContext, needMoreContext);
if (next != string.size())
break;
it.advance();
}
文字列の内容は、UTF-16 では ",\n…\n…\n…" のように見えますが、省略記号の行はいくつありますか。が改行で境界を検出しない理由がわかりません。また、タグ テキストWebCore::nextWordPositionBoundary()
の外側を探している理由もわかりません。<input>
バグが WebKit nightly build に存在することを確認し、 WebKit にバグを報告しました。