Extend the fast path of fish_wcstod

fish_wcstod had a "fast path" which looked for all digits, otherwise
falling back to wcstod_l. However we now pass the C locale to wcstod_l,
so it is safe to extend the fast path to all ASCII characters.

In practice math parsing would pass strings here like "123 + 456" and
the space and + were knocking us off the fast path. benchmarks/math.fish
goes from 2.3 to 1.4 seconds with this change.
This commit is contained in:
ridiculousfish
2021-07-28 16:12:01 -07:00
parent 32e23c84f4
commit fba86fb821

View File

@@ -711,14 +711,13 @@ unsigned long long fish_wcstoull(const wchar_t *str, const wchar_t **endptr, int
/// Like wcstod(), but wcstod() is enormously expensive on some platforms so this tries to have a
/// fast path.
double fish_wcstod(const wchar_t *str, wchar_t **endptr) {
// The "fast path." If we're all ASCII and we fit inline, use strtod().
// The "fast path." If we're all ASCII, use strtod().
char narrow[128];
size_t len = std::wcslen(str);
size_t len_plus_0 = 1 + len;
auto is_digit = [](wchar_t c) { return '0' <= c && c <= '9'; };
if (len_plus_0 <= sizeof narrow && std::all_of(str, str + len, is_digit)) {
auto is_ascii = [](wchar_t c) { return 0 <= c && c <= 127; };
if (len_plus_0 <= sizeof narrow && std::all_of(str, str + len, is_ascii)) {
// Fast path. Copy the string into a local buffer and run strtod() on it.
// We can ignore the locale-taking version because we are limited to ASCII digits.
std::copy(str, str + len_plus_0, narrow);
char *narrow_endptr = nullptr;
double ret = strtod(narrow, endptr ? &narrow_endptr : nullptr);