1 From 5737bdb3d7e5819528e33c360a73372e0e93a6be Mon Sep 17 00:00:00 2001
2 From: Noel Grandin <noel.grandin@collabora.co.uk>
3 Date: Fri, 3 Nov 2023 12:04:30 +0000
4 Subject: [PATCH] speed up hunspell inner loop
6 which calls into the kernel to get elapsed time, instead of using the
7 VDSO-based CLOCK_MONOTONIC (or at least, the C++ equivalent of that),
10 https://gerrit.libreoffice.org/c/core/+/158809
12 src/hunspell/affixmgr.cxx | 43 +++++++++++++++++++++++----------------
13 1 file changed, 25 insertions(+), 18 deletions(-)
15 diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx
16 index 2cad09f..a3c93cd 100644
17 --- a/src/hunspell/affixmgr.cxx
18 +++ b/src/hunspell/affixmgr.cxx
27 @@ -1590,17 +1591,20 @@ struct hentry* AffixMgr::compound_check(const std::string& word,
28 // add a time limit to handle possible
29 // combinatorical explosion of the overlapping words
31 - HUNSPELL_THREAD_LOCAL clock_t timelimit;
32 + HUNSPELL_THREAD_LOCAL std::chrono::steady_clock::time_point clock_time_start;
33 + HUNSPELL_THREAD_LOCAL bool timelimit_exceeded;
35 + // get the current time
36 + std::chrono::steady_clock::time_point clock_now = std::chrono::steady_clock::now();
39 - // get the start time, seeing as we're reusing this set to 0
40 - // to flag timeout, use clock() + 1 to avoid start clock()
41 - // of 0 as being a timeout
42 - timelimit = clock() + 1;
44 - else if (timelimit != 0 && (clock() > timelimit + TIMELIMIT)) {
46 + // set the start time
47 + clock_time_start = clock_now;
48 + timelimit_exceeded = false;
50 + else if (std::chrono::duration_cast<std::chrono::milliseconds>(clock_now - clock_time_start).count()
51 + > TIMELIMIT * CLOCKS_PER_SEC * 1000)
52 + timelimit_exceeded = true;
54 setcminmax(&cmin, &cmax, word.c_str(), len);
56 @@ -1626,7 +1630,7 @@ struct hentry* AffixMgr::compound_check(const std::string& word,
58 do { // simplified checkcompoundpattern loop
61 + if (timelimit_exceeded)
65 @@ -2216,17 +2220,20 @@ int AffixMgr::compound_check_morph(const std::string& word,
66 // add a time limit to handle possible
67 // combinatorical explosion of the overlapping words
69 - HUNSPELL_THREAD_LOCAL clock_t timelimit;
70 + HUNSPELL_THREAD_LOCAL std::chrono::steady_clock::time_point clock_time_start;
71 + HUNSPELL_THREAD_LOCAL bool timelimit_exceeded;
73 + // get the current time
74 + std::chrono::steady_clock::time_point clock_now = std::chrono::steady_clock::now();
77 - // get the start time, seeing as we're reusing this set to 0
78 - // to flag timeout, use clock() + 1 to avoid start clock()
79 - // of 0 as being a timeout
80 - timelimit = clock() + 1;
82 - else if (timelimit != 0 && (clock() > timelimit + TIMELIMIT)) {
84 + // set the start time
85 + clock_time_start = clock_now;
86 + timelimit_exceeded = false;
88 + else if (std::chrono::duration_cast<std::chrono::milliseconds>(clock_now - clock_time_start).count()
89 + > TIMELIMIT * CLOCKS_PER_SEC * 1000)
90 + timelimit_exceeded = true;
92 setcminmax(&cmin, &cmax, word.c_str(), len);
94 @@ -2246,7 +2253,7 @@ int AffixMgr::compound_check_morph(const std::string& word,
96 do { // onlycpdrule loop
99 + if (timelimit_exceeded)
102 oldnumsyllable = numsyllable;