为什么我的Dart脚本启用translateRecipeMatching逻辑后运行极慢?
性能骤降根本原因
你现在的代码存在指数级的无效循环,总运算量达到了十亿次量级,必然卡顿:
- 每个配方条目都会遍历全部23434条翻译数据,每遍历1条翻译就会执行1次
translateRecipeMatching方法 - 只要配方属于Equipment分类,每次执行
translateRecipeMatching都会遍历全部1419条匹配列表做线性查找 - 按你给出的700条配方计算,总循环次数为
700 * 23434 * 1419 ≈ 23亿次,远超出正常脚本的运算量级 - 哪怕只是加一行日志,单次运行就会输出1600万+条日志,直接把VS Code的调试控制台缓冲区占满,导致窗口崩溃。
额外的性能浪费与问题点
- 无提前终止逻辑:遍历翻译列表找到匹配项后没有加
break,会继续把剩下的所有翻译全部遍历完,做无用功 - 重复计算:配方的
craftedItemId转换逻辑每个配方只需要执行1次,你现在放在翻译循环里,相当于每个配方重复执行了2万多次 - 线性查找效率极低:所有匹配都用遍历实现,时间复杂度是O(n),换成哈希表查找可以降到O(1)
- 隐藏Bug:
translateRecipeMatching方法的else分支里,你把clothGroupId赋值给了matchingListItemId而不是craftedItemId,导致非多变体的装备配方匹配逻辑完全无效。
优化方案
第一步:预处理成哈希查找表,完全避免线性遍历
在脚本启动、数据加载完成后,一次性把两个列表转成哈希表:
// 翻译表:key是翻译id,value是处理好的多语言映射 final translationMap = <String, Map<String, dynamic>>{}; for (final translation in translationList) { final id = translation['id'].toString(); final tempMap = <String, dynamic>{}; translation.forEach((key, value) { tempMap[getOldLanguageString(key)] = value; }); translationMap[id] = tempMap; } // 配方匹配表:key是物品internalId,value是对应的clothGroupId final recipeMatchMap = <String, String>{}; for (final item in recipeMatchingList) { final internalId = item.containsKey('variations') ? item['variations'][0]['internalId'].toString() : item['internalId'].toString(); final groupId = item.containsKey('variations') ? item['variations'][0]['clothGroupId'].toString() : item['clothGroupId'].toString(); recipeMatchMap[internalId] = groupId; }
第二步:调整逻辑顺序,避免重复计算
修改addTranslationsToItem方法,把每个条目只需要算一次的逻辑提到翻译循环外,直接用哈希表查找:
Map<String, dynamic> addTranslationsToItem(Map<String, dynamic> item, Map<String, String> recipeMatchMap, Map<String, Map<String, dynamic>> translationMap) { bool clothGroupMatching = clothingCategorys.contains(item["sourceSheet"]); bool recipeMatching = item["sourceSheet"] == "Recipes"; // 其他类型判断省略... String targetId; if (recipeMatching) { targetId = item["craftedItemInternalId"].toString(); // 装备类配方只需要查一次匹配表换groupId if (item["category"] == "Equipment") { targetId = recipeMatchMap[targetId] ?? targetId; } } else { // 其他类型的targetId计算逻辑省略... } // 直接查翻译表,完全不需要遍历翻译列表 if (translationMap.containsKey(targetId)) { item["translations"] = translationMap[targetId]!; } return item; }
优化后总运算量从23亿次降到不到3万次,运行速度会回到10秒以内。
内容的提问来源于stack exchange,提问作者lellek
相关产品推荐
相关产品推荐

