9

概要

フォーム入力のテキストをクリアすると、Chrome で長い遅延 (数秒) が発生します。これにより、計算されたスタイルのリフローまたは再計算が発生しているようですが、よくわかりません。Chrome の Profiler と Timeline は参考になりませんでした。

遅延の原因は何ですか? どうすればそれを取り除くことができますか? これは私のコードのエラーですか、それとも Chrome のバグですか?

http://jsfiddle.net/jmilloy/dHFsQ/

遅延を発生させるには、入力に入力してからテキストを削除します。最後の文字を削除するか、すべてを選択してから削除すると、遅延が発生します。

遅延をなくすには、 、、またはrow4の代わりに使用します。これで、遅延を引き起こすことなく入力をクリアできます。row1row2row3

ノート

  • 遅延はn、行数によって異なります。

  • Chrome では発生しますが、Firefox では発生しません。

  • Linux (Ubuntu/Mint 11) と Windows 7 では発生しますが、OSX では発生しません。誰でも確認できますか?


遅延動作を示すjsfiddleを取得したら、この質問を完全に書き直し、より単純な例で再度書き直しました。

4

3 に答える 3

7

これは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()( searchFunctionisWebCore::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 にバグを報告しました。

于 2013-04-05T20:42:02.620 に答える
2

これは WebKit のバグです (ホームページ/ Wikipedia の記事)。

この問題は、次の OS とブラウザーの組み合わせで再現できました。

  • Windows 7 SP1/クローム 26.0.1410.43 m

  • OS X 10.8.3 / サファリ 6.0.3 (8536.28.10)

  • Arch Linux 3.8.5-1 / Chromium 26.0.1410.43 (189671) (コンパイル済み)

  • Ubuntu 12.10 / Chromium 25.0.1364.160-0ubuntu0.12.10.1 (プリコンパイル済み、Ubuntu ソフトウェア センターから入手可能)

したがって、JavaScript 自体で修正することはできません。解決策は、別の表示方法を使用することです。そのような:

<tr><td style="border-bottom: dotted 1px #000; width: 5px; height: 10px;"></td></tr>

また

<tr><td><span style="display: inline-block; border-bottom: dotted 1px #000; width: 10px;"></span></td></tr>

ここにjsFiddleがあります。意図に応じて、どちらかが機能する場合があります。残念ながら、&#8230;andを使用してみ&#46;&#46;&#46;ましたが、役に立ちませんでした。


前述のように、この動作はFirefox では見られません

  • Windows 7 SP1 / Internet Explorer 10

  • iPhone iOS 6.1.2 / サファリ

  • iPad iOS 6.1.3 / サファリ


知らない人のために参考までに

WebKit: WebKit は、Web ブラウザーが Web ページをレンダリングできるように設計されたレイアウト エンジン ソフトウェアです。(ウィキペディア) WebKit は現在、Chrome、Chromium、および Safari で使用されています (2013 年 4 月 5 日現在)。

Chromium: Chromium は、Google Chrome がそのソース コードを取得するオープン ソースの Web ブラウザー プロジェクトです。ブラウザはコードと機能の大部分を共有していますが、いくつかの小さな違いがあります。(ウィキペディア)

于 2013-04-05T19:31:22.163 に答える
1

コードのこのセクションでは:

for (var i=0; i<peptides.data.length; i++)
  trs += peptides.row(peptides.data[i]);

peptides.data何らかの方法での長さを追加または変更すると、無限ループが発生する可能性があります。これは、peptides.data.lengthがループの反復ごとに評価されるためです。上記のコードではこれが起こっているようには見えませんが、要約版だとおっしゃいました。peptides.data.lengthいずれにせよ、毎回評価する必要がなければ、コードはかなり高速になるため、とにかく変更する価値があります。

for (var i=0, len = peptides.data.length; i<len; i++)
  ...

編集-この質問が更新されたので、OPが説明している問題がはっきりとわかります。私も、ここで何が起こっているのかを理解できる私よりも賢い人がいるかどうかを知りたいと思います.

于 2013-04-02T14:53:50.033 に答える