From b9340f50c26e904aeae73f15164b84c381a4158e Mon Sep 17 00:00:00 2001 From: Bnyro Date: Thu, 21 May 2026 21:15:09 +0200 Subject: [PATCH] [fix] preferences: opening preferences page is very slow (multiple seconds on bad hardware) (#6090) I've been profiling the `/preferences` endpoint using werkzeug's `ProfilerMiddleware` (i.e. just do `app.wsgi_app = ProfilerMiddleware(app.wsgi_app)`) and look at the outputs in the terminal when doing `make run`. It turns out that 95%+ of the time spent were inside babel's Locale parsing (> 700ms on my machine). That's because, when opening the settings, we loaded the full engine traits of each engine and checked if it matches the user-defined search language. As we have 250+ engines, and babel is very slow when parsing Locale's, this took a very long time. By removing this feature that shows whether the selected search language is supported by the engine, the load time went down from 800ms to 50ms on my machine (which is still very slow, but well, that's future work on optimizing). --- searx/enginelib/traits.py | 13 ------------- searx/templates/simple/preferences/engines.html | 4 ---- searx/webapp.py | 13 ++----------- 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/searx/enginelib/traits.py b/searx/enginelib/traits.py index 257734dd9..4a051ac05 100644 --- a/searx/enginelib/traits.py +++ b/searx/enginelib/traits.py @@ -116,19 +116,6 @@ class EngineTraits: return self.all_locale return locales.get_engine_locale(searxng_locale, self.regions, default=default) - def is_locale_supported(self, searxng_locale: str) -> bool: - """A *locale* (SearXNG's internal representation) is considered to be - supported by the engine if the *region* or the *language* is supported - by the engine. - - For verification the functions :py:func:`EngineTraits.get_region` and - :py:func:`EngineTraits.get_language` are used. - """ - if self.data_type == "traits_v1": - return bool(self.get_region(searxng_locale) or self.get_language(searxng_locale)) - - raise TypeError("engine traits of type %s is unknown" % self.data_type) - def copy(self): """Create a copy of the dataclass object.""" return EngineTraits(**dataclasses.asdict(self)) diff --git a/searx/templates/simple/preferences/engines.html b/searx/templates/simple/preferences/engines.html index 09d2aed77..977fe9669 100644 --- a/searx/templates/simple/preferences/engines.html +++ b/searx/templates/simple/preferences/engines.html @@ -23,7 +23,6 @@ {{- _("Allow") -}}{{- '' -}} {{- _("Engine name") -}}{{- '' -}} {{ _("!bang") -}}{{- '' -}} - {{- _("Supports selected language") -}}{{- '' -}} {{- _("SafeSearch") -}}{{- '' -}} {{- _("Time range") -}}{{- '' -}} {{- _("Weight") }} @@ -70,9 +69,6 @@ {{- '' -}} {{ '!' + shortcuts[search_engine.name] }}{{- '' -}} {{- '' -}} - - {{- checkbox(None, supports[search_engine.name]['supports_selected_language'], true) -}} - {{- '' -}} {{- checkbox(None, supports[search_engine.name]['safesearch'], true) -}} {{- '' -}} diff --git a/searx/webapp.py b/searx/webapp.py index b0820c753..f5e8e5cf3 100755 --- a/searx/webapp.py +++ b/searx/webapp.py @@ -918,9 +918,6 @@ def preferences(): 'rate80': rate80, 'rate95': rate95, 'warn_timeout': e.timeout > settings['outgoing']['request_timeout'], - 'supports_selected_language': e.traits.is_locale_supported( - str(sxng_request.preferences.get_value('language') or 'all') - ), 'result_count': result_count, } # end of stats @@ -956,15 +953,9 @@ def preferences(): # supports supports = {} for _, e in filtered_engines.items(): - supports_selected_language = e.traits.is_locale_supported( - str(sxng_request.preferences.get_value('language') or 'all') - ) - safesearch = e.safesearch - time_range_support = e.time_range_support supports[e.name] = { - 'supports_selected_language': supports_selected_language, - 'safesearch': safesearch, - 'time_range_support': time_range_support, + 'safesearch': e.safesearch, + 'time_range_support': e.time_range_support, } return render(