Если вы читаете эту статью, то наверняка уже видели мою предыдущую статью (отметьте здесь👈), в которой я сравнил метод map
и цикл for
и неожиданно выиграл метод map
в тесте. Несмотря на то, что статья началась с моего заявления о том, что метод map не может быть быстрее, чем цикл for, и несмотря на ироничный стиль статьи в целом, она стал вирусным. И чтобы все прояснить, я пишу этот текст.
Для начала позвольте мне рассказать вам короткую историю из моей средней школы:
Команде водителей грузовиков из города А удалось за одну ночь доставить 100 000 упаковок компакт-дисков из города А в город Б. Таким образом, они достигли скорости передачи данных 2,43 терабайт в секунду на расстояние более 500 км без использования дорогих кабелей.
А пока вы гуглите, что такое CD-диски, я сразу напишу код для расширенного честного сравнения методов итерации.
Хорошо
Добавлю к предыдущему тесту несколько существенных изменений:
- Вместо того, чтобы просто присвоить значение переменной
result
, мы добавим элементы в списокresults
. Затем перед каждым вызовомreport()
мы будем очищать списокresults
, чтобы убедиться, что каждый тест начинается с чистого состояния. Это убедит компилятор в том, что операции действительно нужны и не должны оптимизироваться. - Мы добавим в сравнение другие циклы:
forEach
,for-in
иwhile
. Просто чтобы продемонстрировать фундаментальные различия между ними.
import 'dart:convert'; import 'package:benchmarking/benchmarking.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { test('benchmark forEach, for, for-in, and while with iterator', () { List<String> results = []; String? result; var json = "{\"latitude\":52.52,\"longitude\":13.419998,\"generationtime_ms\":0.1590251922607422,\"utc_offset_seconds\":0,\"timezone\":\"GMT\",\"timezone_abbreviation\":\"GMT\",\"elevation\":38.0,\"current_weather\":{\"temperature\":13.3,\"windspeed\":15.6,\"winddirection\":40.0,\"weathercode\":3,\"is_day\":1,\"time\":\"2023-04-18T14:00\"},\"hourly_units\":{\"time\":\"iso8601\",\"temperature_2m\":\"°C\"},\"hourly\":{\"time\":[\"2023-04-18T00:00\",\"2023-04-18T01:00\",\"2023-04-18T02:00\",\"2023-04-18T03:00\",\"2023-04-18T04:00\",\"2023-04-18T05:00\",\"2023-04-18T06:00\",\"2023-04-18T07:00\",\"2023-04-18T08:00\",\"2023-04-18T09:00\",\"2023-04-18T10:00\",\"2023-04-18T11:00\",\"2023-04-18T12:00\",\"2023-04-18T13:00\",\"2023-04-18T14:00\",\"2023-04-18T15:00\",\"2023-04-18T16:00\",\"2023-04-18T17:00\",\"2023-04-18T18:00\",\"2023-04-18T19:00\",\"2023-04-18T20:00\",\"2023-04-18T21:00\",\"2023-04-18T22:00\",\"2023-04-18T23:00\",\"2023-04-19T00:00\",\"2023-04-19T01:00\",\"2023-04-19T02:00\",\"2023-04-19T03:00\",\"2023-04-19T04:00\",\"2023-04-19T05:00\",\"2023-04-19T06:00\",\"2023-04-19T07:00\",\"2023-04-19T08:00\",\"2023-04-19T09:00\",\"2023-04-19T10:00\",\"2023-04-19T11:00\",\"2023-04-19T12:00\",\"2023-04-19T13:00\",\"2023-04-19T14:00\",\"2023-04-19T15:00\",\"2023-04-19T16:00\",\"2023-04-19T17:00\",\"2023-04-19T18:00\",\"2023-04-19T19:00\",\"2023-04-19T20:00\",\"2023-04-19T21:00\",\"2023-04-19T22:00\",\"2023-04-19T23:00\",\"2023-04-20T00:00\",\"2023-04-20T01:00\",\"2023-04-20T02:00\",\"2023-04-20T03:00\",\"2023-04-20T04:00\",\"2023-04-20T05:00\",\"2023-04-20T06:00\",\"2023-04-20T07:00\",\"2023-04-20T08:00\",\"2023-04-20T09:00\",\"2023-04-20T10:00\",\"2023-04-20T11:00\",\"2023-04-20T12:00\",\"2023-04-20T13:00\",\"2023-04-20T14:00\",\"2023-04-20T15:00\",\"2023-04-20T16:00\",\"2023-04-20T17:00\",\"2023-04-20T18:00\",\"2023-04-20T19:00\",\"2023-04-20T20:00\",\"2023-04-20T21:00\",\"2023-04-20T22:00\",\"2023-04-20T23:00\",\"2023-04-21T00:00\",\"2023-04-21T01:00\",\"2023-04-21T02:00\",\"2023-04-21T03:00\",\"2023-04-21T04:00\",\"2023-04-21T05:00\",\"2023-04-21T06:00\",\"2023-04-21T07:00\",\"2023-04-21T08:00\",\"2023-04-21T09:00\",\"2023-04-21T10:00\",\"2023-04-21T11:00\",\"2023-04-21T12:00\",\"2023-04-21T13:00\",\"2023-04-21T14:00\",\"2023-04-21T15:00\",\"2023-04-21T16:00\",\"2023-04-21T17:00\",\"2023-04-21T18:00\",\"2023-04-21T19:00\",\"2023-04-21T20:00\",\"2023-04-21T21:00\",\"2023-04-21T22:00\",\"2023-04-21T23:00\",\"2023-04-22T00:00\",\"2023-04-22T01:00\",\"2023-04-22T02:00\",\"2023-04-22T03:00\",\"2023-04-22T04:00\",\"2023-04-22T05:00\",\"2023-04-22T06:00\",\"2023-04-22T07:00\",\"2023-04-22T08:00\",\"2023-04-22T09:00\",\"2023-04-22T10:00\",\"2023-04-22T11:00\",\"2023-04-22T12:00\",\"2023-04-22T13:00\",\"2023-04-22T14:00\",\"2023-04-22T15:00\",\"2023-04-22T16:00\",\"2023-04-22T17:00\",\"2023-04-22T18:00\",\"2023-04-22T19:00\",\"2023-04-22T20:00\",\"2023-04-22T21:00\",\"2023-04-22T22:00\",\"2023-04-22T23:00\",\"2023-04-23T00:00\",\"2023-04-23T01:00\",\"2023-04-23T02:00\",\"2023-04-23T03:00\",\"2023-04-23T04:00\",\"2023-04-23T05:00\",\"2023-04-23T06:00\",\"2023-04-23T07:00\",\"2023-04-23T08:00\",\"2023-04-23T09:00\",\"2023-04-23T10:00\",\"2023-04-23T11:00\",\"2023-04-23T12:00\",\"2023-04-23T13:00\",\"2023-04-23T14:00\",\"2023-04-23T15:00\",\"2023-04-23T16:00\",\"2023-04-23T17:00\",\"2023-04-23T18:00\",\"2023-04-23T19:00\",\"2023-04-23T20:00\",\"2023-04-23T21:00\",\"2023-04-23T22:00\",\"2023-04-23T23:00\",\"2023-04-24T00:00\",\"2023-04-24T01:00\",\"2023-04-24T02:00\",\"2023-04-24T03:00\",\"2023-04-24T04:00\",\"2023-04-24T05:00\",\"2023-04-24T06:00\",\"2023-04-24T07:00\",\"2023-04-24T08:00\",\"2023-04-24T09:00\",\"2023-04-24T10:00\",\"2023-04-24T11:00\",\"2023-04-24T12:00\",\"2023-04-24T13:00\",\"2023-04-24T14:00\",\"2023-04-24T15:00\",\"2023-04-24T16:00\",\"2023-04-24T17:00\",\"2023-04-24T18:00\",\"2023-04-24T19:00\",\"2023-04-24T20:00\",\"2023-04-24T21:00\",\"2023-04-24T22:00\",\"2023-04-24T23:00\"],\"temperature_2m\":[6.0,5.7,5.2,4.7,4.4,4.3,5.2,6.7,8.2,8.8,10.4,11.7,11.9,12.6,13.3,13.6,12.6,11.9,10.8,9.8,8.6,7.0,5.8,5.1,4.6,4.0,3.5,3.1,2.7,2.9,4.1,6.1,7.9,9.6,11.0,11.8,11.7,11.2,9.9,7.6,5.9,5.1,5.5,5.5,5.7,5.9,6.1,6.1,6.0,5.8,5.7,5.6,5.6,5.7,6.1,6.6,7.0,7.7,8.6,10.9,14.6,15.5,15.9,15.2,15.2,14.7,13.4,12.1,11.2,10.5,10.0,9.6,9.2,8.8,8.4,8.1,7.8,7.9,9.0,10.7,12.7,14.5,16.0,17.1,17.9,18.2,18.2,17.8,17.0,16.0,14.6,13.5,12.5,11.3,10.6,10.2,9.6,9.0,8.5,8.1,8.0,8.2,9.1,10.6,12.6,15.1,16.4,17.5,18.5,18.7,18.6,18.0,17.3,16.4,15.3,14.8,14.4,13.9,13.6,13.4,13.0,12.6,12.2,11.8,11.8,11.9,12.0,9.1,10.0,11.1,11.9,12.7,13.5,13.9,14.2,14.2,14.0,13.6,12.9,12.3,11.7,10.9,10.6,10.3,9.7,9.0,8.1,7.1,6.8,6.6,6.7,7.1,7.6,8.4,9.0,9.6,10.2,10.7,11.1,11.2,10.9,10.3,9.4,8.8,8.0,7.1,6.6,6.1]}}"; var decodedJson = jsonDecode(json); var neededArray = decodedJson['hourly']['time']; syncBenchmark('forEach over needed array', () { neededArray.forEach((item) { results.add(item); }); results.clear(); }).report(units: neededArray.length); syncBenchmark('For loop over needed array', () { for (int i = 0; i < neededArray.length; i++) { results.add(neededArray[i]); } results.clear(); }).report(units: neededArray.length); syncBenchmark('For-in loop over needed array', () { for (var item in neededArray) { results.add(item); } results.clear(); }).report(units: neededArray.length); syncBenchmark('While loop with iterator over needed array', () { var iterator = neededArray.iterator; while (iterator.moveNext()) { results.add(iterator.current); } results.clear(); }).report(units: neededArray.length); syncBenchmark('Map over needed array', () { results = neededArray.map<String>((item) => item.toString()).toList(); results.clear(); }).report(units: neededArray.length); }); }
Итак, давайте посмотрим на результат:
Вот объяснение результатов с точки зрения того, как работают различные методы итерации:
- forEach: этот метод применяет переданную функцию к каждому элементу списка. В этом случае производительность
forEach
составляет 168 000 000 элементов в секунду. Это связано с тем, чтоforEach
основан на функциональном программировании и обеспечивает довольно быструю итерацию по элементам. - Цикл For. Цикл
for
— это классический способ перебора элементов списка с использованием индекса. В этом случае производительность циклаfor
также составляет 168 000 000 элементов в секунду. Это связано с тем, что циклfor
является конструкцией нативного языка и оптимизирован для быстрой итерации. - Цикл For-in. Цикл
for-in
— это высокоуровневый способ перебора элементов списка. В этом тесте производительность составляет 84 000 000 элементов в секунду. Это связано с тем, что циклfor-in
использует итераторы под капотом и не требует индекса для доступа к элементам, что может снизить производительность по сравнению с цикламиfor
иforEach
. - Цикл while с итератором: в этом случае мы вручную используем итератор с циклом
while
. Производительность составляет 84 000 000 элементов в секунду. Это связано с тем, что итераторы обеспечивают низкоуровневый контроль над процессом итерации, что может снизить производительность по сравнению с другими методами. - Map: метод
map
создает новую коллекцию, применяя переданную функцию к каждому элементу исходного списка. В этом случае производительность методаmap
составляет 56 000 000 элементов в секунду. Это связано с тем, что методmap
создает новый список, что приводит к дополнительному выделению памяти и копированию элементов.
И, ребята, всегда помните одну простую вещь:
карта не цикл
Да, этот метод часто используется при создании массивов, но сравнивать его с циклами не совсем корректно. Это как перевозить CD-диски на грузовиках — это более сложный и дорогой способ работы с данными.
Вот и все
Чтобы не попасть в ловушку кликбейтных статей, попробуйте лично пообщаться с опытными разработчиками. Вам очень повезет, если среди ваших коллег найдутся лиды и старшие с хорошими методологиями, и они поделятся ими с другими. Это основа.
Подпишитесь, чтобы не пропустить новые новаторские сообщения.
Вам также могут быть интересны другие мои тесты:
Вторник Flutter Benchmark: SQLite vs. Hive — как нас обманывают популярные статьи
Всем привет. Это очередная история нашего регулярного сегмента «тестирование очевидных вещей по вторникам. И на этот раз…medium.com»
Технический персонал:
Или целая серия статей о работе с REST API (это настоящее дерьмо как Санта-Барбара):
Совместная работа Flutter и REST API — реализация фильтрации (часть 10)
Добро пожаловать в часть 10 серии «Совместная работа Flutter и REST API! Это особая веха, так как мы…medium.com»