Skip to content

Commit 1dcedfe

Browse files
committed
Redesign translation data format
The current format for translation data is problematic. Design and implement a new format which is more time-efficient and space-efficient. See the documentation in tools/compile-translations.go for details. This commit should not change behavior. Benchmarks before: -------------------------------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------------------------------- benchmark_translate_from_source_code 4.20 ns 4.20 ns 166058970 benchmark_translate_from_translation_hit 21.5 ns 21.5 ns 32483955 benchmark_translate_from_translation_miss 14.3 ns 14.3 ns 48922995 benchmark_load_translations/c 24.5 ns 24.5 ns 28542187 benchmark_load_translations/en 28.5 ns 28.5 ns 24432980 benchmark_load_translations/en_loud 42.8 ns 42.8 ns 16316674 benchmark_load_translations/en_us 51.6 ns 51.6 ns 13472161 benchmark_load_translations/en_us_loud 71.6 ns 71.6 ns 9730601 benchmark_load_translations/en_us_utf8 94.9 ns 94.9 ns 7243153 benchmark_load_translations/en_us_utf8_loud 119 ns 119 ns 5856172 benchmark_load_translations/posix 32.3 ns 32.3 ns 21791104 benchmark_load_translations_and_find_hit 56.3 ns 56.3 ns 12252757 benchmark_load_translations_and_find_miss 52.1 ns 52.1 ns 13305961 Benchmarks after: -------------------------------------------------------------------------------------- Benchmark Time CPU Iterations -------------------------------------------------------------------------------------- benchmark_translate_from_source_code 3.11 ns 3.11 ns 223754407 benchmark_translate_from_translation_hit 1.73 ns 1.73 ns 404250404 benchmark_translate_from_translation_miss 2.17 ns 2.17 ns 320953691 benchmark_load_translations/c 30.1 ns 30.1 ns 23174741 benchmark_load_translations/en 34.1 ns 34.1 ns 20494803 benchmark_load_translations/en_loud 39.3 ns 39.3 ns 17804728 benchmark_load_translations/en_us 63.1 ns 63.1 ns 10996089 benchmark_load_translations/en_us_loud 67.1 ns 67.1 ns 10363768 benchmark_load_translations/en_us_utf8 115 ns 115 ns 6080506 benchmark_load_translations/en_us_utf8_loud 126 ns 126 ns 5536004 benchmark_load_translations/posix 37.2 ns 37.2 ns 18806537 benchmark_load_translations_and_find_hit 39.9 ns 39.9 ns 17542497 benchmark_load_translations_and_find_miss 40.2 ns 40.2 ns 17409687
1 parent 5a2c71f commit 1dcedfe

29 files changed

+3893
-6312
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ add_subdirectory(plugin/vim)
6666
add_subdirectory(plugin/emacs)
6767
add_subdirectory(plugin/vscode)
6868
add_subdirectory(src)
69-
add_subdirectory(tools)
7069
add_subdirectory(website/wasm)
7170
add_subdirectory(completions)
7271
include(CTest)

benchmark/benchmark-translation.cpp

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
#include <benchmark/benchmark.h>
55
#include <quick-lint-js/assert.h>
6-
#include <quick-lint-js/gmo.h>
7-
#include <quick-lint-js/translation-data.h>
86
#include <quick-lint-js/translation.h>
97

108
namespace quick_lint_js {
@@ -14,55 +12,55 @@ void benchmark_translate_from_source_code(benchmark::State &state) {
1412
messages.use_messages_from_source_code();
1513
for (auto _ : state) {
1614
::benchmark::DoNotOptimize(messages.translate(
17-
"variable assigned before its declaration"_gmo_message));
15+
"variable assigned before its declaration"_translatable));
1816
::benchmark::DoNotOptimize(
19-
messages.translate("variable declared here"_gmo_message));
17+
messages.translate("variable declared here"_translatable));
2018
::benchmark::DoNotOptimize(messages.translate(
21-
"~~~ invalid string, do not use outside benchmark ~~~"_gmo_message));
19+
"~~~ invalid string, do not use outside benchmark ~~~"_translatable));
2220
}
2321
}
2422
BENCHMARK(benchmark_translate_from_source_code);
2523

2624
void benchmark_translate_from_translation_hit(benchmark::State &state) {
27-
static constexpr gmo_message messages_to_translate[] = {
28-
"variable assigned before its declaration"_gmo_message,
29-
"variable declared here"_gmo_message,
25+
static constexpr translatable_message messages_to_translate[] = {
26+
"variable assigned before its declaration"_translatable,
27+
"variable declared here"_translatable,
3028
};
3129

3230
translatable_messages messages;
33-
bool have_translation =
34-
messages.use_messages_from_locale("en@loud", gmo_files);
31+
bool have_translation = messages.use_messages_from_locale("en@loud");
3532
QLJS_ALWAYS_ASSERT(have_translation);
36-
for (const gmo_message &message : messages_to_translate) {
33+
for (const translatable_message &message : messages_to_translate) {
3734
// Messages should be translated.
38-
QLJS_ALWAYS_ASSERT(messages.translate(message) != message.message());
35+
QLJS_ALWAYS_ASSERT(
36+
std::strcmp(messages.translate(message), message.c_str()) != 0);
3937
}
4038

4139
for (auto _ : state) {
42-
for (const gmo_message &message : messages_to_translate) {
40+
for (const translatable_message &message : messages_to_translate) {
4341
::benchmark::DoNotOptimize(messages.translate(message));
4442
}
4543
}
4644
}
4745
BENCHMARK(benchmark_translate_from_translation_hit);
4846

4947
void benchmark_translate_from_translation_miss(benchmark::State &state) {
50-
static constexpr gmo_message messages_to_translate[] = {
51-
"~~~ invalid string, do not use outside benchmark ~~~"_gmo_message,
52-
"another invalid string, do not use outside benchmark"_gmo_message,
48+
static constexpr translatable_message messages_to_translate[] = {
49+
"~~~ invalid string, do not use outside benchmark ~~~"_translatable,
50+
"another invalid string, do not use outside benchmark"_translatable,
5351
};
5452

5553
translatable_messages messages;
56-
bool have_translation =
57-
messages.use_messages_from_locale("en@loud", gmo_files);
54+
bool have_translation = messages.use_messages_from_locale("en@loud");
5855
QLJS_ALWAYS_ASSERT(have_translation);
59-
for (const gmo_message &message : messages_to_translate) {
56+
for (const translatable_message &message : messages_to_translate) {
6057
// Messages should not be translated.
61-
QLJS_ALWAYS_ASSERT(messages.translate(message) == message.message());
58+
QLJS_ALWAYS_ASSERT(
59+
std::strcmp(messages.translate(message), message.c_str()) == 0);
6260
}
6361

6462
for (auto _ : state) {
65-
for (const gmo_message &message : messages_to_translate) {
63+
for (const translatable_message &message : messages_to_translate) {
6664
::benchmark::DoNotOptimize(messages.translate(message));
6765
}
6866
}
@@ -72,8 +70,7 @@ BENCHMARK(benchmark_translate_from_translation_miss);
7270
void benchmark_load_translations(benchmark::State &state, const char *locale) {
7371
for (auto _ : state) {
7472
translatable_messages messages;
75-
bool have_translation =
76-
messages.use_messages_from_locale(locale, gmo_files);
73+
bool have_translation = messages.use_messages_from_locale(locale);
7774
::benchmark::DoNotOptimize(have_translation);
7875
::benchmark::DoNotOptimize(messages);
7976
}
@@ -89,49 +86,45 @@ BENCHMARK_CAPTURE(benchmark_load_translations, en_us_utf8_loud,
8986
BENCHMARK_CAPTURE(benchmark_load_translations, posix, "POSIX");
9087

9188
void benchmark_load_translations_and_find_hit(benchmark::State &state) {
92-
static constexpr gmo_message message_to_translate =
93-
"variable assigned before its declaration"_gmo_message;
89+
static constexpr translatable_message message_to_translate =
90+
"variable assigned before its declaration"_translatable;
9491

9592
const char *locale = "en@loud";
9693
{
9794
// Message should be translated.
9895
translatable_messages messages;
99-
bool have_translation =
100-
messages.use_messages_from_locale(locale, gmo_files);
96+
bool have_translation = messages.use_messages_from_locale(locale);
10197
QLJS_ALWAYS_ASSERT(have_translation);
102-
QLJS_ALWAYS_ASSERT(messages.translate(message_to_translate) !=
103-
message_to_translate.message());
98+
QLJS_ALWAYS_ASSERT(std::strcmp(messages.translate(message_to_translate),
99+
message_to_translate.c_str()) != 0);
104100
}
105101

106102
for (auto _ : state) {
107103
translatable_messages messages;
108-
bool have_translation =
109-
messages.use_messages_from_locale(locale, gmo_files);
104+
bool have_translation = messages.use_messages_from_locale(locale);
110105
::benchmark::DoNotOptimize(have_translation);
111106
::benchmark::DoNotOptimize(messages.translate(message_to_translate));
112107
}
113108
}
114109
BENCHMARK(benchmark_load_translations_and_find_hit);
115110

116111
void benchmark_load_translations_and_find_miss(benchmark::State &state) {
117-
static constexpr gmo_message message_to_translate =
118-
"~~~ invalid string, do not use outside benchmark ~~~"_gmo_message;
112+
static constexpr translatable_message message_to_translate =
113+
"~~~ invalid string, do not use outside benchmark ~~~"_translatable;
119114

120115
const char *locale = "en@loud";
121116
{
122117
// Message should not be translated.
123118
translatable_messages messages;
124-
bool have_translation =
125-
messages.use_messages_from_locale(locale, gmo_files);
119+
bool have_translation = messages.use_messages_from_locale(locale);
126120
QLJS_ALWAYS_ASSERT(have_translation);
127-
QLJS_ALWAYS_ASSERT(messages.translate(message_to_translate) ==
128-
message_to_translate.message());
121+
QLJS_ALWAYS_ASSERT(std::strcmp(messages.translate(message_to_translate),
122+
message_to_translate.c_str()) == 0);
129123
}
130124

131125
for (auto _ : state) {
132126
translatable_messages messages;
133-
bool have_translation =
134-
messages.use_messages_from_locale(locale, gmo_files);
127+
bool have_translation = messages.use_messages_from_locale(locale);
135128
::benchmark::DoNotOptimize(have_translation);
136129
::benchmark::DoNotOptimize(messages.translate(message_to_translate));
137130
}

src/CMakeLists.txt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ quick_lint_js_add_library(
6969
file.cpp
7070
global-variables-browser.cpp
7171
global-variables.cpp
72-
gmo.cpp
7372
integer.cpp
7473
json.cpp
7574
language.cpp
@@ -105,7 +104,6 @@ quick_lint_js_add_library(
105104
quick-lint-js/cli-location.h
106105
quick-lint-js/configuration-loader.h
107106
quick-lint-js/configuration.h
108-
quick-lint-js/constant-divider.h
109107
quick-lint-js/cpp.h
110108
quick-lint-js/crash.h
111109
quick-lint-js/diagnostic-formatter.h
@@ -127,7 +125,7 @@ quick_lint_js_add_library(
127125
quick-lint-js/file.h
128126
quick-lint-js/force-inline.h
129127
quick-lint-js/global-variables.h
130-
quick-lint-js/gmo.h
128+
quick-lint-js/hash-fnv.h
131129
quick-lint-js/have.h
132130
quick-lint-js/integer.h
133131
quick-lint-js/json.h
@@ -159,7 +157,8 @@ quick_lint_js_add_library(
159157
quick-lint-js/simdjson.h
160158
quick-lint-js/temporary-directory.h
161159
quick-lint-js/text-error-reporter.h
162-
quick-lint-js/translation-data.h
160+
quick-lint-js/translation-table-generated.h
161+
quick-lint-js/translation-table.h
163162
quick-lint-js/translation.h
164163
quick-lint-js/unreachable.h
165164
quick-lint-js/uri.h
@@ -174,7 +173,7 @@ quick_lint_js_add_library(
174173
simdjson.cpp
175174
temporary-directory.cpp
176175
text-error-reporter.cpp
177-
translation-data.cpp
176+
translation-table-generated.cpp
178177
translation.cpp
179178
uri.cpp
180179
utf-16.cpp

src/diagnostic.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <quick-lint-js/cpp.h>
66
#include <quick-lint-js/diagnostic.h>
77
#include <quick-lint-js/error.h>
8-
#include <quick-lint-js/gmo.h>
98
#include <quick-lint-js/lex.h>
109
#include <quick-lint-js/narrow-cast.h>
1110
#include <utility>
@@ -28,7 +27,7 @@ class diagnostic_info_builder {
2827
// Each of Args must be a diagnostic_message_arg_info.
2928
template <class... Args>
3029
constexpr diagnostic_info_builder add(diagnostic_severity sev,
31-
const gmo_message& message,
30+
const translatable_message& message,
3231
const Args&... arg_infos) {
3332
diagnostic_message_info& message_info =
3433
this->info_.messages[this->current_message_index_++];

0 commit comments

Comments
 (0)