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