diff --git a/CHANGELOG.md b/CHANGELOG.md index 855c0c91b..4f9a74855 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.22.5 + +### JavaScript API + +* Improve performance for logic-heavy stylesheets. + ## 1.22.4 * Fix a bug where at-rules imported from within a style rule would appear within diff --git a/lib/src/utils.dart b/lib/src/utils.dart index aecde2f6b..5bf5e60a6 100644 --- a/lib/src/utils.dart +++ b/lib/src/utils.dart @@ -306,7 +306,11 @@ bool startsWithIgnoreSeparator(String string, String prefix) { /// If [source] is passed, copies it into the map. Map normalizedMap([Map source]) { var map = LinkedHashMap( - equals: equalsIgnoreSeparator, hashCode: hashCodeIgnoreSeparator); + // Explicitly set this because the default implementation involves a type + // check, which is very expensive in dart2js. + isValidKey: (_) => true, + equals: equalsIgnoreSeparator, + hashCode: hashCodeIgnoreSeparator); if (source != null) map.addAll(source); return map; } @@ -316,7 +320,11 @@ Map normalizedMap([Map source]) { /// If [source] is passed, copies it into the set. Set normalizedSet([Iterable source]) { var set = LinkedHashSet( - equals: equalsIgnoreSeparator, hashCode: hashCodeIgnoreSeparator); + // Explicitly set this because the default implementation involves a type + // check, which is very expensive in dart2js. + isValidKey: (_) => true, + equals: equalsIgnoreSeparator, + hashCode: hashCodeIgnoreSeparator); if (source != null) set.addAll(source); return set; } diff --git a/lib/src/visitor/async_evaluate.dart b/lib/src/visitor/async_evaluate.dart index 40e111e42..ff1b6320e 100644 --- a/lib/src/visitor/async_evaluate.dart +++ b/lib/src/visitor/async_evaluate.dart @@ -1962,15 +1962,19 @@ class _EvaluateVisitor {bool trackSpans}) async { trackSpans ??= _sourceMap; - var positional = (await mapAsync(arguments.positional, - (Expression expression) => expression.accept(this))) - .toList(); + var positional = [ + for (var expression in arguments.positional) await expression.accept(this) + ]; var named = await normalizedMapMapAsync( arguments.named, value: (_, expression) => expression.accept(this)); - var positionalNodes = - trackSpans ? arguments.positional.map(_expressionNode).toList() : null; + var positionalNodes = trackSpans + ? [ + for (var expression in arguments.positional) + _expressionNode(expression) + ] + : null; var namedNodes = trackSpans ? mapMap(arguments.named, value: (_, expression) => _expressionNode(expression)) diff --git a/lib/src/visitor/evaluate.dart b/lib/src/visitor/evaluate.dart index fcd07f9ae..7e1420531 100644 --- a/lib/src/visitor/evaluate.dart +++ b/lib/src/visitor/evaluate.dart @@ -5,7 +5,7 @@ // DO NOT EDIT. This file was generated from async_evaluate.dart. // See tool/grind/synchronize.dart for details. // -// Checksum: cae91fd0fcd94fbb45712286a85761d69fef5415 +// Checksum: 1685f0e62002cbb13d3d54ea3d5166c4c7f8f678 // // ignore_for_file: unused_import @@ -1949,14 +1949,18 @@ class _EvaluateVisitor {bool trackSpans}) { trackSpans ??= _sourceMap; - var positional = arguments.positional - .map((Expression expression) => expression.accept(this)) - .toList(); + var positional = [ + for (var expression in arguments.positional) expression.accept(this) + ]; var named = normalizedMapMap(arguments.named, value: (_, expression) => expression.accept(this)); - var positionalNodes = - trackSpans ? arguments.positional.map(_expressionNode).toList() : null; + var positionalNodes = trackSpans + ? [ + for (var expression in arguments.positional) + _expressionNode(expression) + ] + : null; var namedNodes = trackSpans ? mapMap(arguments.named, value: (_, expression) => _expressionNode(expression)) diff --git a/perf.md b/perf.md index 4986a35d3..96f7f7034 100644 --- a/perf.md +++ b/perf.md @@ -4,7 +4,7 @@ the benefit Dart Sass could provide relative to other implementations. This was tested against: * libsass 0f3d6ad1 and sassc 4674821 compiled with g++ (Debian 7.3.0-18) 7.3.0. -* Dart Sass 088fc28 on Dart 2.4.0 and Node v12.0.0. +* Dart Sass 50a45a7 on Dart 2.4.0 and Node v12.0.0. * Ruby Sass 8d1edc76 on ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]. on Debian x64 with Intel Xeon E5-1650 v3 @ 3.50GHz. The Dart Sass @@ -20,148 +20,149 @@ I ran five instances of each configuration and recorded the fastest time. Running on a file containing 4 instances of `.foo {a: b}`: -* sassc: 0.004s -* Dart Sass from a script snapshot: 0.219s -* Dart Sass native executable: 0.020s -* Dart Sass on Node.js: 0.200s -* Ruby Sass with a hot cache: 0.155s +* sassc: 0.005s +* Dart Sass from a script snapshot: 0.216s +* Dart Sass native executable: 0.018s +* Dart Sass on Node.js: 0.209s +* Ruby Sass with a hot cache: 0.148s Based on these numbers, Dart Sass from a native executable is approximately: -* 5.0x slower than libsass -* 10.0x faster than Dart Sass on Node -* 7.8x faster than Ruby Sass +* 3.6x slower than libsass +* 11.6x faster than Dart Sass on Node +* 8.2x faster than Ruby Sass ## Large Plain CSS Running on a file containing 2^17 instances of `.foo {a: b}`: -* sassc: 1.714s -* Dart Sass from a script snapshot: 1.606s -* Dart Sass native executable: 1.547s -* Dart Sass on Node.js: 2.672s -* Ruby Sass with a hot cache: 11.145s +* sassc: 1.705s +* Dart Sass from a script snapshot: 1.550s +* Dart Sass native executable: 1.518s +* Dart Sass on Node.js: 2.765s +* Ruby Sass with a hot cache: 10.965s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x faster than libsass -* 1.7x faster than Dart Sass on Node +* 1.8x faster than Dart Sass on Node * 7.2x faster than Ruby Sass ## Preceding Sparse `@extend` Running on a file containing `.x {@extend .y}`, 2^17 instances of `.foo {a: b}`, and then `.y {a: b}`: -* sassc: 1.750s -* Dart Sass from a script snapshot: 1.602s -* Dart Sass native executable: 1.585s -* Dart Sass on Node.js: 2.782s -* Ruby Sass with a hot cache: 17.012s +* sassc: 1.712s +* Dart Sass from a script snapshot: 1.613s +* Dart Sass native executable: 1.582s +* Dart Sass on Node.js: 2.739s +* Ruby Sass with a hot cache: 16.472s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x faster than libsass -* 1.8x faster than Dart Sass on Node -* 10.7x faster than Ruby Sass +* 1.7x faster than Dart Sass on Node +* 10.4x faster than Ruby Sass ## Following Sparse `@extend` Running on a file containing `.y {a: b}`, 2^17 instances of `.foo {a: b}`, and then `.x {@extend .y}`: -* sassc: 1.724s -* Dart Sass from a script snapshot: 1.610s -* Dart Sass native executable: 1.568s -* Dart Sass on Node.js: 2.712s -* Ruby Sass with a hot cache: 16.670s +* sassc: 1.701s +* Dart Sass from a script snapshot: 1.568s +* Dart Sass native executable: 1.543s +* Dart Sass on Node.js: 2.821s +* Ruby Sass with a hot cache: 16.469s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x faster than libsass -* 1.7x faster than Dart Sass on Node -* 10.6x faster than Ruby Sass +* 1.8x faster than Dart Sass on Node +* 10.7x faster than Ruby Sass ## Preceding Dense `@extend` Running on a file containing `.bar {@extend .foo}` followed by 2^17 instances of `.foo {a: b}`: -* sassc: 2.290s -* Dart Sass from a script snapshot: 2.476s -* Dart Sass native executable: 2.566s -* Dart Sass on Node.js: 5.399s -* Ruby Sass with a hot cache: 29.002s +* sassc: 2.260s +* Dart Sass from a script snapshot: 2.405s +* Dart Sass native executable: 2.526s +* Dart Sass on Node.js: 5.612s +* Ruby Sass with a hot cache: 28.690s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x slower than libsass -* 2.1x faster than Dart Sass on Node -* 11.3x faster than Ruby Sass +* 2.2x faster than Dart Sass on Node +* 11.4x faster than Ruby Sass ## Following Dense `@extend` Running on a file containing 2^17 instances of `.foo {a: b}` followed by `.bar {@extend .foo}`: -* sassc: 2.317s -* Dart Sass from a script snapshot: 2.381s -* Dart Sass native executable: 2.461s -* Dart Sass on Node.js: 5.481s -* Ruby Sass with a hot cache: 29.197s +* sassc: 2.289s +* Dart Sass from a script snapshot: 2.396s +* Dart Sass native executable: 2.457s +* Dart Sass on Node.js: 6.319s +* Ruby Sass with a hot cache: 28.708s Based on these numbers, Dart Sass from a native executable is approximately: * 1.1x slower than libsass -* 2.2x faster than Dart Sass on Node -* 11.9x faster than Ruby Sass +* 2.6x faster than Dart Sass on Node +* 11.7x faster than Ruby Sass ## Bootstrap Running on a file containing 16 instances of importing the Bootstrap framework: -* sassc: 0.763s -* Dart Sass from a script snapshot: 1.613s -* Dart Sass native executable: 0.992s -* Dart Sass on Node.js: 3.529s -* Ruby Sass with a hot cache: 12.969s +* sassc: 0.767s +* Dart Sass from a script snapshot: 1.534s +* Dart Sass native executable: 0.955s +* Dart Sass on Node.js: 3.156s +* Ruby Sass with a hot cache: 12.521s Based on these numbers, Dart Sass from a native executable is approximately: -* 1.3x slower than libsass -* 3.6x faster than Dart Sass on Node +* 1.2x slower than libsass +* 3.3x faster than Dart Sass on Node * 13.1x faster than Ruby Sass ## a11ycolor Running on a file containing test cases for a computation-intensive color-processing library: -* sassc: 0.262s -* Dart Sass from a script snapshot: 0.805s -* Dart Sass native executable: 0.612s -* Dart Sass on Node.js: 1.876s -* Ruby Sass with a hot cache: 5.396s +* sassc: 0.248s +* Dart Sass from a script snapshot: 0.736s +* Dart Sass native executable: 0.565s +* Dart Sass on Node.js: 1.043s +* Ruby Sass with a hot cache: 5.091s Based on these numbers, Dart Sass from a native executable is approximately: * 2.3x slower than libsass -* 3.1x faster than Dart Sass on Node -* 8.8x faster than Ruby Sass +* 1.8x faster than Dart Sass on Node +* 9.0x faster than Ruby Sass ## Susy Running on a file containing test cases for the computation-intensive Susy grid framework: -* sassc: 0.244s +* sassc: 0.248s * Dart Sass from a script snapshot: 0.673s -* Dart Sass native executable: 0.248s -* Dart Sass on Node.js: 1.361s -* Ruby Sass with a hot cache: 1.576s +* Dart Sass native executable: 0.237s +* Dart Sass on Node.js: 0.990s +* Ruby Sass with a hot cache: 1.527s Based on these numbers, Dart Sass from a native executable is approximately: * identical to libsass -* 5.5x faster than Dart Sass on Node +* 4.2x faster than Dart Sass on Node * 6.4x faster than Ruby Sass # Prior Measurements +* [1.22.4](https://github.com/sass/dart-sass/blob/a7172a2b1dd48b339e5d57159ed364ffb9f5812e/perf.md). * [1.20.2](https://github.com/sass/dart-sass/blob/4b7699291c9f69533d25980d23b0647266b665f2/perf.md). * [1.13.4](https://github.com/sass/dart-sass/blob/b6ccc91a138e75420227ff79381c5f70e60254f1/perf.md). * [1.6.0](https://github.com/sass/dart-sass/blob/048cbe197a77e1cf4b837a40a5acb737e949fd5c/perf.md). diff --git a/pubspec.yaml b/pubspec.yaml index 0d52a7fa5..a4b51b534 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ name: sass -version: 1.22.4 +version: 1.22.5 description: A Sass implementation in Dart. author: Dart Team homepage: https://github.com/sass/dart-sass diff --git a/tool/grind/npm.dart b/tool/grind/npm.dart index 1b77d9cca..8ab71e44f 100644 --- a/tool/grind/npm.dart +++ b/tool/grind/npm.dart @@ -40,7 +40,10 @@ void _js({@required bool release}) { // * We expect our test coverage to ensure that nothing throws subtypes of // Error. // * We thoroughly test edge cases in user input. - if (release) ...["-O4", "--fast-startup"] + // + // We don't minify because download size isn't especially important + // server-side and it's nice to get readable stack traces from bug reports. + if (release) ...["-O4", "--no-minify", "--fast-startup"] ]); var text = destination .readAsStringSync()