[Bf-blender-cvs] [4ad39964fd2] master: Cycles: Speed up #include expansion algorithm

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


Commit: 4ad39964fd2f7e27ecc42946b421c22794e8f75f
Author: Sergey Sharybin
Date:   Tue Aug 1 20:34:40 2017 +0200
Branches: master
https://developer.blender.org/rB4ad39964fd2f7e27ecc42946b421c22794e8f75f

Cycles: Speed up #include expansion algorithm

The idea is to re-use files which were already processed. Gives about 4x speedup
of processing time (~4.5sec vs 1.0sec) on my laptop for the whole OpenCL kernel.

For users it will mean lower delay before OpenCL rendering might start.

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

M	intern/cycles/util/util_path.cpp

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

diff --git a/intern/cycles/util/util_path.cpp b/intern/cycles/util/util_path.cpp
index f9c3b4bb139..921a9a8915c 100644
--- a/intern/cycles/util/util_path.cpp
+++ b/intern/cycles/util/util_path.cpp
@@ -45,6 +45,7 @@ OIIO_NAMESPACE_USING
 #  include <shlwapi.h>
 #endif
 
+#include "util/util_map.h"
 #include "util/util_windows.h"
 
 CCL_NAMESPACE_BEGIN
@@ -768,15 +769,24 @@ bool path_remove(const string& path)
 	return remove(path.c_str()) == 0;
 }
 
-static string line_directive(const string& base, const string& path, int line)
+struct SourceReplaceState {
+	typedef map<string, string> ProcessedMapping;
+	string base;
+	ProcessedMapping processed_files;
+};
+
+static string line_directive(const SourceReplaceState& state,
+                             const string& path,
+                             const int line)
 {
 	string escaped_path = path;
 	/* First we make path relative. */
-	if(string_startswith(escaped_path, base.c_str())) {
-		const string base_file = path_filename(base);
-		const size_t base_len = base.length();
-		escaped_path = base_file + escaped_path.substr(base_len,
-		                                               escaped_path.length() - base_len);
+	if(string_startswith(escaped_path, state.base.c_str())) {
+		const string base_file = path_filename(state.base);
+		const size_t base_len = state.base.length();
+		escaped_path = base_file +
+		        escaped_path.substr(base_len,
+		                            escaped_path.length() - base_len);
 	}
 	/* Second, we replace all unsafe characters. */
 	string_replace(escaped_path, "\"", "\\\"");
@@ -786,22 +796,29 @@ static string line_directive(const string& base, const string& path, int line)
 	return string_printf("#line %d \"%s\"", line, escaped_path.c_str());
 }
 
+/* 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.
+ */
 static string path_source_replace_includes_recursive(
-        const string& base,
         const string& source,
-        const string& source_filepath)
+        const string& source_filepath,
+        SourceReplaceState *state)
 {
-	/* 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.
+	/* Try to re-use processed file without spending time on replacing all
+	 * include directives again.
 	 */
-
+	SourceReplaceState::ProcessedMapping::iterator replaced_file =
+	        state->processed_files.find(source_filepath);
+	if(replaced_file != state->processed_files.end()) {
+		return replaced_file->second;
+	}
+	/* Perform full file processing.  */
 	string result = "";
 	vector<string> lines;
 	string_split(lines, source, "\n", false);
-
 	for(size_t i = 0; i < lines.size(); ++i) {
-		string line = lines[i];
+		const string& line = lines[i];
 		if(line[0] == '#') {
 			string token = string_strip(line.substr(1, line.size() - 1));
 			if(string_startswith(token, "include")) {
@@ -810,7 +827,7 @@ static string path_source_replace_includes_recursive(
 					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);
-					string filepath = path_join(base, filename);
+					string filepath = path_join(state->base, filename);
 					if(!path_exists(filepath)) {
 						filepath = path_join(path_dirname(source_filepath),
 						                     filename);
@@ -818,18 +835,21 @@ static string path_source_replace_includes_recursive(
 					string text;
 					if(path_read_text(filepath, text)) {
 						text = path_source_replace_includes_recursive(
-						        base, text, filepath);
+						        text, filepath, state);
 						/* Use line directives for better error messages. */
-						line = line_directive(base, filepath, 1)
+						result += line_directive(*state, filepath, 1)
 						     + token.replace(0, n_end + 1, "\n" + text + "\n")
-						     + line_directive(base, source_filepath, i + 1);
+						     + line_directive(*state, source_filepath, i + 1) +
+						     "\n";
+						continue;
 					}
 				}
 			}
 		}
 		result += line + "\n";
 	}
-
+	/* Store result for further reuse. */
+	state->processed_files[source_filepath] = result;
 	return result;
 }
 
@@ -837,10 +857,12 @@ string path_source_replace_includes(const string& source,
                                     const string& path,
                                     const string& source_filename)
 {
+	SourceReplaceState state;
+	state.base = path;
 	return path_source_replace_includes_recursive(
-	        path,
 	        source,
-	        path_join(path, source_filename));
+	        path_join(path, source_filename),
+	        &state);
 }
 
 FILE *path_fopen(const string& path, const string& mode)




More information about the Bf-blender-cvs mailing list