feat: speed up javascript munging
Perform a single pass so the work of doing `m` replacements in a string of length `n` is O(m + n) instead of O(m * n) For the yogalogy template this change improves the script munging step from ~2.5ms to 0.5ms [release] (from ~17ms to 3ms [debug]).
This commit is contained in:
parent
028cc115a0
commit
cc4c1cf9d5
4 changed files with 186 additions and 185 deletions
|
|
@ -1,71 +1,73 @@
|
|||
use aho_corasick::{AhoCorasick, AhoCorasickBuilder};
|
||||
|
||||
// TODO figure out why this code takes ~70ms to munge the javascript. By comparison just writing a
|
||||
// bunch of chainged string.replace( , ).replace( , ).replace .... takes about 16ms.
|
||||
let mut patterns = Vec::new();
|
||||
let mut replace_with = Vec::new();
|
||||
|
||||
patterns.push("'REPLACE_ME_WITH_JSON_STRINGIFY'");
|
||||
replace_with.push("JSON.stringify(x)");
|
||||
|
||||
patterns.push("$elm$json$Json$Decode$fail('REPLACE_ME_WITH_BYTES_DECODER');");
|
||||
replace_with.push(r#"
|
||||
_Json_decodePrim(function(value) {
|
||||
return (typeof value === 'object' && value instanceof DataView)
|
||||
? $elm$core$Result$Ok(value)
|
||||
: _Json_expecting('a DataView', value);
|
||||
});
|
||||
"#);
|
||||
|
||||
patterns.push(";}(this));");
|
||||
replace_with.push(";}(globalThis));");
|
||||
|
||||
|
||||
// let mut final_script = data
|
||||
|
||||
if sqlite_path.is_some() {
|
||||
patterns.push("var $author$project$Astrid$Query$execute = function (query) {\n\treturn $author$project$Astrid$Query$dummyExecute;\n};");
|
||||
replace_with.push(include_str!("fixtures/sql-client-integration.js"));
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$fetch = F3(\n\tfunction (sql, parameters, decoder) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push("var $author$project$Astrid$Query$fetch = _Query_fetchAll;");
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$fetchOne = F3(\n\tfunction (sql, parameters, decoder) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push("var $author$project$Astrid$Query$fetchOne = _Query_fetchOne;");
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$map5 = F6(\n\tfunction (f, a, b, c, d, e) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push(r#"var $author$project$Astrid$Query$map5 = _Query_map5;"#);
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$map4 = F5(\n\tfunction (f, a, b, c, d) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push(r#"var $author$project$Astrid$Query$map4 = _Query_map4;"#);
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$map3 = F4(\n\tfunction (f, a, b, c) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push(r#"var $author$project$Astrid$Query$map3 = _Query_map3;"#);
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$map2 = F3(\n\tfunction (f, a, b) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push(r#"var $author$project$Astrid$Query$map2 = _Query_map2;"#);
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$map = F2(\n\tfunction (f, a) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push(r#"var $author$project$Astrid$Query$map = _Query_map1;"#);
|
||||
|
||||
patterns.push("var $author$project$Astrid$Query$andThen = F2(\n\tfunction (f, q) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
replace_with.push(r#"var $author$project$Astrid$Query$andThen = _Query_andThen;"#);
|
||||
}
|
||||
debug_assert!(patterns.len() == replace_with.len());
|
||||
|
||||
// let mut final_script = Vec::with_capacity(data.len() + 8 * 1024);
|
||||
|
||||
let span = info_span!("build aho-corasick patterns");
|
||||
let timing_guard = span.enter();
|
||||
//let ac = AhoCorasick::new(&patterns);
|
||||
let ac = AhoCorasickBuilder::new()
|
||||
.auto_configure(&patterns)
|
||||
.build(&patterns);
|
||||
drop(timing_guard);
|
||||
let span = info_span!("run replacements");
|
||||
let timing_guard = span.enter();
|
||||
for _ in ac.find_iter(data.as_bytes()) {
|
||||
|
||||
}
|
||||
drop(timing_guard);
|
||||
let mut final_script = ac.replace_all_bytes(data.as_bytes(), &replace_with);
|
||||
// bunch of chainged string.replace( , ).replace( , ).replace .... takes about (16ms debug) (2.5ms
|
||||
// release).
|
||||
// There has to be a faster way to do all of this.
|
||||
// let mut patterns = Vec::new();
|
||||
// let mut replace_with = Vec::new();
|
||||
//
|
||||
// patterns.push("'REPLACE_ME_WITH_JSON_STRINGIFY'");
|
||||
// replace_with.push("JSON.stringify(x)");
|
||||
//
|
||||
// patterns.push("$elm$json$Json$Decode$fail('REPLACE_ME_WITH_BYTES_DECODER');");
|
||||
// replace_with.push(r#"
|
||||
// _Json_decodePrim(function(value) {
|
||||
// return (typeof value === 'object' && value instanceof DataView)
|
||||
// ? $elm$core$Result$Ok(value)
|
||||
// : _Json_expecting('a DataView', value);
|
||||
// });
|
||||
// "#);
|
||||
//
|
||||
// patterns.push(";}(this));");
|
||||
// replace_with.push(";}(globalThis));");
|
||||
//
|
||||
//
|
||||
// // let mut final_script = data
|
||||
//
|
||||
// if sqlite_path.is_some() {
|
||||
// patterns.push("var $author$project$Astrid$Query$execute = function (query) {\n\treturn $author$project$Astrid$Query$dummyExecute;\n};");
|
||||
// replace_with.push(include_str!("fixtures/sql-client-integration.js"));
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$fetch = F3(\n\tfunction (sql, parameters, decoder) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push("var $author$project$Astrid$Query$fetch = _Query_fetchAll;");
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$fetchOne = F3(\n\tfunction (sql, parameters, decoder) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push("var $author$project$Astrid$Query$fetchOne = _Query_fetchOne;");
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$map5 = F6(\n\tfunction (f, a, b, c, d, e) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push(r#"var $author$project$Astrid$Query$map5 = _Query_map5;"#);
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$map4 = F5(\n\tfunction (f, a, b, c, d) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push(r#"var $author$project$Astrid$Query$map4 = _Query_map4;"#);
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$map3 = F4(\n\tfunction (f, a, b, c) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push(r#"var $author$project$Astrid$Query$map3 = _Query_map3;"#);
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$map2 = F3(\n\tfunction (f, a, b) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push(r#"var $author$project$Astrid$Query$map2 = _Query_map2;"#);
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$map = F2(\n\tfunction (f, a) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push(r#"var $author$project$Astrid$Query$map = _Query_map1;"#);
|
||||
//
|
||||
// patterns.push("var $author$project$Astrid$Query$andThen = F2(\n\tfunction (f, q) {\n\t\treturn $author$project$Astrid$Query$Dummy;\n\t});");
|
||||
// replace_with.push(r#"var $author$project$Astrid$Query$andThen = _Query_andThen;"#);
|
||||
// }
|
||||
// debug_assert!(patterns.len() == replace_with.len());
|
||||
//
|
||||
// // let mut final_script = Vec::with_capacity(data.len() + 8 * 1024);
|
||||
//
|
||||
// let span = info_span!("build aho-corasick patterns");
|
||||
// let timing_guard = span.enter();
|
||||
// //let ac = AhoCorasick::new(&patterns);
|
||||
// let ac = AhoCorasickBuilder::new()
|
||||
// .auto_configure(&patterns)
|
||||
// .build(&patterns);
|
||||
// drop(timing_guard);
|
||||
// let span = info_span!("run replacements");
|
||||
// let timing_guard = span.enter();
|
||||
// for _ in ac.find_iter(data.as_bytes()) {
|
||||
//
|
||||
// }
|
||||
// drop(timing_guard);
|
||||
// let mut final_script = ac.replace_all_bytes(data.as_bytes(), &replace_with);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue