Если вы читаете эту статью, то наверняка уже видели мою предыдущую статью (отметьте здесь👈), в которой я сравнил метод map и цикл for и неожиданно выиграл метод map в тесте. Несмотря на то, что статья началась с моего заявления о том, что метод map не может быть быстрее, чем цикл for, и несмотря на ироничный стиль статьи в целом, она стал вирусным. И чтобы все прояснить, я пишу этот текст.

Для начала позвольте мне рассказать вам короткую историю из моей средней школы:

Команде водителей грузовиков из города А удалось за одну ночь доставить 100 000 упаковок компакт-дисков из города А в город Б. Таким образом, они достигли скорости передачи данных 2,43 терабайт в секунду на расстояние более 500 км без использования дорогих кабелей.

А пока вы гуглите, что такое CD-диски, я сразу напишу код для расширенного честного сравнения методов итерации.

Хорошо

Добавлю к предыдущему тесту несколько существенных изменений:

  1. Вместо того, чтобы просто присвоить значение переменной result, мы добавим элементы в список results. Затем перед каждым вызовом report() мы будем очищать список results, чтобы убедиться, что каждый тест начинается с чистого состояния. Это убедит компилятор в том, что операции действительно нужны и не должны оптимизироваться.
  2. Мы добавим в сравнение другие циклы: 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);
  });
}

Итак, давайте посмотрим на результат:

Вот объяснение результатов с точки зрения того, как работают различные методы итерации:

  1. forEach: этот метод применяет переданную функцию к каждому элементу списка. В этом случае производительность forEach составляет 168 000 000 элементов в секунду. Это связано с тем, что forEach основан на функциональном программировании и обеспечивает довольно быструю итерацию по элементам.
  2. Цикл For. Цикл for — это классический способ перебора элементов списка с использованием индекса. В этом случае производительность цикла for также составляет 168 000 000 элементов в секунду. Это связано с тем, что цикл for является конструкцией нативного языка и оптимизирован для быстрой итерации.
  3. Цикл For-in. Цикл for-in — это высокоуровневый способ перебора элементов списка. В этом тесте производительность составляет 84 000 000 элементов в секунду. Это связано с тем, что цикл for-in использует итераторы под капотом и не требует индекса для доступа к элементам, что может снизить производительность по сравнению с циклами for и forEach.
  4. Цикл while с итератором: в этом случае мы вручную используем итератор с циклом while. Производительность составляет 84 000 000 элементов в секунду. Это связано с тем, что итераторы обеспечивают низкоуровневый контроль над процессом итерации, что может снизить производительность по сравнению с другими методами.
  5. Map: метод map создает новую коллекцию, применяя переданную функцию к каждому элементу исходного списка. В этом случае производительность метода map составляет 56 000 000 элементов в секунду. Это связано с тем, что метод map создает новый список, что приводит к дополнительному выделению памяти и копированию элементов.

И, ребята, всегда помните одну простую вещь:

карта не цикл

Да, этот метод часто используется при создании массивов, но сравнивать его с циклами не совсем корректно. Это как перевозить CD-диски на грузовиках — это более сложный и дорогой способ работы с данными.

Вот и все

Чтобы не попасть в ловушку кликбейтных статей, попробуйте лично пообщаться с опытными разработчиками. Вам очень повезет, если среди ваших коллег найдутся лиды и старшие с хорошими методологиями, и они поделятся ими с другими. Это основа.

Подпишитесь, чтобы не пропустить новые новаторские сообщения.

Вам также могут быть интересны другие мои тесты:







Технический персонал:



Или целая серия статей о работе с REST API (это настоящее дерьмо как Санта-Барбара):