Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions flutter/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ analyzer:
exclude:
- lib/localizations/**
- lib/protos/**
- build/**
- android/**
- ios/**
- windows/**
language:
strict-casts: true

Expand Down
35 changes: 30 additions & 5 deletions flutter/lib/app_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,23 +31,48 @@ class BenchmarkId {
static const imageClassificationV2 = 'image_classification_v2';
static const imageClassificationOfflineV2 = 'image_classification_offline_v2';
static const stableDiffusion = 'stable_diffusion';
static const llm = 'llm-1b';
static const llmInstruct = 'llm-1b-instruct';
static const llm1b = 'llm-1b';
static const llm1bInstruct = 'llm-1b-instruct';
static const llm3b = 'llm-3b';
static const llm3bInstruct = 'llm-3b-instruct';
static const llm8b = 'llm-8b';
static const llm8bInstruct = 'llm-8b-instruct';

// The sort order of this list will be used in the UI
static const llmIds = [
llm1b,
llm1bInstruct,
llm3b,
llm3bInstruct,
llm8b,
llm8bInstruct,
];

// The sort order of this list will be used in the UI.
// Every task in tasks.pbtxt must appear here: BenchmarkStore sorts with
// indexOf, which returns -1 for anything missing and floats it to the top.
static const allIds = [
imageClassificationV2,
objectDetection,
imageSegmentationV2,
naturalLanguageProcessing,
superResolution,
stableDiffusion,
llm,
llmInstruct,
llm1b,
llm1bInstruct,
llm3b,
llm3bInstruct,
llm8b,
llm8bInstruct,
imageClassificationOfflineV2,
];
}

/// Ids of the `task_set` blocks in tasks.pbtxt.
class BenchmarkSetId {
static const imageClassification = 'image_classification';
static const llm = 'llm';
}

class BackendId {
static const tflite = 'libtflitebackend';
static const pixel = 'libtflitepixelbackend';
Expand Down
10 changes: 10 additions & 0 deletions flutter/lib/benchmark/benchmark.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ class BenchmarkSet {
applyOptionStateMap(optionState);
}

BenchmarkSetInfo get info => BenchmarkSetInfo(config);

/// The benchmarks this set will actually run under the current options.
List<Benchmark> get activeBenchmarks =>
benchmarks.where((e) => e.isActive).toList();

Iterable<BenchmarkOption> availableOptions() {
var unhiddenOptions = optionSets
.where((e) => !e.config.hidden)
Expand Down Expand Up @@ -277,6 +283,10 @@ class BenchmarkOptionSet {
};
}

/// True when the config allows exactly one option here, so the UI should
/// offer a single choice rather than independent checkboxes.
bool get isSingleChoice => config.maxSelected == 1;

bool? getOption(String id) {
return options[id]?.enabled;
}
Expand Down
38 changes: 36 additions & 2 deletions flutter/lib/benchmark/info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,16 @@

BenchmarkLocalizationInfo getLocalizedInfo(AppLocalizations stringResources) {
switch (task.id) {
case (BenchmarkId.llm):
// Every LLM variant shares one description; the size and the eval it
// runs are already in the task's own name.
case (BenchmarkId.llm1b):
case (BenchmarkId.llm1bInstruct):
case (BenchmarkId.llm3b):
case (BenchmarkId.llm3bInstruct):
case (BenchmarkId.llm8b):
case (BenchmarkId.llm8bInstruct):
return BenchmarkLocalizationInfo(
name: 'LLM',
name: task.name,
detailsTitle: stringResources.benchInfoLlm,
detailsContent: stringResources.benchInfoLlmDesc,
);
Expand Down Expand Up @@ -91,3 +98,30 @@
@override
String toString() => 'Benchmark:${task.id}';
}

/// Name, icon and description of a whole task set.
///
/// A set is a frontend-only grouping, so it needs its own identity rather than
/// borrowing one from whichever benchmark happens to sort first.
class BenchmarkSetInfo {
final pb.TaskSet config;

BenchmarkSetInfo(this.config);

String get name => config.name;

Widget get icon => BenchmarkIcons.getSetDarkIcon(config.id);

Check warning on line 113 in flutter/lib/benchmark/info.dart

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Undefined name 'BenchmarkIcons'.

See more on https://sonarcloud.io/project/issues?id=mlcommons_mobile_app_open&issues=AaDd4Uegz5PIa1mbJH9x&open=AaDd4Uegz5PIa1mbJH9x&pullRequest=1183

/// Null when the set has no description of its own. Sets come from config,
/// so an unknown one is a gap to fall back from, not a crash.
String? localizedDetails(AppLocalizations stringResources) {
switch (config.id) {
case (BenchmarkSetId.llm):

Check warning on line 119 in flutter/lib/benchmark/info.dart

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Undefined name 'BenchmarkSetId'.

See more on https://sonarcloud.io/project/issues?id=mlcommons_mobile_app_open&issues=AaDd4Uegz5PIa1mbJH9y&open=AaDd4Uegz5PIa1mbJH9y&pullRequest=1183
return stringResources.benchInfoLlmDesc;
case (BenchmarkSetId.imageClassification):
return stringResources.benchInfoImageClassificationV2Desc;
default:
return null;
}
}
}
32 changes: 26 additions & 6 deletions flutter/lib/benchmark/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -402,9 +402,30 @@ class BenchmarkState extends ChangeNotifier {
return;
}
if (!benchmark.selectBackend(libName)) return;
// Persist only this explicit choice, merged into the stored map, so
// untouched benchmarks keep following future defaults and selections
// made under other task configs are preserved.
_persistBackendSelection({benchmark.id: libName});
notifyListeners();
}

/// Applies one backend to every benchmark in the set that offers it.
/// Benchmarks without that backend keep the one they have.
void benchmarkSetBackendForSet(BenchmarkSet benchmarkSet, String libName) {
if (state == BenchmarkStateEnum.running ||
state == BenchmarkStateEnum.aborting) {
return;
}
final applied = <String, String>{};
for (final benchmark in benchmarkSet.benchmarks) {
if (benchmark.selectBackend(libName)) applied[benchmark.id] = libName;
}
if (applied.isEmpty) return;
_persistBackendSelection(applied);
notifyListeners();
}

/// Persist only explicit choices, merged into the stored map, so untouched
/// benchmarks keep following future defaults and selections made under other
/// task configs are preserved.
void _persistBackendSelection(Map<String, String> choices) {
Map<String, dynamic> stored = {};
if (_store.backendSelection.isNotEmpty) {
try {
Expand All @@ -413,12 +434,11 @@ class BenchmarkState extends ChangeNotifier {
print('Backend selection parse fail: $e');
}
}
stored[benchmark.id] = libName;
stored.addAll(choices);
_store.backendSelection = jsonEncode(stored);
// The resource map is built for the previously selected backends;
// rebuild it so resource validation sees the new backend's files.
// rebuild it so resource validation sees the new backends' files.
deferredLoadResources();
notifyListeners();
}

void benchmarkSetOption(
Expand Down
16 changes: 14 additions & 2 deletions flutter/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,18 @@
"mainScreenGo": "GO",
"mainScreenMeasureTitle": "Measure your device performance for:",
"mainScreenBenchmarkSelected": "Benchmarks (<selected>/<total> selected)",
"mainScreenOptionsSelected": "<active>/<total> options selected",
"mainScreenSetRunsCount": "Runs <count> of <total> benchmarks",
"mainScreenSetRunsNothing": "Runs nothing",
"mainScreenSetNothingSelected": "Nothing selected — this set will not run",
"mainScreenSetBackends": "Backends",
"mainScreenSetFilesMissing": "Files missing",
"mainScreenSetBackendForAll": "Apply to all",
"mainScreenSetBackendMixed": "Mixed",
"mainScreenBackendLabel": "Backend",
"mainScreenDelegateLabel": "Delegate",
"mainScreenOptionRuleOneOrMore": "select one or more",
"mainScreenOptionRulePickOne": "pick one",
"mainScreenBenchmarkNotSelected": "not selected",

"progressPerformance": "Performance",
"progressAccuracy": "Accuracy",
Expand All @@ -55,7 +66,8 @@
"resultsNotAvailable": "N/A",
"resultsBenchmarkAborted": "Benchmark aborted!",
"resultsBatchSize": "Batches: <batchSize>",
"resultsBenchmarksInSet": "<count> benchmarks in this set",
"resultsSetRanCount": "<count> of <total> benchmarks ran",
"resultsBenchmarkNotRun": "Not run",

"shareButtonMLCommons": "Share with MLCommons",
"shareButtonOther": "Share with others",
Expand Down
16 changes: 14 additions & 2 deletions flutter/lib/l10n/app_zh.arb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,18 @@
"mainScreenGo": "开始",
"mainScreenMeasureTitle": "测量您的设备性能:",
"mainScreenBenchmarkSelected": "基准测试(已选择 <selected>/<total>)",
"mainScreenOptionsSelected": "已选择 <active>/<total> 个选项",
"mainScreenSetRunsCount": "运行 <total> 项中的 <count> 项基准测试",
"mainScreenSetRunsNothing": "不运行任何基准测试",
"mainScreenSetNothingSelected": "未选择任何选项 — 此组不会运行",
"mainScreenSetBackends": "后端",
"mainScreenSetFilesMissing": "缺少文件",
"mainScreenSetBackendForAll": "应用于全部",
"mainScreenSetBackendMixed": "混合",
"mainScreenBackendLabel": "后端",
"mainScreenDelegateLabel": "委托",
"mainScreenOptionRuleOneOrMore": "选择一项或多项",
"mainScreenOptionRulePickOne": "选择一项",
"mainScreenBenchmarkNotSelected": "未选择",

"progressPerformance": "性能",
"progressAccuracy": "准确度",
Expand All @@ -55,7 +66,8 @@
"resultsNotAvailable": "N/A",
"resultsBenchmarkAborted": "基准测试已中止!",
"resultsBatchSize": "批次:<batchSize>",
"resultsBenchmarksInSet": "此组包含 <count> 个基准测试",
"resultsSetRanCount": "已运行 <total> 项中的 <count> 项基准测试",
"resultsBenchmarkNotRun": "未运行",

"shareButtonMLCommons": "分享给 MLCommons",
"shareButtonOther": "分享给他人",
Expand Down
15 changes: 15 additions & 0 deletions flutter/lib/ui/app_styles.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@
static const progressCircle = _blue4;
static const goCircle = _green;
static const warningIcon = _yellow;

// Benchmark config / result cards.
static const cardBorder = Color(0xFFE2E8F0);
static const cardDivider = Color(0xFFF1F5F9);
static const cardFooter = Color(0xFFFAFBFC);

Check warning on line 47 in flutter/lib/ui/app_styles.dart

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

The method 'Color' isn't defined for the type 'AppColors'.

See more on https://sonarcloud.io/project/issues?id=mlcommons_mobile_app_open&issues=AaDd4Uaxz5PIa1mbJH9D&open=AaDd4Uaxz5PIa1mbJH9D&pullRequest=1183
static const panelBackground = Color(0xFFF4F7FA);
static const panelDivider = Color(0xFFE6ECF1);

Check warning on line 49 in flutter/lib/ui/app_styles.dart

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Const variables must be initialized with a constant value.

See more on https://sonarcloud.io/project/issues?id=mlcommons_mobile_app_open&issues=AaDd4Uaxz5PIa1mbJH9S&open=AaDd4Uaxz5PIa1mbJH9S&pullRequest=1183
static const setIconBackground = Color(0xFFEAF4FB);
static const chipBorder = Color(0xFFC3CED9);
static const bodyText = Color(0xFF0F172A);
static const mutedText = Color(0xFF475569);

Check warning on line 53 in flutter/lib/ui/app_styles.dart

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Const variables must be initialized with a constant value.

See more on https://sonarcloud.io/project/issues?id=mlcommons_mobile_app_open&issues=AaDd4Uaxz5PIa1mbJH9W&open=AaDd4Uaxz5PIa1mbJH9W&pullRequest=1183
static const subtleText = Color(0xFF64748B);
static const warningText = Color(0xFF7A5800);
static const warningBackground = Color(0xFFFDF6E0);
static const warningBorder = Color(0xFFE8C95C);
}

class AppGradients {
Expand Down
Loading
Loading