From 2eb7c7dd6392488d858989da8d57d618f58f04ca Mon Sep 17 00:00:00 2001 From: dsinclair Date: Thu, 18 Aug 2016 09:58:19 -0700 Subject: Use a map for app::m_Timers Currently the timers is a vector. When we cancel a timer we have an O(n) operation to remove the timer. If there are a lot of timers (which this test has > 16k) this can take a long time. The impact is a lot lower in Release, but the test is very slow in Debug. From Linux on waterfall: [ RUN ] FPDFFormFillEmbeddertest.BUG_634716 [ OK ] FPDFFormFillEmbeddertest.BUG_634716 (7855 ms) From Linux try bot: [ RUN ] FPDFFormFillEmbeddertest.BUG_634716 [ OK ] FPDFFormFillEmbeddertest.BUG_634716 (431 ms) From Linux XFA Rel GYP on waterfall: [ RUN ] FPDFFormFillEmbeddertest.BUG_634716 [ OK ] FPDFFormFillEmbeddertest.BUG_634716 (185 ms) From Linux XFA Rel GYP try bot: [ RUN ] FPDFFormFillEmbeddertest.BUG_634716 [ OK ] FPDFFormFillEmbeddertest.BUG_634716 (72 ms) Review-Url: https://codereview.chromium.org/2251333002 --- fpdfsdk/javascript/app.cpp | 26 +++++++++++++------------- fpdfsdk/javascript/app.h | 3 ++- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/fpdfsdk/javascript/app.cpp b/fpdfsdk/javascript/app.cpp index 97c97eb89a..573de4030a 100644 --- a/fpdfsdk/javascript/app.cpp +++ b/fpdfsdk/javascript/app.cpp @@ -509,15 +509,18 @@ FX_BOOL app::setInterval(IJS_Context* cc, uint32_t dwInterval = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000; CPDFDoc_Environment* pApp = pRuntime->GetReaderApp(); - m_Timers.push_back(std::unique_ptr( - new GlobalTimer(this, pApp, pRuntime, 0, script, dwInterval, 0))); + + std::unique_ptr timer( + new GlobalTimer(this, pApp, pRuntime, 0, script, dwInterval, 0)); + GlobalTimer* timerRef = timer.get(); + m_Timers[timerRef] = std::move(timer); v8::Local pRetObj = pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); CJS_TimerObj* pJS_TimerObj = static_cast(pRuntime->GetObjectPrivate(pRetObj)); TimerObj* pTimerObj = static_cast(pJS_TimerObj->GetEmbedObject()); - pTimerObj->SetTimer(m_Timers.back().get()); + pTimerObj->SetTimer(timerRef); vRet = CJS_Value(pRuntime, pRetObj); return TRUE; @@ -543,8 +546,11 @@ FX_BOOL app::setTimeOut(IJS_Context* cc, uint32_t dwTimeOut = params.size() > 1 ? params[1].ToInt(pRuntime) : 1000; CPDFDoc_Environment* pApp = pRuntime->GetReaderApp(); - m_Timers.push_back(std::unique_ptr( - new GlobalTimer(this, pApp, pRuntime, 1, script, dwTimeOut, dwTimeOut))); + + std::unique_ptr timer( + new GlobalTimer(this, pApp, pRuntime, 1, script, dwTimeOut, dwTimeOut)); + GlobalTimer* timerRef = timer.get(); + m_Timers[timerRef] = std::move(timer); v8::Local pRetObj = pRuntime->NewFxDynamicObj(CJS_TimerObj::g_nObjDefnID); @@ -553,7 +559,7 @@ FX_BOOL app::setTimeOut(IJS_Context* cc, static_cast(pRuntime->GetObjectPrivate(pRetObj)); TimerObj* pTimerObj = static_cast(pJS_TimerObj->GetEmbedObject()); - pTimerObj->SetTimer(m_Timers.back().get()); + pTimerObj->SetTimer(timerRef); vRet = CJS_Value(pRuntime, pRetObj); return TRUE; @@ -620,13 +626,7 @@ void app::TimerProc(GlobalTimer* pTimer) { } void app::CancelProc(GlobalTimer* pTimer) { - auto iter = std::find_if(m_Timers.begin(), m_Timers.end(), - [pTimer](const std::unique_ptr& that) { - return pTimer == that.get(); - }); - - if (iter != m_Timers.end()) - m_Timers.erase(iter); + m_Timers.erase(pTimer); } void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) { diff --git a/fpdfsdk/javascript/app.h b/fpdfsdk/javascript/app.h index 97db59e437..911d86586a 100644 --- a/fpdfsdk/javascript/app.h +++ b/fpdfsdk/javascript/app.h @@ -7,6 +7,7 @@ #ifndef FPDFSDK_JAVASCRIPT_APP_H_ #define FPDFSDK_JAVASCRIPT_APP_H_ +#include #include #include @@ -165,7 +166,7 @@ class app : public CJS_EmbedObj { bool m_bCalculate; bool m_bRuntimeHighLight; - std::vector> m_Timers; + std::map> m_Timers; }; class CJS_App : public CJS_Object { -- cgit v1.2.3