[Bf-blender-cvs] [f879cac0326] master: Cycles: Avoid some expensive operations in header expansions

Sergey Sharybin noreply at git.blender.org
Wed Aug 2 21:13:42 CEST 2017


Commit: f879cac03263be6fb18efdd1aef4f0fd96a568aa
Author: Sergey Sharybin
Date:   Wed Aug 2 20:23:14 2017 +0200
Branches: master
https://developer.blender.org/rBf879cac03263be6fb18efdd1aef4f0fd96a568aa

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%.

===================================================================

M	intern/cycles/util/util_path.cpp

===================================================================

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;




More information about the Bf-blender-cvs mailing list