Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Sharybin <sergey.vfx@gmail.com>2017-08-02 21:23:14 +0300
committerSergey Sharybin <sergey.vfx@gmail.com>2017-08-02 21:59:19 +0300
commitf879cac03263be6fb18efdd1aef4f0fd96a568aa (patch)
treea62f43b76e21502c37ea51b045039411f3201d97 /intern/cycles
parenta280697e77be984021cdf3181a396f34529f933d (diff)
Cycles: Avoid some expensive operations in header expansions
Basically gather lines as-is during traversal, avoiding allocating memory for all the lines in headers. Brings additional performance improvement abut 20%.
Diffstat (limited to 'intern/cycles')
-rw-r--r--intern/cycles/util/util_path.cpp117
1 files changed, 82 insertions, 35 deletions
diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index 22b407ce926..c2bff61ada7 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -771,12 +771,21 @@ bool path_remove(const string& path)
struct SourceReplaceState {
typedef map<string, string> ProcessedMapping;
-
+ /* Base director for all relative include headers. */
string base;
+ /* Result of processed files. */
ProcessedMapping processed_files;
+ /* Set of files which are considered "precompiled" and which are replaced
+ * with and empty string on a subsequent occurrence in include statement.
+ */
set<string> precompiled_headers;
};
+static string path_source_replace_includes_recursive(
+ const string& source,
+ const string& source_filepath,
+ SourceReplaceState *state);
+
static string line_directive(const SourceReplaceState& state,
const string& path,
const int line)
@@ -798,6 +807,44 @@ static string line_directive(const SourceReplaceState& state,
return string_printf("#line %d \"%s\"", line, escaped_path.c_str());
}
+static string path_source_handle_preprocessor(
+ const string& preprocessor_line,
+ const string& source_filepath,
+ const size_t line_number,
+ SourceReplaceState *state)
+{
+ string result = preprocessor_line;
+ string token = string_strip(
+ preprocessor_line.substr(1, preprocessor_line.size() - 1));
+ if(string_startswith(token, "include")) {
+ token = string_strip(token.substr(7, token.size() - 7));
+ if(token[0] == '"') {
+ const size_t n_start = 1;
+ const size_t n_end = token.find("\"", n_start);
+ const string filename = token.substr(n_start, n_end - n_start);
+ const bool is_precompiled = string_endswith(token, "// PRECOMPILED");
+ string filepath = path_join(state->base, filename);
+ if(!path_exists(filepath)) {
+ filepath = path_join(path_dirname(source_filepath),
+ filename);
+ }
+ if(is_precompiled) {
+ state->precompiled_headers.insert(filepath);
+ }
+ string text;
+ if(path_read_text(filepath, text)) {
+ text = path_source_replace_includes_recursive(
+ text, filepath, state);
+ /* Use line directives for better error messages. */
+ result = line_directive(*state, filepath, 1) + "\n"
+ + text + "\n"
+ + line_directive(*state, source_filepath, line_number + 1);
+ }
+ }
+ }
+ return result;
+}
+
/* Our own little c preprocessor that replaces #includes with the file
* contents, to work around issue of OpenCL drivers not supporting
* include paths with spaces in them.
@@ -821,42 +868,42 @@ static string path_source_replace_includes_recursive(
}
/* Perform full file processing. */
string result = "";
- vector<string> lines;
- string_split(lines, source, "\n", false);
- for(size_t i = 0; i < lines.size(); ++i) {
- const string& line = lines[i];
- if(line[0] == '#') {
- string token = string_strip(line.substr(1, line.size() - 1));
- if(string_startswith(token, "include")) {
- token = string_strip(token.substr(7, token.size() - 7));
- if(token[0] == '"') {
- const size_t n_start = 1;
- const size_t n_end = token.find("\"", n_start);
- const string filename = token.substr(n_start, n_end - n_start);
- const bool is_precompiled = string_endswith(token, "// PRECOMPILED");
- string filepath = path_join(state->base, filename);
- if(!path_exists(filepath)) {
- filepath = path_join(path_dirname(source_filepath),
- filename);
- }
- if(is_precompiled) {
- state->precompiled_headers.insert(filepath);
- }
- string text;
- if(path_read_text(filepath, text)) {
- text = path_source_replace_includes_recursive(
- text, filepath, state);
- /* Use line directives for better error messages. */
- result += line_directive(*state, filepath, 1)
- + token.replace(0, n_end + 1, "\n" + text + "\n")
- + line_directive(*state, source_filepath, i + 1) +
- "\n";
- continue;
- }
- }
+ const size_t source_length = source.length();
+ size_t index = 0;
+ size_t line_number = 0, column_number = 1;
+ bool inside_preprocessor = false;
+ string preprocessor_line = "";
+ while(index < source_length) {
+ const char ch = source[index];
+ if(ch == '\n') {
+ if(inside_preprocessor) {
+ result += path_source_handle_preprocessor(preprocessor_line,
+ source_filepath,
+ line_number,
+ state);
}
+ inside_preprocessor = false;
+ preprocessor_line = "";
+ column_number = 0;
+ ++line_number;
}
- result += line + "\n";
+ else if(ch == '#' && column_number == 1) {
+ inside_preprocessor = true;
+ }
+ if(inside_preprocessor) {
+ preprocessor_line += ch;
+ }
+ else {
+ result += ch;
+ }
+ ++index;
+ ++column_number;
+ }
+ if(inside_preprocessor) {
+ result += path_source_handle_preprocessor(preprocessor_line,
+ source_filepath,
+ line_number,
+ state);
}
/* Store result for further reuse. */
state->processed_files[source_filepath] = result;