Skip to content

Commit

Permalink
Speed up first asset load by encoding asset manifest in binary rather…
Browse files Browse the repository at this point in the history
… than JSON (#113637)
  • Loading branch information
andrewkolos committed Dec 5, 2022
1 parent d52e2de commit 56cad89
Show file tree
Hide file tree
Showing 14 changed files with 2,077 additions and 919 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// found in the LICENSE file.

import 'dart:convert';
import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart' show PlatformAssetBundle;
import 'package:flutter/services.dart' show PlatformAssetBundle, StandardMessageCodec;
import 'package:flutter/widgets.dart';

import '../common.dart';
Expand All @@ -18,16 +18,14 @@ void main() async {
final BenchmarkResultPrinter printer = BenchmarkResultPrinter();
WidgetsFlutterBinding.ensureInitialized();
final Stopwatch watch = Stopwatch();
final PlatformAssetBundle bundle = PlatformAssetBundle();

final ByteData assetManifestBytes = await bundle.load('money_asset_manifest.json');
final ByteData assetManifest = await loadAssetManifest();

watch.start();
for (int i = 0; i < _kNumIterations; i++) {
bundle.clear();
final String json = utf8.decode(assetManifestBytes.buffer.asUint8List());
// This is a test, so we don't need to worry about this rule.
// This is effectively a test.
// ignore: invalid_use_of_visible_for_testing_member
await AssetImage.manifestParser(json);
AssetImage.parseAssetManifest(assetManifest);
}
watch.stop();

Expand All @@ -40,3 +38,49 @@ void main() async {

printer.printToStdout();
}

final RegExp _extractRatioRegExp = RegExp(r'/?(\d+(\.\d*)?)x$');

Future<ByteData> loadAssetManifest() async {
double parseScale(String key) {
final Uri assetUri = Uri.parse(key);
String directoryPath = '';
if (assetUri.pathSegments.length > 1) {
directoryPath = assetUri.pathSegments[assetUri.pathSegments.length - 2];
}
final Match? match = _extractRatioRegExp.firstMatch(directoryPath);
if (match != null && match.groupCount > 0) {
return double.parse(match.group(1)!);
}
return 1.0;
}

final Map<String, dynamic> result = <String, dynamic>{};
final PlatformAssetBundle bundle = PlatformAssetBundle();

// For the benchmark, we use the older JSON format and then convert it to the modern binary format.
final ByteData jsonAssetManifestBytes = await bundle.load('money_asset_manifest.json');
final String jsonAssetManifest = utf8.decode(jsonAssetManifestBytes.buffer.asUint8List());

final Map<String, dynamic> assetManifest = json.decode(jsonAssetManifest) as Map<String, dynamic>;

for (final MapEntry<String, dynamic> manifestEntry in assetManifest.entries) {
final List<dynamic> resultVariants = <dynamic>[];
final List<String> entries = (manifestEntry.value as List<dynamic>).cast<String>();
for (final String variant in entries) {
if (variant == manifestEntry.key) {
// With the newer binary format, don't include the main asset in it's
// list of variants. This reduces parsing time at runtime.
continue;
}
final Map<String, dynamic> resultVariant = <String, dynamic>{};
final double variantDevicePixelRatio = parseScale(variant);
resultVariant['asset'] = variant;
resultVariant['dpr'] = variantDevicePixelRatio;
resultVariants.add(resultVariant);
}
result[manifestEntry.key] = resultVariants;
}

return const StandardMessageCodec().encodeMessage(result)!;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter_gallery/gallery/example_code_parser.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -58,4 +60,9 @@ class TestAssetBundle extends AssetBundle {

@override
String toString() => '$runtimeType@$hashCode()';

@override
Future<T> loadStructuredBinaryData<T>(String key, FutureOr<T> Function(ByteData data) parser) async {
return parser(await load(key));
}
}
Loading

0 comments on commit 56cad89

Please sign in to comment.