flutterdartdart-isolates

Flutter isolate bad performance with big list


On my Flutter app i need to parse a JSON which has a list of 100k or more elements. For this reason, no not stack the UI thread, I am using Isolate to move the load of work in a separate thread. The problem is that the performance decreased a lot: without Isolate in 20/30 seconds the function was over, with Isolate it parsed just the 2% of the elements.

Since I am new to Isolate, am I doing something wrong? Or can I improve my code somehow?

  Future<ServiceResponse> _createServiceResponse(
    Map<String, dynamic> map,
  ) async {
    Map<String, dynamic> responseMap = {};
    List<Ean> eans = List.empty(growable: true);
    List<Article> articles = List.empty(growable: true);

    responseMap["assortment"] =
        AssortmentJson.fromJson(map).convertToObox().convertToDomain();
    if (map.containsKey("article")) {
      int counter = 0;
      for (var element in (map["article"] as List<dynamic>)) {
        String progress =
            "${(counter++ / map["article"].length * 100).toInt()}%";
        LoadingOverlay.of(context).attachText(progress);

        Map<String, dynamic> item = element as Map<String, dynamic>;
        var (article, eanList) =
            await Isolate.run(() => _createArticlesAndEanList(item));
        articles.add(article);
        eans.addAll(eanList);
      }
    }
    responseMap["articles"] = articles;
    responseMap["eans"] = eans;
    return ServiceResponse(ok: true, payload: responseMap);
  }

  static Future<(Article, List<Ean>)> _createArticlesAndEanList(
      Map<String, dynamic> articleJson) async {
    List<Ean> eans = List.empty(growable: true);

    var article = ArticleJson.fromJson(
            articleJson.convertIdToInt().convertDateFormatToAppFormat())
        .convertToObox(assignReferences: false)
        .convertToDomain();

    Map<String, int?> propertyNotAssigned = {};
    if (articleJson.containsKey("ean")) {
      eans.addAll((articleJson["ean"] as List<dynamic>).map((e) =>
          EanJson.fromJson((e as Map<String, dynamic>).convertIdToInt())
              .convertToObox(
                  assignReferences: false,
                  propertyNameToId: propertyNotAssigned)
              .convertToDomain()
              .assignArticleFromArticleList(article)));
    }

    return (article, eans);
  }


Solution

    1. You create a new Isolate for each element and run them one after the other. It would make much more sense to use only one isolate for everything together.
    2. The biggest work in json deserialization is the conversion from a String to a Map<String, dynamic> and not the interpretation of the Map<String, dynamic>. Have you already taken this into account?