diff options
author | Aras Pranckevicius <aras@nesnausk.org> | 2022-05-12 13:48:55 +0300 |
---|---|---|
committer | Aras Pranckevicius <aras@nesnausk.org> | 2022-05-12 13:49:05 +0300 |
commit | 9757b4efb12e0fba21735fa7960148e6a7b67bb2 (patch) | |
tree | f10d73e9d57b840fe20131a069b75171d6d2fe17 /source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh | |
parent | 207b0c2a0f792375ea7a3087823af41621ececd2 (diff) |
OBJ: improve new importer file parsing performance on windows
The OBJ parser was primarily using StringRef for convenience, with
functions like "skip whitespace" or "parse a number" taking an input
stringref, representing an input line, and returning a new stringref,
representing the remainder of the line. This is convenient, but does
more work than strictly needed -- while parsing, only the "beginning"
of the line ever changes by moving forward; the end of the line
always stays the same. We can change the code to take a pair of
pointers (begin of line, end of line) as input, and make the
functions return the new begin of line pointer. This makes the return
value neatly fit into a processor register, which StringRef did not.
On Windows, this does result in non-trivial speedups in the actual
OBJ file parsing part, due to Windows calling convention where return
values larger than 64 bits are returned via memory. Does not
measurably affect performance on Mac/Linux, because the calling
convention there uses a pair of 64-bit registers to return a
StringRef.
End-to-end times of importing several test files, on Windows
(VS2022 build, Ryzen 5950X):
- Monkey subdivided to level 6, no normals (220MB file): 1.25s -> 0.85s
- Rungholt minecraft level (270MB file): 7.0s -> 5.8s
- Blender 3 splash scene (2.4GB file): 49.1s -> 45.5s
The full import process has a lot of other overhead besides actual
OBJ file parsing (mostly creating actual blender objects out of
parsed data). In pure parsing, in the monkey test scene above, the
parsing part goes 1.0s -> 0.6s.
Reviewed By: Howard Trickey
Differential Revision: https://developer.blender.org/D14936
Diffstat (limited to 'source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh')
-rw-r--r-- | source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh | 30 |
1 files changed, 20 insertions, 10 deletions
diff --git a/source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh b/source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh index 532224569ac..3f428b1ab5c 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh +++ b/source/blender/io/wavefront_obj/importer/obj_import_string_utils.hh @@ -9,6 +9,14 @@ * The utilities are not directly usable by other formats, since * they treat backslash (\) as a whitespace character (OBJ format * allows backslashes to function as a line-continuation character). + * + * Many of these functions take two pointers (p, end) indicating + * which part of a string to operate on, and return a possibly + * changed new start of the string. They could be taking a StringRef + * as input and returning a new StringRef, but this is a hot path + * in OBJ parsing, and the StringRef approach does lose performance + * (mostly due to return of StringRef being two register-size values + * instead of just one pointer). */ namespace blender::io::obj { @@ -26,16 +34,16 @@ namespace blender::io::obj { StringRef read_next_line(StringRef &buffer); /** - * Drop leading white-space from a StringRef. + * Drop leading white-space from a string part. * Note that backslash character is considered white-space. */ -StringRef drop_whitespace(StringRef str); +const char *drop_whitespace(const char *p, const char *end); /** - * Drop leading non-white-space from a StringRef. + * Drop leading non-white-space from a string part. * Note that backslash character is considered white-space. */ -StringRef drop_non_whitespace(StringRef str); +const char *drop_non_whitespace(const char *p, const char *end); /** * Parse an integer from an input string. @@ -44,9 +52,10 @@ StringRef drop_non_whitespace(StringRef str); * number can't be parsed (invalid syntax, out of range), * `fallback` value is stored instead. * - * Returns the remainder of the input string after parsing. + * Returns the start of remainder of the input string after parsing. */ -StringRef parse_int(StringRef str, int fallback, int &dst, bool skip_space = true); +const char *parse_int( + const char *p, const char *end, int fallback, int &dst, bool skip_space = true); /** * Parse a float from an input string. @@ -55,9 +64,10 @@ StringRef parse_int(StringRef str, int fallback, int &dst, bool skip_space = tru * number can't be parsed (invalid syntax, out of range), * `fallback` value is stored instead. * - * Returns the remainder of the input string after parsing. + * Returns the start of remainder of the input string after parsing. */ -StringRef parse_float(StringRef str, float fallback, float &dst, bool skip_space = true); +const char *parse_float( + const char *p, const char *end, float fallback, float &dst, bool skip_space = true); /** * Parse a number of white-space separated floats from an input string. @@ -65,8 +75,8 @@ StringRef parse_float(StringRef str, float fallback, float &dst, bool skip_space * number can't be parsed (invalid syntax, out of range), * `fallback` value is stored instead. * - * Returns the remainder of the input string after parsing. + * Returns the start of remainder of the input string after parsing. */ -StringRef parse_floats(StringRef str, float fallback, float *dst, int count); +const char *parse_floats(const char *p, const char *end, float fallback, float *dst, int count); } // namespace blender::io::obj |