[{"data":1,"prerenderedAt":3559},["ShallowReactive",2],{"page-\u002Fdart\u002F10-isolates-and-concurrency":3},{"id":4,"title":5,"body":6,"description":3552,"extension":3553,"meta":3554,"navigation":75,"path":3555,"seo":3556,"stem":3557,"__hash__":3558},"content\u002Fdart\u002F10-isolates-and-concurrency.md","Dart — Isolates, Actor Model & Zero-Copy Transfer",{"type":7,"value":8,"toc":3540},"minimark",[9,13,18,367,377,758,762,1775,1779,2060,2064,2944,2948,3157,3161,3217,3221,3329,3333,3337,3394,3397,3536],[10,11,5],"h1",{"id":12},"dart-isolates-actor-model-zero-copy-transfer",[14,15,17],"h2",{"id":16},"the-actor-model-no-shared-memory","The Actor Model — No Shared Memory",[19,20,22],"code-wrapper",{"language":21},"dart",[23,24,28],"pre",{"className":25,"code":26,"language":21,"meta":27,"style":27},"language-dart shiki shiki-themes github-light github-dark","\u002F\u002F Dart has NO shared-memory threads. Isolates are independent workers:\n\u002F\u002F - Each isolate has its own memory heap (no shared mutable state).\n\u002F\u002F - Communication is via message passing (ports).\n\u002F\u002F - No data races — no locks, no mutexes, no atomics.\n\u002F\u002F\n\u002F\u002F This is the Erlang\u002FAkka actor model, not the Java\u002FC++ threading model.\n\n\u002F\u002F ── Isolate.run: one-shot computation in a separate isolate ──\n\u002F\u002F Spawns an isolate, runs the function, sends the result back, kills the isolate.\n\u002F\u002F The closure and its captured values are DEEP-COPIED to the new isolate.\n\nFuture\u003Cint> heavySum() async {\n  return Isolate.run(() {\n    \u002F\u002F This runs on a separate OS thread with its own heap.\n    \u002F\u002F No access to the main isolate's memory — everything is copied.\n    var sum = 0;\n    for (var i = 0; i \u003C 1000000000; i++) sum += i;\n    return sum;  \u002F\u002F result is deep-copied back to the main isolate\n  });\n}\n\n\u002F\u002F Capturing values — they're COPIED (deep copy), not shared:\nFuture\u003Cvoid> processFile(String path) async {\n  final result = await Isolate.run(() {\n    \u002F\u002F `path` was copied — modifying it here doesn't affect the original.\n    final content = File(path).readAsStringSync();\n    return content.toUpperCase();\n  });\n  print(result);\n}\n","",[29,30,31,40,46,52,58,64,70,77,83,89,95,100,131,149,155,161,179,221,233,239,245,250,256,284,306,312,335,348,353,362],"code",{"__ignoreMap":27},[32,33,36],"span",{"class":34,"line":35},"line",1,[32,37,39],{"class":38},"sdCPZ","\u002F\u002F Dart has NO shared-memory threads. Isolates are independent workers:\n",[32,41,43],{"class":34,"line":42},2,[32,44,45],{"class":38},"\u002F\u002F - Each isolate has its own memory heap (no shared mutable state).\n",[32,47,49],{"class":34,"line":48},3,[32,50,51],{"class":38},"\u002F\u002F - Communication is via message passing (ports).\n",[32,53,55],{"class":34,"line":54},4,[32,56,57],{"class":38},"\u002F\u002F - No data races — no locks, no mutexes, no atomics.\n",[32,59,61],{"class":34,"line":60},5,[32,62,63],{"class":38},"\u002F\u002F\n",[32,65,67],{"class":34,"line":66},6,[32,68,69],{"class":38},"\u002F\u002F This is the Erlang\u002FAkka actor model, not the Java\u002FC++ threading model.\n",[32,71,73],{"class":34,"line":72},7,[32,74,76],{"emptyLinePlaceholder":75},true,"\n",[32,78,80],{"class":34,"line":79},8,[32,81,82],{"class":38},"\u002F\u002F ── Isolate.run: one-shot computation in a separate isolate ──\n",[32,84,86],{"class":34,"line":85},9,[32,87,88],{"class":38},"\u002F\u002F Spawns an isolate, runs the function, sends the result back, kills the isolate.\n",[32,90,92],{"class":34,"line":91},10,[32,93,94],{"class":38},"\u002F\u002F The closure and its captured values are DEEP-COPIED to the new isolate.\n",[32,96,98],{"class":34,"line":97},11,[32,99,76],{"emptyLinePlaceholder":75},[32,101,103,107,111,114,117,121,124,128],{"class":34,"line":102},12,[32,104,106],{"class":105},"snvgF","Future",[32,108,110],{"class":109},"ssxIu","\u003C",[32,112,113],{"class":105},"int",[32,115,116],{"class":109},"> ",[32,118,120],{"class":119},"sIsaT","heavySum",[32,122,123],{"class":109},"() ",[32,125,127],{"class":126},"svdQ7","async",[32,129,130],{"class":109}," {\n",[32,132,134,137,140,143,146],{"class":34,"line":133},13,[32,135,136],{"class":126},"  return",[32,138,139],{"class":105}," Isolate",[32,141,142],{"class":109},".",[32,144,145],{"class":119},"run",[32,147,148],{"class":109},"(() {\n",[32,150,152],{"class":34,"line":151},14,[32,153,154],{"class":38},"    \u002F\u002F This runs on a separate OS thread with its own heap.\n",[32,156,158],{"class":34,"line":157},15,[32,159,160],{"class":38},"    \u002F\u002F No access to the main isolate's memory — everything is copied.\n",[32,162,164,167,170,173,176],{"class":34,"line":163},16,[32,165,166],{"class":126},"    var",[32,168,169],{"class":109}," sum ",[32,171,172],{"class":126},"=",[32,174,175],{"class":105}," 0",[32,177,178],{"class":109},";\n",[32,180,182,185,188,191,194,196,198,201,203,206,209,212,215,218],{"class":34,"line":181},17,[32,183,184],{"class":126},"    for",[32,186,187],{"class":109}," (",[32,189,190],{"class":126},"var",[32,192,193],{"class":109}," i ",[32,195,172],{"class":126},[32,197,175],{"class":105},[32,199,200],{"class":109},"; i ",[32,202,110],{"class":126},[32,204,205],{"class":105}," 1000000000",[32,207,208],{"class":109},"; i",[32,210,211],{"class":126},"++",[32,213,214],{"class":109},") sum ",[32,216,217],{"class":126},"+=",[32,219,220],{"class":109}," i;\n",[32,222,224,227,230],{"class":34,"line":223},18,[32,225,226],{"class":126},"    return",[32,228,229],{"class":109}," sum;  ",[32,231,232],{"class":38},"\u002F\u002F result is deep-copied back to the main isolate\n",[32,234,236],{"class":34,"line":235},19,[32,237,238],{"class":109},"  });\n",[32,240,242],{"class":34,"line":241},20,[32,243,244],{"class":109},"}\n",[32,246,248],{"class":34,"line":247},21,[32,249,76],{"emptyLinePlaceholder":75},[32,251,253],{"class":34,"line":252},22,[32,254,255],{"class":38},"\u002F\u002F Capturing values — they're COPIED (deep copy), not shared:\n",[32,257,259,261,263,266,268,271,274,277,280,282],{"class":34,"line":258},23,[32,260,106],{"class":105},[32,262,110],{"class":109},[32,264,265],{"class":126},"void",[32,267,116],{"class":109},[32,269,270],{"class":119},"processFile",[32,272,273],{"class":109},"(",[32,275,276],{"class":105},"String",[32,278,279],{"class":109}," path) ",[32,281,127],{"class":126},[32,283,130],{"class":109},[32,285,287,290,293,295,298,300,302,304],{"class":34,"line":286},24,[32,288,289],{"class":126},"  final",[32,291,292],{"class":109}," result ",[32,294,172],{"class":126},[32,296,297],{"class":126}," await",[32,299,139],{"class":105},[32,301,142],{"class":109},[32,303,145],{"class":119},[32,305,148],{"class":109},[32,307,309],{"class":34,"line":308},25,[32,310,311],{"class":38},"    \u002F\u002F `path` was copied — modifying it here doesn't affect the original.\n",[32,313,315,318,321,323,326,329,332],{"class":34,"line":314},26,[32,316,317],{"class":126},"    final",[32,319,320],{"class":109}," content ",[32,322,172],{"class":126},[32,324,325],{"class":105}," File",[32,327,328],{"class":109},"(path).",[32,330,331],{"class":119},"readAsStringSync",[32,333,334],{"class":109},"();\n",[32,336,338,340,343,346],{"class":34,"line":337},27,[32,339,226],{"class":126},[32,341,342],{"class":109}," content.",[32,344,345],{"class":119},"toUpperCase",[32,347,334],{"class":109},[32,349,351],{"class":34,"line":350},28,[32,352,238],{"class":109},[32,354,356,359],{"class":34,"line":355},29,[32,357,358],{"class":119},"  print",[32,360,361],{"class":109},"(result);\n",[32,363,365],{"class":34,"line":364},30,[32,366,244],{"class":109},[14,368,370,373,374],{"id":369},"isolaterun-vs-isolatespawn",[29,371,372],{},"Isolate.run"," vs ",[29,375,376],{},"Isolate.spawn",[19,378,379],{"language":21},[23,380,382],{"className":25,"code":381,"language":21,"meta":27,"style":27},"import 'dart:isolate';\n\n\u002F\u002F ── Isolate.run: one-shot, fire-and-forget, returns a Future. ──\n\u002F\u002F Best for: one-off CPU-heavy work (JSON parsing, compression, sorting).\n\u002F\u002F The isolate is automatically killed after the function returns.\n\nFuture\u003CMap\u003CString, dynamic>> parseHugeJson(String json) async {\n  return Isolate.run(() => jsonDecode(json) as Map\u003CString, dynamic>);\n}\n\n\u002F\u002F ── Isolate.spawn: long-running, bidirectional communication. ──\n\u002F\u002F Best for: worker pools, event-driven workers, persistent background tasks.\n\u002F\u002F You manage the lifecycle (spawn, communicate, kill).\n\nvoid workerEntryPoint(SendPort mainSendPort) {\n  \u002F\u002F Set up a receive port for messages from the main isolate.\n  final receivePort = ReceivePort();\n  mainSendPort.send(receivePort.sendPort);  \u002F\u002F send our port back\n\n  receivePort.listen((message) {\n    \u002F\u002F Process messages from the main isolate.\n    final result = _process(message);\n    mainSendPort.send(result);  \u002F\u002F send result back\n  });\n}\n\nFuture\u003Cvoid> main() async {\n  final mainReceivePort = ReceivePort();\n  await Isolate.spawn(workerEntryPoint, mainReceivePort.sendPort);\n\n  \u002F\u002F Get the worker's send port (first message from the worker).\n  final workerSendPort = await mainReceivePort.first as SendPort;\n\n  \u002F\u002F Now we can send messages to the worker:\n  final responsePort = ReceivePort();\n  workerSendPort.send('task-1');\n  \u002F\u002F ... manage communication\n}\n",[29,383,384,395,399,404,409,414,418,454,493,497,501,506,511,516,520,535,540,554,568,572,583,588,602,615,619,623,627,646,659,674,678,684,706,711,717,731,747,753],{"__ignoreMap":27},[32,385,386,389,393],{"class":34,"line":35},[32,387,388],{"class":126},"import",[32,390,392],{"class":391},"sJ6F3"," 'dart:isolate'",[32,394,178],{"class":109},[32,396,397],{"class":34,"line":42},[32,398,76],{"emptyLinePlaceholder":75},[32,400,401],{"class":34,"line":48},[32,402,403],{"class":38},"\u002F\u002F ── Isolate.run: one-shot, fire-and-forget, returns a Future. ──\n",[32,405,406],{"class":34,"line":54},[32,407,408],{"class":38},"\u002F\u002F Best for: one-off CPU-heavy work (JSON parsing, compression, sorting).\n",[32,410,411],{"class":34,"line":60},[32,412,413],{"class":38},"\u002F\u002F The isolate is automatically killed after the function returns.\n",[32,415,416],{"class":34,"line":66},[32,417,76],{"emptyLinePlaceholder":75},[32,419,420,422,424,427,429,431,434,437,440,443,445,447,450,452],{"class":34,"line":72},[32,421,106],{"class":105},[32,423,110],{"class":109},[32,425,426],{"class":105},"Map",[32,428,110],{"class":109},[32,430,276],{"class":105},[32,432,433],{"class":109},", ",[32,435,436],{"class":105},"dynamic",[32,438,439],{"class":109},">> ",[32,441,442],{"class":119},"parseHugeJson",[32,444,273],{"class":109},[32,446,276],{"class":105},[32,448,449],{"class":109}," json) ",[32,451,127],{"class":126},[32,453,130],{"class":109},[32,455,456,458,460,462,464,467,470,473,476,479,482,484,486,488,490],{"class":34,"line":79},[32,457,136],{"class":126},[32,459,139],{"class":105},[32,461,142],{"class":109},[32,463,145],{"class":119},[32,465,466],{"class":109},"(() ",[32,468,469],{"class":126},"=>",[32,471,472],{"class":119}," jsonDecode",[32,474,475],{"class":109},"(json) ",[32,477,478],{"class":126},"as",[32,480,481],{"class":105}," Map",[32,483,110],{"class":109},[32,485,276],{"class":105},[32,487,433],{"class":109},[32,489,436],{"class":105},[32,491,492],{"class":109},">);\n",[32,494,495],{"class":34,"line":85},[32,496,244],{"class":109},[32,498,499],{"class":34,"line":91},[32,500,76],{"emptyLinePlaceholder":75},[32,502,503],{"class":34,"line":97},[32,504,505],{"class":38},"\u002F\u002F ── Isolate.spawn: long-running, bidirectional communication. ──\n",[32,507,508],{"class":34,"line":102},[32,509,510],{"class":38},"\u002F\u002F Best for: worker pools, event-driven workers, persistent background tasks.\n",[32,512,513],{"class":34,"line":133},[32,514,515],{"class":38},"\u002F\u002F You manage the lifecycle (spawn, communicate, kill).\n",[32,517,518],{"class":34,"line":151},[32,519,76],{"emptyLinePlaceholder":75},[32,521,522,524,527,529,532],{"class":34,"line":157},[32,523,265],{"class":126},[32,525,526],{"class":119}," workerEntryPoint",[32,528,273],{"class":109},[32,530,531],{"class":105},"SendPort",[32,533,534],{"class":109}," mainSendPort) {\n",[32,536,537],{"class":34,"line":163},[32,538,539],{"class":38},"  \u002F\u002F Set up a receive port for messages from the main isolate.\n",[32,541,542,544,547,549,552],{"class":34,"line":181},[32,543,289],{"class":126},[32,545,546],{"class":109}," receivePort ",[32,548,172],{"class":126},[32,550,551],{"class":105}," ReceivePort",[32,553,334],{"class":109},[32,555,556,559,562,565],{"class":34,"line":223},[32,557,558],{"class":109},"  mainSendPort.",[32,560,561],{"class":119},"send",[32,563,564],{"class":109},"(receivePort.sendPort);  ",[32,566,567],{"class":38},"\u002F\u002F send our port back\n",[32,569,570],{"class":34,"line":235},[32,571,76],{"emptyLinePlaceholder":75},[32,573,574,577,580],{"class":34,"line":241},[32,575,576],{"class":109},"  receivePort.",[32,578,579],{"class":119},"listen",[32,581,582],{"class":109},"((message) {\n",[32,584,585],{"class":34,"line":247},[32,586,587],{"class":38},"    \u002F\u002F Process messages from the main isolate.\n",[32,589,590,592,594,596,599],{"class":34,"line":252},[32,591,317],{"class":126},[32,593,292],{"class":109},[32,595,172],{"class":126},[32,597,598],{"class":119}," _process",[32,600,601],{"class":109},"(message);\n",[32,603,604,607,609,612],{"class":34,"line":258},[32,605,606],{"class":109},"    mainSendPort.",[32,608,561],{"class":119},[32,610,611],{"class":109},"(result);  ",[32,613,614],{"class":38},"\u002F\u002F send result back\n",[32,616,617],{"class":34,"line":286},[32,618,238],{"class":109},[32,620,621],{"class":34,"line":308},[32,622,244],{"class":109},[32,624,625],{"class":34,"line":314},[32,626,76],{"emptyLinePlaceholder":75},[32,628,629,631,633,635,637,640,642,644],{"class":34,"line":337},[32,630,106],{"class":105},[32,632,110],{"class":109},[32,634,265],{"class":126},[32,636,116],{"class":109},[32,638,639],{"class":119},"main",[32,641,123],{"class":109},[32,643,127],{"class":126},[32,645,130],{"class":109},[32,647,648,650,653,655,657],{"class":34,"line":350},[32,649,289],{"class":126},[32,651,652],{"class":109}," mainReceivePort ",[32,654,172],{"class":126},[32,656,551],{"class":105},[32,658,334],{"class":109},[32,660,661,664,666,668,671],{"class":34,"line":355},[32,662,663],{"class":126},"  await",[32,665,139],{"class":105},[32,667,142],{"class":109},[32,669,670],{"class":119},"spawn",[32,672,673],{"class":109},"(workerEntryPoint, mainReceivePort.sendPort);\n",[32,675,676],{"class":34,"line":364},[32,677,76],{"emptyLinePlaceholder":75},[32,679,681],{"class":34,"line":680},31,[32,682,683],{"class":38},"  \u002F\u002F Get the worker's send port (first message from the worker).\n",[32,685,687,689,692,694,696,699,701,704],{"class":34,"line":686},32,[32,688,289],{"class":126},[32,690,691],{"class":109}," workerSendPort ",[32,693,172],{"class":126},[32,695,297],{"class":126},[32,697,698],{"class":109}," mainReceivePort.first ",[32,700,478],{"class":126},[32,702,703],{"class":105}," SendPort",[32,705,178],{"class":109},[32,707,709],{"class":34,"line":708},33,[32,710,76],{"emptyLinePlaceholder":75},[32,712,714],{"class":34,"line":713},34,[32,715,716],{"class":38},"  \u002F\u002F Now we can send messages to the worker:\n",[32,718,720,722,725,727,729],{"class":34,"line":719},35,[32,721,289],{"class":126},[32,723,724],{"class":109}," responsePort ",[32,726,172],{"class":126},[32,728,551],{"class":105},[32,730,334],{"class":109},[32,732,734,737,739,741,744],{"class":34,"line":733},36,[32,735,736],{"class":109},"  workerSendPort.",[32,738,561],{"class":119},[32,740,273],{"class":109},[32,742,743],{"class":391},"'task-1'",[32,745,746],{"class":109},");\n",[32,748,750],{"class":34,"line":749},37,[32,751,752],{"class":38},"  \u002F\u002F ... manage communication\n",[32,754,756],{"class":34,"line":755},38,[32,757,244],{"class":109},[14,759,761],{"id":760},"bidirectional-communication-production-pattern","Bidirectional Communication — Production Pattern",[19,763,764],{"language":21},[23,765,767],{"className":25,"code":766,"language":21,"meta":27,"style":27},"import 'dart:isolate';\nimport 'dart:async';\n\n\u002F\u002F A reusable worker that accepts tasks and returns results.\nclass IsolateWorker {\n  late final Isolate _isolate;\n  late final SendPort _sendPort;\n  final _receivePort = ReceivePort();\n  final _pending = \u003Cint, Completer>{};\n  int _taskId = 0;\n\n  Future\u003Cvoid> start() async {\n    final ready = ReceivePort();\n    _isolate = await Isolate.spawn(\n      _entry,\n      (ready.sendPort, _receivePort.sendPort),\n      debugName: 'isolate-worker',\n    );\n    _sendPort = await ready.first as SendPort;\n\n    \u002F\u002F Route responses to the correct completer.\n    _receivePort.listen((message) {\n      if (message is _Response) {\n        final completer = _pending.remove(message.taskId);\n        if (message.error != null) {\n          completer?.completeError(message.error!);\n        } else {\n          completer?.complete(message.result);\n        }\n      }\n    });\n  }\n\n  Future\u003CT> execute\u003CT>(String task, dynamic payload) {\n    final id = _taskId++;\n    final completer = Completer\u003CT>();\n    _pending[id] = completer;\n    _sendPort.send(_Request(id, task, payload));\n    return completer.future;\n  }\n\n  void dispose() {\n    _isolate.kill(priority: Isolate.immediate);\n    _receivePort.close();\n  }\n\n  static void _entry((SendPort, SendPort) ports) {\n    final (readyPort, mainPort) = ports;\n    final receivePort = ReceivePort();\n    readyPort.send(receivePort.sendPort);\n\n    receivePort.listen((message) {\n      if (message is _Request) {\n        try {\n          final result = _dispatchTask(message.task, message.payload);\n          mainPort.send(_Response(message.taskId, result, null));\n        } catch (e) {\n          mainPort.send(_Response(message.taskId, null, e.toString()));\n        }\n      }\n    });\n  }\n\n  static dynamic _dispatchTask(String task, dynamic payload) {\n    return switch (task) {\n      'sort' => (payload as List).cast\u003Cint>()..sort(),\n      'parse' => jsonDecode(payload as String),\n      'hash' => payload.hashCode,  \u002F\u002F placeholder for real work\n      _ => throw UnimplementedError('Unknown task: $task'),\n    };\n  }\n}\n\nclass _Request {\n  final int taskId;\n  final String task;\n  final dynamic payload;\n  const _Request(this.taskId, this.task, this.payload);\n}\n\nclass _Response {\n  final int taskId;\n  final dynamic result;\n  final String? error;\n  const _Response(this.taskId, this.result, this.error);\n}\n",[29,768,769,777,786,790,795,805,818,829,842,867,881,885,905,918,936,941,946,960,965,983,987,992,1001,1018,1037,1053,1074,1084,1098,1103,1108,1113,1118,1122,1153,1169,1187,1197,1212,1220,1225,1230,1242,1261,1271,1276,1281,1305,1318,1331,1342,1347,1357,1371,1379,1395,1417,1428,1453,1458,1463,1468,1473,1478,1498,1509,1545,1566,1580,1610,1616,1621,1626,1631,1640,1651,1661,1671,1697,1702,1707,1716,1725,1735,1747,1770],{"__ignoreMap":27},[32,770,771,773,775],{"class":34,"line":35},[32,772,388],{"class":126},[32,774,392],{"class":391},[32,776,178],{"class":109},[32,778,779,781,784],{"class":34,"line":42},[32,780,388],{"class":126},[32,782,783],{"class":391}," 'dart:async'",[32,785,178],{"class":109},[32,787,788],{"class":34,"line":48},[32,789,76],{"emptyLinePlaceholder":75},[32,791,792],{"class":34,"line":54},[32,793,794],{"class":38},"\u002F\u002F A reusable worker that accepts tasks and returns results.\n",[32,796,797,800,803],{"class":34,"line":60},[32,798,799],{"class":126},"class",[32,801,802],{"class":105}," IsolateWorker",[32,804,130],{"class":109},[32,806,807,810,813,815],{"class":34,"line":66},[32,808,809],{"class":126},"  late",[32,811,812],{"class":126}," final",[32,814,139],{"class":105},[32,816,817],{"class":109}," _isolate;\n",[32,819,820,822,824,826],{"class":34,"line":72},[32,821,809],{"class":126},[32,823,812],{"class":126},[32,825,703],{"class":105},[32,827,828],{"class":109}," _sendPort;\n",[32,830,831,833,836,838,840],{"class":34,"line":79},[32,832,289],{"class":126},[32,834,835],{"class":109}," _receivePort ",[32,837,172],{"class":126},[32,839,551],{"class":105},[32,841,334],{"class":109},[32,843,844,846,849,851,854,856,858,861,864],{"class":34,"line":85},[32,845,289],{"class":126},[32,847,848],{"class":109}," _pending ",[32,850,172],{"class":126},[32,852,853],{"class":126}," \u003C",[32,855,113],{"class":105},[32,857,433],{"class":109},[32,859,860],{"class":105},"Completer",[32,862,863],{"class":126},">",[32,865,866],{"class":109},"{};\n",[32,868,869,872,875,877,879],{"class":34,"line":91},[32,870,871],{"class":105},"  int",[32,873,874],{"class":109}," _taskId ",[32,876,172],{"class":126},[32,878,175],{"class":105},[32,880,178],{"class":109},[32,882,883],{"class":34,"line":97},[32,884,76],{"emptyLinePlaceholder":75},[32,886,887,890,892,894,896,899,901,903],{"class":34,"line":102},[32,888,889],{"class":105},"  Future",[32,891,110],{"class":109},[32,893,265],{"class":126},[32,895,116],{"class":109},[32,897,898],{"class":119},"start",[32,900,123],{"class":109},[32,902,127],{"class":126},[32,904,130],{"class":109},[32,906,907,909,912,914,916],{"class":34,"line":133},[32,908,317],{"class":126},[32,910,911],{"class":109}," ready ",[32,913,172],{"class":126},[32,915,551],{"class":105},[32,917,334],{"class":109},[32,919,920,923,925,927,929,931,933],{"class":34,"line":151},[32,921,922],{"class":109},"    _isolate ",[32,924,172],{"class":126},[32,926,297],{"class":126},[32,928,139],{"class":105},[32,930,142],{"class":109},[32,932,670],{"class":119},[32,934,935],{"class":109},"(\n",[32,937,938],{"class":34,"line":157},[32,939,940],{"class":109},"      _entry,\n",[32,942,943],{"class":34,"line":163},[32,944,945],{"class":109},"      (ready.sendPort, _receivePort.sendPort),\n",[32,947,948,951,954,957],{"class":34,"line":181},[32,949,950],{"class":109},"      debugName",[32,952,953],{"class":126},":",[32,955,956],{"class":391}," 'isolate-worker'",[32,958,959],{"class":109},",\n",[32,961,962],{"class":34,"line":223},[32,963,964],{"class":109},"    );\n",[32,966,967,970,972,974,977,979,981],{"class":34,"line":235},[32,968,969],{"class":109},"    _sendPort ",[32,971,172],{"class":126},[32,973,297],{"class":126},[32,975,976],{"class":109}," ready.first ",[32,978,478],{"class":126},[32,980,703],{"class":105},[32,982,178],{"class":109},[32,984,985],{"class":34,"line":241},[32,986,76],{"emptyLinePlaceholder":75},[32,988,989],{"class":34,"line":247},[32,990,991],{"class":38},"    \u002F\u002F Route responses to the correct completer.\n",[32,993,994,997,999],{"class":34,"line":252},[32,995,996],{"class":109},"    _receivePort.",[32,998,579],{"class":119},[32,1000,582],{"class":109},[32,1002,1003,1006,1009,1012,1015],{"class":34,"line":258},[32,1004,1005],{"class":126},"      if",[32,1007,1008],{"class":109}," (message ",[32,1010,1011],{"class":126},"is",[32,1013,1014],{"class":105}," _Response",[32,1016,1017],{"class":109},") {\n",[32,1019,1020,1023,1026,1028,1031,1034],{"class":34,"line":286},[32,1021,1022],{"class":126},"        final",[32,1024,1025],{"class":109}," completer ",[32,1027,172],{"class":126},[32,1029,1030],{"class":109}," _pending.",[32,1032,1033],{"class":119},"remove",[32,1035,1036],{"class":109},"(message.taskId);\n",[32,1038,1039,1042,1045,1048,1051],{"class":34,"line":308},[32,1040,1041],{"class":126},"        if",[32,1043,1044],{"class":109}," (message.error ",[32,1046,1047],{"class":126},"!=",[32,1049,1050],{"class":105}," null",[32,1052,1017],{"class":109},[32,1054,1055,1058,1061,1063,1066,1069,1072],{"class":34,"line":314},[32,1056,1057],{"class":109},"          completer",[32,1059,1060],{"class":126},"?",[32,1062,142],{"class":109},[32,1064,1065],{"class":119},"completeError",[32,1067,1068],{"class":109},"(message.error",[32,1070,1071],{"class":126},"!",[32,1073,746],{"class":109},[32,1075,1076,1079,1082],{"class":34,"line":337},[32,1077,1078],{"class":109},"        } ",[32,1080,1081],{"class":126},"else",[32,1083,130],{"class":109},[32,1085,1086,1088,1090,1092,1095],{"class":34,"line":350},[32,1087,1057],{"class":109},[32,1089,1060],{"class":126},[32,1091,142],{"class":109},[32,1093,1094],{"class":119},"complete",[32,1096,1097],{"class":109},"(message.result);\n",[32,1099,1100],{"class":34,"line":355},[32,1101,1102],{"class":109},"        }\n",[32,1104,1105],{"class":34,"line":364},[32,1106,1107],{"class":109},"      }\n",[32,1109,1110],{"class":34,"line":680},[32,1111,1112],{"class":109},"    });\n",[32,1114,1115],{"class":34,"line":686},[32,1116,1117],{"class":109},"  }\n",[32,1119,1120],{"class":34,"line":708},[32,1121,76],{"emptyLinePlaceholder":75},[32,1123,1124,1126,1128,1131,1133,1136,1138,1140,1143,1145,1148,1150],{"class":34,"line":713},[32,1125,889],{"class":105},[32,1127,110],{"class":109},[32,1129,1130],{"class":105},"T",[32,1132,116],{"class":109},[32,1134,1135],{"class":119},"execute",[32,1137,110],{"class":109},[32,1139,1130],{"class":105},[32,1141,1142],{"class":109},">(",[32,1144,276],{"class":105},[32,1146,1147],{"class":109}," task, ",[32,1149,436],{"class":105},[32,1151,1152],{"class":109}," payload) {\n",[32,1154,1155,1157,1160,1162,1165,1167],{"class":34,"line":719},[32,1156,317],{"class":126},[32,1158,1159],{"class":109}," id ",[32,1161,172],{"class":126},[32,1163,1164],{"class":109}," _taskId",[32,1166,211],{"class":126},[32,1168,178],{"class":109},[32,1170,1171,1173,1175,1177,1180,1182,1184],{"class":34,"line":733},[32,1172,317],{"class":126},[32,1174,1025],{"class":109},[32,1176,172],{"class":126},[32,1178,1179],{"class":105}," Completer",[32,1181,110],{"class":109},[32,1183,1130],{"class":105},[32,1185,1186],{"class":109},">();\n",[32,1188,1189,1192,1194],{"class":34,"line":749},[32,1190,1191],{"class":109},"    _pending[id] ",[32,1193,172],{"class":126},[32,1195,1196],{"class":109}," completer;\n",[32,1198,1199,1202,1204,1206,1209],{"class":34,"line":755},[32,1200,1201],{"class":109},"    _sendPort.",[32,1203,561],{"class":119},[32,1205,273],{"class":109},[32,1207,1208],{"class":105},"_Request",[32,1210,1211],{"class":109},"(id, task, payload));\n",[32,1213,1215,1217],{"class":34,"line":1214},39,[32,1216,226],{"class":126},[32,1218,1219],{"class":109}," completer.future;\n",[32,1221,1223],{"class":34,"line":1222},40,[32,1224,1117],{"class":109},[32,1226,1228],{"class":34,"line":1227},41,[32,1229,76],{"emptyLinePlaceholder":75},[32,1231,1233,1236,1239],{"class":34,"line":1232},42,[32,1234,1235],{"class":126},"  void",[32,1237,1238],{"class":119}," dispose",[32,1240,1241],{"class":109},"() {\n",[32,1243,1245,1248,1251,1254,1256,1258],{"class":34,"line":1244},43,[32,1246,1247],{"class":109},"    _isolate.",[32,1249,1250],{"class":119},"kill",[32,1252,1253],{"class":109},"(priority",[32,1255,953],{"class":126},[32,1257,139],{"class":105},[32,1259,1260],{"class":109},".immediate);\n",[32,1262,1264,1266,1269],{"class":34,"line":1263},44,[32,1265,996],{"class":109},[32,1267,1268],{"class":119},"close",[32,1270,334],{"class":109},[32,1272,1274],{"class":34,"line":1273},45,[32,1275,1117],{"class":109},[32,1277,1279],{"class":34,"line":1278},46,[32,1280,76],{"emptyLinePlaceholder":75},[32,1282,1284,1287,1290,1293,1296,1298,1300,1302],{"class":34,"line":1283},47,[32,1285,1286],{"class":126},"  static",[32,1288,1289],{"class":126}," void",[32,1291,1292],{"class":119}," _entry",[32,1294,1295],{"class":109},"((",[32,1297,531],{"class":105},[32,1299,433],{"class":109},[32,1301,531],{"class":105},[32,1303,1304],{"class":109},") ports) {\n",[32,1306,1308,1310,1313,1315],{"class":34,"line":1307},48,[32,1309,317],{"class":126},[32,1311,1312],{"class":109}," (readyPort, mainPort) ",[32,1314,172],{"class":126},[32,1316,1317],{"class":109}," ports;\n",[32,1319,1321,1323,1325,1327,1329],{"class":34,"line":1320},49,[32,1322,317],{"class":126},[32,1324,546],{"class":109},[32,1326,172],{"class":126},[32,1328,551],{"class":105},[32,1330,334],{"class":109},[32,1332,1334,1337,1339],{"class":34,"line":1333},50,[32,1335,1336],{"class":109},"    readyPort.",[32,1338,561],{"class":119},[32,1340,1341],{"class":109},"(receivePort.sendPort);\n",[32,1343,1345],{"class":34,"line":1344},51,[32,1346,76],{"emptyLinePlaceholder":75},[32,1348,1350,1353,1355],{"class":34,"line":1349},52,[32,1351,1352],{"class":109},"    receivePort.",[32,1354,579],{"class":119},[32,1356,582],{"class":109},[32,1358,1360,1362,1364,1366,1369],{"class":34,"line":1359},53,[32,1361,1005],{"class":126},[32,1363,1008],{"class":109},[32,1365,1011],{"class":126},[32,1367,1368],{"class":105}," _Request",[32,1370,1017],{"class":109},[32,1372,1374,1377],{"class":34,"line":1373},54,[32,1375,1376],{"class":126},"        try",[32,1378,130],{"class":109},[32,1380,1382,1385,1387,1389,1392],{"class":34,"line":1381},55,[32,1383,1384],{"class":126},"          final",[32,1386,292],{"class":109},[32,1388,172],{"class":126},[32,1390,1391],{"class":119}," _dispatchTask",[32,1393,1394],{"class":109},"(message.task, message.payload);\n",[32,1396,1398,1401,1403,1405,1408,1411,1414],{"class":34,"line":1397},56,[32,1399,1400],{"class":109},"          mainPort.",[32,1402,561],{"class":119},[32,1404,273],{"class":109},[32,1406,1407],{"class":105},"_Response",[32,1409,1410],{"class":109},"(message.taskId, result, ",[32,1412,1413],{"class":105},"null",[32,1415,1416],{"class":109},"));\n",[32,1418,1420,1422,1425],{"class":34,"line":1419},57,[32,1421,1078],{"class":109},[32,1423,1424],{"class":126},"catch",[32,1426,1427],{"class":109}," (e) {\n",[32,1429,1431,1433,1435,1437,1439,1442,1444,1447,1450],{"class":34,"line":1430},58,[32,1432,1400],{"class":109},[32,1434,561],{"class":119},[32,1436,273],{"class":109},[32,1438,1407],{"class":105},[32,1440,1441],{"class":109},"(message.taskId, ",[32,1443,1413],{"class":105},[32,1445,1446],{"class":109},", e.",[32,1448,1449],{"class":119},"toString",[32,1451,1452],{"class":109},"()));\n",[32,1454,1456],{"class":34,"line":1455},59,[32,1457,1102],{"class":109},[32,1459,1461],{"class":34,"line":1460},60,[32,1462,1107],{"class":109},[32,1464,1466],{"class":34,"line":1465},61,[32,1467,1112],{"class":109},[32,1469,1471],{"class":34,"line":1470},62,[32,1472,1117],{"class":109},[32,1474,1476],{"class":34,"line":1475},63,[32,1477,76],{"emptyLinePlaceholder":75},[32,1479,1481,1483,1486,1488,1490,1492,1494,1496],{"class":34,"line":1480},64,[32,1482,1286],{"class":126},[32,1484,1485],{"class":105}," dynamic",[32,1487,1391],{"class":119},[32,1489,273],{"class":109},[32,1491,276],{"class":105},[32,1493,1147],{"class":109},[32,1495,436],{"class":105},[32,1497,1152],{"class":109},[32,1499,1501,1503,1506],{"class":34,"line":1500},65,[32,1502,226],{"class":126},[32,1504,1505],{"class":126}," switch",[32,1507,1508],{"class":109}," (task) {\n",[32,1510,1512,1515,1518,1521,1523,1526,1529,1532,1534,1536,1539,1542],{"class":34,"line":1511},66,[32,1513,1514],{"class":391},"      'sort'",[32,1516,1517],{"class":126}," =>",[32,1519,1520],{"class":109}," (payload ",[32,1522,478],{"class":126},[32,1524,1525],{"class":105}," List",[32,1527,1528],{"class":109},").",[32,1530,1531],{"class":119},"cast",[32,1533,110],{"class":109},[32,1535,113],{"class":105},[32,1537,1538],{"class":109},">()..",[32,1540,1541],{"class":119},"sort",[32,1543,1544],{"class":109},"(),\n",[32,1546,1548,1551,1553,1555,1558,1560,1563],{"class":34,"line":1547},67,[32,1549,1550],{"class":391},"      'parse'",[32,1552,1517],{"class":126},[32,1554,472],{"class":119},[32,1556,1557],{"class":109},"(payload ",[32,1559,478],{"class":126},[32,1561,1562],{"class":105}," String",[32,1564,1565],{"class":109},"),\n",[32,1567,1569,1572,1574,1577],{"class":34,"line":1568},68,[32,1570,1571],{"class":391},"      'hash'",[32,1573,1517],{"class":126},[32,1575,1576],{"class":109}," payload.hashCode,  ",[32,1578,1579],{"class":38},"\u002F\u002F placeholder for real work\n",[32,1581,1583,1586,1588,1591,1594,1596,1599,1602,1605,1608],{"class":34,"line":1582},69,[32,1584,1585],{"class":109},"      _ ",[32,1587,469],{"class":126},[32,1589,1590],{"class":126}," throw",[32,1592,1593],{"class":105}," UnimplementedError",[32,1595,273],{"class":109},[32,1597,1598],{"class":391},"'Unknown task: ",[32,1600,1601],{"class":391},"$",[32,1603,1604],{"class":105},"task",[32,1606,1607],{"class":391},"'",[32,1609,1565],{"class":109},[32,1611,1613],{"class":34,"line":1612},70,[32,1614,1615],{"class":109},"    };\n",[32,1617,1619],{"class":34,"line":1618},71,[32,1620,1117],{"class":109},[32,1622,1624],{"class":34,"line":1623},72,[32,1625,244],{"class":109},[32,1627,1629],{"class":34,"line":1628},73,[32,1630,76],{"emptyLinePlaceholder":75},[32,1632,1634,1636,1638],{"class":34,"line":1633},74,[32,1635,799],{"class":126},[32,1637,1368],{"class":105},[32,1639,130],{"class":109},[32,1641,1643,1645,1648],{"class":34,"line":1642},75,[32,1644,289],{"class":126},[32,1646,1647],{"class":105}," int",[32,1649,1650],{"class":109}," taskId;\n",[32,1652,1654,1656,1658],{"class":34,"line":1653},76,[32,1655,289],{"class":126},[32,1657,1562],{"class":105},[32,1659,1660],{"class":109}," task;\n",[32,1662,1664,1666,1668],{"class":34,"line":1663},77,[32,1665,289],{"class":126},[32,1667,1485],{"class":105},[32,1669,1670],{"class":109}," payload;\n",[32,1672,1674,1677,1679,1681,1684,1687,1689,1692,1694],{"class":34,"line":1673},78,[32,1675,1676],{"class":126},"  const",[32,1678,1368],{"class":105},[32,1680,273],{"class":109},[32,1682,1683],{"class":105},"this",[32,1685,1686],{"class":109},".taskId, ",[32,1688,1683],{"class":105},[32,1690,1691],{"class":109},".task, ",[32,1693,1683],{"class":105},[32,1695,1696],{"class":109},".payload);\n",[32,1698,1700],{"class":34,"line":1699},79,[32,1701,244],{"class":109},[32,1703,1705],{"class":34,"line":1704},80,[32,1706,76],{"emptyLinePlaceholder":75},[32,1708,1710,1712,1714],{"class":34,"line":1709},81,[32,1711,799],{"class":126},[32,1713,1014],{"class":105},[32,1715,130],{"class":109},[32,1717,1719,1721,1723],{"class":34,"line":1718},82,[32,1720,289],{"class":126},[32,1722,1647],{"class":105},[32,1724,1650],{"class":109},[32,1726,1728,1730,1732],{"class":34,"line":1727},83,[32,1729,289],{"class":126},[32,1731,1485],{"class":105},[32,1733,1734],{"class":109}," result;\n",[32,1736,1738,1740,1742,1744],{"class":34,"line":1737},84,[32,1739,289],{"class":126},[32,1741,1562],{"class":105},[32,1743,1060],{"class":126},[32,1745,1746],{"class":109}," error;\n",[32,1748,1750,1752,1754,1756,1758,1760,1762,1765,1767],{"class":34,"line":1749},85,[32,1751,1676],{"class":126},[32,1753,1014],{"class":105},[32,1755,273],{"class":109},[32,1757,1683],{"class":105},[32,1759,1686],{"class":109},[32,1761,1683],{"class":105},[32,1763,1764],{"class":109},".result, ",[32,1766,1683],{"class":105},[32,1768,1769],{"class":109},".error);\n",[32,1771,1773],{"class":34,"line":1772},86,[32,1774,244],{"class":109},[14,1776,1778],{"id":1777},"transferabletypeddata-zero-copy-transfer","TransferableTypedData — Zero-Copy Transfer",[19,1780,1781],{"language":21},[23,1782,1784],{"className":25,"code":1783,"language":21,"meta":27,"style":27},"import 'dart:isolate';\nimport 'dart:typed_data';\n\n\u002F\u002F By default, messages between isolates are DEEP-COPIED (full serialization).\n\u002F\u002F For large byte buffers (Uint8List), this is O(n) in memory and time.\n\u002F\u002F TransferableTypedData transfers ownership — zero copy, O(1).\n\n\u002F\u002F ❌ Anti-pattern: sending a large Uint8List directly — it's deep-copied.\nFuture\u003CUint8List> processImageBad(Uint8List pixels) async {\n  return Isolate.run(() {\n    \u002F\u002F `pixels` was deep-copied to this isolate — 2x memory usage.\n    return _transformPixels(pixels);\n  });\n}\n\n\u002F\u002F ✓ Correct: TransferableTypedData — zero-copy transfer.\nFuture\u003CUint8List> processImageGood(Uint8List pixels) async {\n  \u002F\u002F Wrap for transfer to the isolate:\n  final transferable = TransferableTypedData.fromList([pixels]);\n  final result = await Isolate.run(() {\n    \u002F\u002F Materialize in the worker — the data is moved, not copied.\n    final data = transferable.materialize().asUint8List();\n    return _transformPixels(data);\n  });\n  \u002F\u002F The result is copied back (small result, acceptable).\n  \u002F\u002F For large results, wrap in TransferableTypedData again.\n  return result;\n}\n\nUint8List _transformPixels(Uint8List pixels) {\n  \u002F\u002F ... image processing\n  return pixels;\n}\n",[29,1785,1786,1794,1803,1807,1812,1817,1822,1826,1831,1856,1868,1873,1883,1887,1891,1895,1900,1923,1928,1948,1966,1971,1994,2003,2007,2012,2017,2023,2027,2031,2044,2049,2056],{"__ignoreMap":27},[32,1787,1788,1790,1792],{"class":34,"line":35},[32,1789,388],{"class":126},[32,1791,392],{"class":391},[32,1793,178],{"class":109},[32,1795,1796,1798,1801],{"class":34,"line":42},[32,1797,388],{"class":126},[32,1799,1800],{"class":391}," 'dart:typed_data'",[32,1802,178],{"class":109},[32,1804,1805],{"class":34,"line":48},[32,1806,76],{"emptyLinePlaceholder":75},[32,1808,1809],{"class":34,"line":54},[32,1810,1811],{"class":38},"\u002F\u002F By default, messages between isolates are DEEP-COPIED (full serialization).\n",[32,1813,1814],{"class":34,"line":60},[32,1815,1816],{"class":38},"\u002F\u002F For large byte buffers (Uint8List), this is O(n) in memory and time.\n",[32,1818,1819],{"class":34,"line":66},[32,1820,1821],{"class":38},"\u002F\u002F TransferableTypedData transfers ownership — zero copy, O(1).\n",[32,1823,1824],{"class":34,"line":72},[32,1825,76],{"emptyLinePlaceholder":75},[32,1827,1828],{"class":34,"line":79},[32,1829,1830],{"class":38},"\u002F\u002F ❌ Anti-pattern: sending a large Uint8List directly — it's deep-copied.\n",[32,1832,1833,1835,1837,1840,1842,1845,1847,1849,1852,1854],{"class":34,"line":85},[32,1834,106],{"class":105},[32,1836,110],{"class":109},[32,1838,1839],{"class":105},"Uint8List",[32,1841,116],{"class":109},[32,1843,1844],{"class":119},"processImageBad",[32,1846,273],{"class":109},[32,1848,1839],{"class":105},[32,1850,1851],{"class":109}," pixels) ",[32,1853,127],{"class":126},[32,1855,130],{"class":109},[32,1857,1858,1860,1862,1864,1866],{"class":34,"line":91},[32,1859,136],{"class":126},[32,1861,139],{"class":105},[32,1863,142],{"class":109},[32,1865,145],{"class":119},[32,1867,148],{"class":109},[32,1869,1870],{"class":34,"line":97},[32,1871,1872],{"class":38},"    \u002F\u002F `pixels` was deep-copied to this isolate — 2x memory usage.\n",[32,1874,1875,1877,1880],{"class":34,"line":102},[32,1876,226],{"class":126},[32,1878,1879],{"class":119}," _transformPixels",[32,1881,1882],{"class":109},"(pixels);\n",[32,1884,1885],{"class":34,"line":133},[32,1886,238],{"class":109},[32,1888,1889],{"class":34,"line":151},[32,1890,244],{"class":109},[32,1892,1893],{"class":34,"line":157},[32,1894,76],{"emptyLinePlaceholder":75},[32,1896,1897],{"class":34,"line":163},[32,1898,1899],{"class":38},"\u002F\u002F ✓ Correct: TransferableTypedData — zero-copy transfer.\n",[32,1901,1902,1904,1906,1908,1910,1913,1915,1917,1919,1921],{"class":34,"line":181},[32,1903,106],{"class":105},[32,1905,110],{"class":109},[32,1907,1839],{"class":105},[32,1909,116],{"class":109},[32,1911,1912],{"class":119},"processImageGood",[32,1914,273],{"class":109},[32,1916,1839],{"class":105},[32,1918,1851],{"class":109},[32,1920,127],{"class":126},[32,1922,130],{"class":109},[32,1924,1925],{"class":34,"line":223},[32,1926,1927],{"class":38},"  \u002F\u002F Wrap for transfer to the isolate:\n",[32,1929,1930,1932,1935,1937,1940,1942,1945],{"class":34,"line":235},[32,1931,289],{"class":126},[32,1933,1934],{"class":109}," transferable ",[32,1936,172],{"class":126},[32,1938,1939],{"class":105}," TransferableTypedData",[32,1941,142],{"class":109},[32,1943,1944],{"class":119},"fromList",[32,1946,1947],{"class":109},"([pixels]);\n",[32,1949,1950,1952,1954,1956,1958,1960,1962,1964],{"class":34,"line":241},[32,1951,289],{"class":126},[32,1953,292],{"class":109},[32,1955,172],{"class":126},[32,1957,297],{"class":126},[32,1959,139],{"class":105},[32,1961,142],{"class":109},[32,1963,145],{"class":119},[32,1965,148],{"class":109},[32,1967,1968],{"class":34,"line":247},[32,1969,1970],{"class":38},"    \u002F\u002F Materialize in the worker — the data is moved, not copied.\n",[32,1972,1973,1975,1978,1980,1983,1986,1989,1992],{"class":34,"line":252},[32,1974,317],{"class":126},[32,1976,1977],{"class":109}," data ",[32,1979,172],{"class":126},[32,1981,1982],{"class":109}," transferable.",[32,1984,1985],{"class":119},"materialize",[32,1987,1988],{"class":109},"().",[32,1990,1991],{"class":119},"asUint8List",[32,1993,334],{"class":109},[32,1995,1996,1998,2000],{"class":34,"line":258},[32,1997,226],{"class":126},[32,1999,1879],{"class":119},[32,2001,2002],{"class":109},"(data);\n",[32,2004,2005],{"class":34,"line":286},[32,2006,238],{"class":109},[32,2008,2009],{"class":34,"line":308},[32,2010,2011],{"class":38},"  \u002F\u002F The result is copied back (small result, acceptable).\n",[32,2013,2014],{"class":34,"line":314},[32,2015,2016],{"class":38},"  \u002F\u002F For large results, wrap in TransferableTypedData again.\n",[32,2018,2019,2021],{"class":34,"line":337},[32,2020,136],{"class":126},[32,2022,1734],{"class":109},[32,2024,2025],{"class":34,"line":350},[32,2026,244],{"class":109},[32,2028,2029],{"class":34,"line":355},[32,2030,76],{"emptyLinePlaceholder":75},[32,2032,2033,2035,2037,2039,2041],{"class":34,"line":364},[32,2034,1839],{"class":105},[32,2036,1879],{"class":119},[32,2038,273],{"class":109},[32,2040,1839],{"class":105},[32,2042,2043],{"class":109}," pixels) {\n",[32,2045,2046],{"class":34,"line":680},[32,2047,2048],{"class":38},"  \u002F\u002F ... image processing\n",[32,2050,2051,2053],{"class":34,"line":686},[32,2052,136],{"class":126},[32,2054,2055],{"class":109}," pixels;\n",[32,2057,2058],{"class":34,"line":708},[32,2059,244],{"class":109},[14,2061,2063],{"id":2062},"worker-pool-reusing-isolates","Worker Pool — Reusing Isolates",[19,2065,2066],{"language":21},[23,2067,2069],{"className":25,"code":2068,"language":21,"meta":27,"style":27},"import 'dart:isolate';\nimport 'dart:async';\n\n\u002F\u002F Spawning an isolate costs ~50ms. For many small tasks, spawn once and reuse.\nclass WorkerPool {\n  final int _size;\n  final List\u003C_Worker> _workers = [];\n  final _idle = \u003C_Worker>[];\n  final _queue = \u003C_Task>[];\n\n  WorkerPool(this._size);\n\n  Future\u003Cvoid> start() async {\n    for (var i = 0; i \u003C _size; i++) {\n      final worker = await _Worker.spawn('worker-$i');\n      _workers.add(worker);\n      _idle.add(worker);\n    }\n    _processQueue();\n  }\n\n  Future\u003CT> submit\u003CT>(dynamic Function() task) {\n    final completer = Completer\u003CT>();\n    _queue.add(_Task(task, completer));\n    _processQueue();\n    return completer.future;\n  }\n\n  void _processQueue() {\n    while (_idle.isNotEmpty && _queue.isNotEmpty) {\n      final worker = _idle.removeLast();\n      final task = _queue.removeAt(0);\n      worker.execute(task).then((_) => _idle.add(worker));\n    }\n  }\n\n  void dispose() {\n    for (var w in _workers) w.dispose();\n  }\n}\n\nclass _Task {\n  final dynamic Function() fn;\n  final Completer completer;\n  _Task(this.fn, this.completer);\n}\n\nclass _Worker {\n  final Isolate isolate;\n  final SendPort sendPort;\n  final ReceivePort receivePort;\n\n  _Worker(this.isolate, this.sendPort, this.receivePort);\n\n  static Future\u003C_Worker> spawn(String debugName) async {\n    final receivePort = ReceivePort();\n    final isolate = await Isolate.spawn(\n      _entry,\n      receivePort.sendPort,\n      debugName: debugName,\n    );\n    final sendPort = await receivePort.first as SendPort;\n    return _Worker(isolate, sendPort, receivePort);\n  }\n\n  Future\u003Cdynamic> execute(_Task task) async {\n    sendPort.send(task.fn);\n    final result = await receivePort.first;\n    task.completer.complete(result);\n    return result;\n  }\n\n  void dispose() {\n    isolate.kill();\n    receivePort.close();\n  }\n\n  static void _entry(SendPort mainPort) {\n    final receivePort = ReceivePort();\n    mainPort.send(receivePort.sendPort);\n    receivePort.listen((fn) {\n      final result = (fn as dynamic Function())();\n      mainPort.send(result);\n    });\n  }\n}\n",[29,2070,2071,2079,2087,2091,2096,2105,2114,2133,2151,2169,2173,2185,2189,2207,2232,2265,2276,2285,2290,2297,2301,2305,2332,2348,2362,2368,2374,2378,2382,2391,2405,2421,2443,2468,2472,2476,2480,2488,2510,2514,2518,2522,2531,2542,2550,2567,2571,2575,2583,2592,2601,2610,2614,2636,2640,2666,2678,2697,2701,2706,2715,2719,2739,2748,2752,2756,2779,2789,2802,2811,2817,2821,2825,2833,2842,2850,2854,2858,2873,2885,2894,2903,2923,2932,2936,2940],{"__ignoreMap":27},[32,2072,2073,2075,2077],{"class":34,"line":35},[32,2074,388],{"class":126},[32,2076,392],{"class":391},[32,2078,178],{"class":109},[32,2080,2081,2083,2085],{"class":34,"line":42},[32,2082,388],{"class":126},[32,2084,783],{"class":391},[32,2086,178],{"class":109},[32,2088,2089],{"class":34,"line":48},[32,2090,76],{"emptyLinePlaceholder":75},[32,2092,2093],{"class":34,"line":54},[32,2094,2095],{"class":38},"\u002F\u002F Spawning an isolate costs ~50ms. For many small tasks, spawn once and reuse.\n",[32,2097,2098,2100,2103],{"class":34,"line":60},[32,2099,799],{"class":126},[32,2101,2102],{"class":105}," WorkerPool",[32,2104,130],{"class":109},[32,2106,2107,2109,2111],{"class":34,"line":66},[32,2108,289],{"class":126},[32,2110,1647],{"class":105},[32,2112,2113],{"class":109}," _size;\n",[32,2115,2116,2118,2120,2122,2125,2128,2130],{"class":34,"line":72},[32,2117,289],{"class":126},[32,2119,1525],{"class":105},[32,2121,110],{"class":109},[32,2123,2124],{"class":105},"_Worker",[32,2126,2127],{"class":109},"> _workers ",[32,2129,172],{"class":126},[32,2131,2132],{"class":109}," [];\n",[32,2134,2135,2137,2140,2142,2144,2146,2148],{"class":34,"line":79},[32,2136,289],{"class":126},[32,2138,2139],{"class":109}," _idle ",[32,2141,172],{"class":126},[32,2143,853],{"class":126},[32,2145,2124],{"class":105},[32,2147,863],{"class":126},[32,2149,2150],{"class":109},"[];\n",[32,2152,2153,2155,2158,2160,2162,2165,2167],{"class":34,"line":85},[32,2154,289],{"class":126},[32,2156,2157],{"class":109}," _queue ",[32,2159,172],{"class":126},[32,2161,853],{"class":126},[32,2163,2164],{"class":105},"_Task",[32,2166,863],{"class":126},[32,2168,2150],{"class":109},[32,2170,2171],{"class":34,"line":91},[32,2172,76],{"emptyLinePlaceholder":75},[32,2174,2175,2178,2180,2182],{"class":34,"line":97},[32,2176,2177],{"class":105},"  WorkerPool",[32,2179,273],{"class":109},[32,2181,1683],{"class":105},[32,2183,2184],{"class":109},"._size);\n",[32,2186,2187],{"class":34,"line":102},[32,2188,76],{"emptyLinePlaceholder":75},[32,2190,2191,2193,2195,2197,2199,2201,2203,2205],{"class":34,"line":133},[32,2192,889],{"class":105},[32,2194,110],{"class":109},[32,2196,265],{"class":126},[32,2198,116],{"class":109},[32,2200,898],{"class":119},[32,2202,123],{"class":109},[32,2204,127],{"class":126},[32,2206,130],{"class":109},[32,2208,2209,2211,2213,2215,2217,2219,2221,2223,2225,2228,2230],{"class":34,"line":151},[32,2210,184],{"class":126},[32,2212,187],{"class":109},[32,2214,190],{"class":126},[32,2216,193],{"class":109},[32,2218,172],{"class":126},[32,2220,175],{"class":105},[32,2222,200],{"class":109},[32,2224,110],{"class":126},[32,2226,2227],{"class":109}," _size; i",[32,2229,211],{"class":126},[32,2231,1017],{"class":109},[32,2233,2234,2237,2240,2242,2244,2247,2249,2251,2253,2256,2258,2261,2263],{"class":34,"line":157},[32,2235,2236],{"class":126},"      final",[32,2238,2239],{"class":109}," worker ",[32,2241,172],{"class":126},[32,2243,297],{"class":126},[32,2245,2246],{"class":105}," _Worker",[32,2248,142],{"class":109},[32,2250,670],{"class":119},[32,2252,273],{"class":109},[32,2254,2255],{"class":391},"'worker-",[32,2257,1601],{"class":391},[32,2259,2260],{"class":105},"i",[32,2262,1607],{"class":391},[32,2264,746],{"class":109},[32,2266,2267,2270,2273],{"class":34,"line":163},[32,2268,2269],{"class":109},"      _workers.",[32,2271,2272],{"class":119},"add",[32,2274,2275],{"class":109},"(worker);\n",[32,2277,2278,2281,2283],{"class":34,"line":181},[32,2279,2280],{"class":109},"      _idle.",[32,2282,2272],{"class":119},[32,2284,2275],{"class":109},[32,2286,2287],{"class":34,"line":223},[32,2288,2289],{"class":109},"    }\n",[32,2291,2292,2295],{"class":34,"line":235},[32,2293,2294],{"class":119},"    _processQueue",[32,2296,334],{"class":109},[32,2298,2299],{"class":34,"line":241},[32,2300,1117],{"class":109},[32,2302,2303],{"class":34,"line":247},[32,2304,76],{"emptyLinePlaceholder":75},[32,2306,2307,2309,2311,2313,2315,2318,2320,2322,2324,2326,2329],{"class":34,"line":252},[32,2308,889],{"class":105},[32,2310,110],{"class":109},[32,2312,1130],{"class":105},[32,2314,116],{"class":109},[32,2316,2317],{"class":119},"submit",[32,2319,110],{"class":109},[32,2321,1130],{"class":105},[32,2323,1142],{"class":109},[32,2325,436],{"class":105},[32,2327,2328],{"class":105}," Function",[32,2330,2331],{"class":109},"() task) {\n",[32,2333,2334,2336,2338,2340,2342,2344,2346],{"class":34,"line":258},[32,2335,317],{"class":126},[32,2337,1025],{"class":109},[32,2339,172],{"class":126},[32,2341,1179],{"class":105},[32,2343,110],{"class":109},[32,2345,1130],{"class":105},[32,2347,1186],{"class":109},[32,2349,2350,2353,2355,2357,2359],{"class":34,"line":286},[32,2351,2352],{"class":109},"    _queue.",[32,2354,2272],{"class":119},[32,2356,273],{"class":109},[32,2358,2164],{"class":105},[32,2360,2361],{"class":109},"(task, completer));\n",[32,2363,2364,2366],{"class":34,"line":308},[32,2365,2294],{"class":119},[32,2367,334],{"class":109},[32,2369,2370,2372],{"class":34,"line":314},[32,2371,226],{"class":126},[32,2373,1219],{"class":109},[32,2375,2376],{"class":34,"line":337},[32,2377,1117],{"class":109},[32,2379,2380],{"class":34,"line":350},[32,2381,76],{"emptyLinePlaceholder":75},[32,2383,2384,2386,2389],{"class":34,"line":355},[32,2385,1235],{"class":126},[32,2387,2388],{"class":119}," _processQueue",[32,2390,1241],{"class":109},[32,2392,2393,2396,2399,2402],{"class":34,"line":364},[32,2394,2395],{"class":126},"    while",[32,2397,2398],{"class":109}," (_idle.isNotEmpty ",[32,2400,2401],{"class":126},"&&",[32,2403,2404],{"class":109}," _queue.isNotEmpty) {\n",[32,2406,2407,2409,2411,2413,2416,2419],{"class":34,"line":680},[32,2408,2236],{"class":126},[32,2410,2239],{"class":109},[32,2412,172],{"class":126},[32,2414,2415],{"class":109}," _idle.",[32,2417,2418],{"class":119},"removeLast",[32,2420,334],{"class":109},[32,2422,2423,2425,2428,2430,2433,2436,2438,2441],{"class":34,"line":686},[32,2424,2236],{"class":126},[32,2426,2427],{"class":109}," task ",[32,2429,172],{"class":126},[32,2431,2432],{"class":109}," _queue.",[32,2434,2435],{"class":119},"removeAt",[32,2437,273],{"class":109},[32,2439,2440],{"class":105},"0",[32,2442,746],{"class":109},[32,2444,2445,2448,2450,2453,2456,2459,2461,2463,2465],{"class":34,"line":708},[32,2446,2447],{"class":109},"      worker.",[32,2449,1135],{"class":119},[32,2451,2452],{"class":109},"(task).",[32,2454,2455],{"class":119},"then",[32,2457,2458],{"class":109},"((_) ",[32,2460,469],{"class":126},[32,2462,2415],{"class":109},[32,2464,2272],{"class":119},[32,2466,2467],{"class":109},"(worker));\n",[32,2469,2470],{"class":34,"line":713},[32,2471,2289],{"class":109},[32,2473,2474],{"class":34,"line":719},[32,2475,1117],{"class":109},[32,2477,2478],{"class":34,"line":733},[32,2479,76],{"emptyLinePlaceholder":75},[32,2481,2482,2484,2486],{"class":34,"line":749},[32,2483,1235],{"class":126},[32,2485,1238],{"class":119},[32,2487,1241],{"class":109},[32,2489,2490,2492,2494,2496,2499,2502,2505,2508],{"class":34,"line":755},[32,2491,184],{"class":126},[32,2493,187],{"class":109},[32,2495,190],{"class":126},[32,2497,2498],{"class":109}," w ",[32,2500,2501],{"class":126},"in",[32,2503,2504],{"class":109}," _workers) w.",[32,2506,2507],{"class":119},"dispose",[32,2509,334],{"class":109},[32,2511,2512],{"class":34,"line":1214},[32,2513,1117],{"class":109},[32,2515,2516],{"class":34,"line":1222},[32,2517,244],{"class":109},[32,2519,2520],{"class":34,"line":1227},[32,2521,76],{"emptyLinePlaceholder":75},[32,2523,2524,2526,2529],{"class":34,"line":1232},[32,2525,799],{"class":126},[32,2527,2528],{"class":105}," _Task",[32,2530,130],{"class":109},[32,2532,2533,2535,2537,2539],{"class":34,"line":1244},[32,2534,289],{"class":126},[32,2536,1485],{"class":105},[32,2538,2328],{"class":105},[32,2540,2541],{"class":109},"() fn;\n",[32,2543,2544,2546,2548],{"class":34,"line":1263},[32,2545,289],{"class":126},[32,2547,1179],{"class":105},[32,2549,1196],{"class":109},[32,2551,2552,2555,2557,2559,2562,2564],{"class":34,"line":1273},[32,2553,2554],{"class":105},"  _Task",[32,2556,273],{"class":109},[32,2558,1683],{"class":105},[32,2560,2561],{"class":109},".fn, ",[32,2563,1683],{"class":105},[32,2565,2566],{"class":109},".completer);\n",[32,2568,2569],{"class":34,"line":1278},[32,2570,244],{"class":109},[32,2572,2573],{"class":34,"line":1283},[32,2574,76],{"emptyLinePlaceholder":75},[32,2576,2577,2579,2581],{"class":34,"line":1307},[32,2578,799],{"class":126},[32,2580,2246],{"class":105},[32,2582,130],{"class":109},[32,2584,2585,2587,2589],{"class":34,"line":1320},[32,2586,289],{"class":126},[32,2588,139],{"class":105},[32,2590,2591],{"class":109}," isolate;\n",[32,2593,2594,2596,2598],{"class":34,"line":1333},[32,2595,289],{"class":126},[32,2597,703],{"class":105},[32,2599,2600],{"class":109}," sendPort;\n",[32,2602,2603,2605,2607],{"class":34,"line":1344},[32,2604,289],{"class":126},[32,2606,551],{"class":105},[32,2608,2609],{"class":109}," receivePort;\n",[32,2611,2612],{"class":34,"line":1349},[32,2613,76],{"emptyLinePlaceholder":75},[32,2615,2616,2619,2621,2623,2626,2628,2631,2633],{"class":34,"line":1359},[32,2617,2618],{"class":105},"  _Worker",[32,2620,273],{"class":109},[32,2622,1683],{"class":105},[32,2624,2625],{"class":109},".isolate, ",[32,2627,1683],{"class":105},[32,2629,2630],{"class":109},".sendPort, ",[32,2632,1683],{"class":105},[32,2634,2635],{"class":109},".receivePort);\n",[32,2637,2638],{"class":34,"line":1373},[32,2639,76],{"emptyLinePlaceholder":75},[32,2641,2642,2644,2647,2649,2651,2653,2655,2657,2659,2662,2664],{"class":34,"line":1381},[32,2643,1286],{"class":126},[32,2645,2646],{"class":105}," Future",[32,2648,110],{"class":109},[32,2650,2124],{"class":105},[32,2652,116],{"class":109},[32,2654,670],{"class":119},[32,2656,273],{"class":109},[32,2658,276],{"class":105},[32,2660,2661],{"class":109}," debugName) ",[32,2663,127],{"class":126},[32,2665,130],{"class":109},[32,2667,2668,2670,2672,2674,2676],{"class":34,"line":1397},[32,2669,317],{"class":126},[32,2671,546],{"class":109},[32,2673,172],{"class":126},[32,2675,551],{"class":105},[32,2677,334],{"class":109},[32,2679,2680,2682,2685,2687,2689,2691,2693,2695],{"class":34,"line":1419},[32,2681,317],{"class":126},[32,2683,2684],{"class":109}," isolate ",[32,2686,172],{"class":126},[32,2688,297],{"class":126},[32,2690,139],{"class":105},[32,2692,142],{"class":109},[32,2694,670],{"class":119},[32,2696,935],{"class":109},[32,2698,2699],{"class":34,"line":1430},[32,2700,940],{"class":109},[32,2702,2703],{"class":34,"line":1455},[32,2704,2705],{"class":109},"      receivePort.sendPort,\n",[32,2707,2708,2710,2712],{"class":34,"line":1460},[32,2709,950],{"class":109},[32,2711,953],{"class":126},[32,2713,2714],{"class":109}," debugName,\n",[32,2716,2717],{"class":34,"line":1465},[32,2718,964],{"class":109},[32,2720,2721,2723,2726,2728,2730,2733,2735,2737],{"class":34,"line":1470},[32,2722,317],{"class":126},[32,2724,2725],{"class":109}," sendPort ",[32,2727,172],{"class":126},[32,2729,297],{"class":126},[32,2731,2732],{"class":109}," receivePort.first ",[32,2734,478],{"class":126},[32,2736,703],{"class":105},[32,2738,178],{"class":109},[32,2740,2741,2743,2745],{"class":34,"line":1475},[32,2742,226],{"class":126},[32,2744,2246],{"class":105},[32,2746,2747],{"class":109},"(isolate, sendPort, receivePort);\n",[32,2749,2750],{"class":34,"line":1480},[32,2751,1117],{"class":109},[32,2753,2754],{"class":34,"line":1500},[32,2755,76],{"emptyLinePlaceholder":75},[32,2757,2758,2760,2762,2764,2766,2768,2770,2772,2775,2777],{"class":34,"line":1511},[32,2759,889],{"class":105},[32,2761,110],{"class":109},[32,2763,436],{"class":105},[32,2765,116],{"class":109},[32,2767,1135],{"class":119},[32,2769,273],{"class":109},[32,2771,2164],{"class":105},[32,2773,2774],{"class":109}," task) ",[32,2776,127],{"class":126},[32,2778,130],{"class":109},[32,2780,2781,2784,2786],{"class":34,"line":1547},[32,2782,2783],{"class":109},"    sendPort.",[32,2785,561],{"class":119},[32,2787,2788],{"class":109},"(task.fn);\n",[32,2790,2791,2793,2795,2797,2799],{"class":34,"line":1568},[32,2792,317],{"class":126},[32,2794,292],{"class":109},[32,2796,172],{"class":126},[32,2798,297],{"class":126},[32,2800,2801],{"class":109}," receivePort.first;\n",[32,2803,2804,2807,2809],{"class":34,"line":1582},[32,2805,2806],{"class":109},"    task.completer.",[32,2808,1094],{"class":119},[32,2810,361],{"class":109},[32,2812,2813,2815],{"class":34,"line":1612},[32,2814,226],{"class":126},[32,2816,1734],{"class":109},[32,2818,2819],{"class":34,"line":1618},[32,2820,1117],{"class":109},[32,2822,2823],{"class":34,"line":1623},[32,2824,76],{"emptyLinePlaceholder":75},[32,2826,2827,2829,2831],{"class":34,"line":1628},[32,2828,1235],{"class":126},[32,2830,1238],{"class":119},[32,2832,1241],{"class":109},[32,2834,2835,2838,2840],{"class":34,"line":1633},[32,2836,2837],{"class":109},"    isolate.",[32,2839,1250],{"class":119},[32,2841,334],{"class":109},[32,2843,2844,2846,2848],{"class":34,"line":1642},[32,2845,1352],{"class":109},[32,2847,1268],{"class":119},[32,2849,334],{"class":109},[32,2851,2852],{"class":34,"line":1653},[32,2853,1117],{"class":109},[32,2855,2856],{"class":34,"line":1663},[32,2857,76],{"emptyLinePlaceholder":75},[32,2859,2860,2862,2864,2866,2868,2870],{"class":34,"line":1673},[32,2861,1286],{"class":126},[32,2863,1289],{"class":126},[32,2865,1292],{"class":119},[32,2867,273],{"class":109},[32,2869,531],{"class":105},[32,2871,2872],{"class":109}," mainPort) {\n",[32,2874,2875,2877,2879,2881,2883],{"class":34,"line":1699},[32,2876,317],{"class":126},[32,2878,546],{"class":109},[32,2880,172],{"class":126},[32,2882,551],{"class":105},[32,2884,334],{"class":109},[32,2886,2887,2890,2892],{"class":34,"line":1704},[32,2888,2889],{"class":109},"    mainPort.",[32,2891,561],{"class":119},[32,2893,1341],{"class":109},[32,2895,2896,2898,2900],{"class":34,"line":1709},[32,2897,1352],{"class":109},[32,2899,579],{"class":119},[32,2901,2902],{"class":109},"((fn) {\n",[32,2904,2905,2907,2909,2911,2914,2916,2918,2920],{"class":34,"line":1718},[32,2906,2236],{"class":126},[32,2908,292],{"class":109},[32,2910,172],{"class":126},[32,2912,2913],{"class":109}," (fn ",[32,2915,478],{"class":126},[32,2917,1485],{"class":105},[32,2919,2328],{"class":105},[32,2921,2922],{"class":109},"())();\n",[32,2924,2925,2928,2930],{"class":34,"line":1727},[32,2926,2927],{"class":109},"      mainPort.",[32,2929,561],{"class":119},[32,2931,361],{"class":109},[32,2933,2934],{"class":34,"line":1737},[32,2935,1112],{"class":109},[32,2937,2938],{"class":34,"line":1749},[32,2939,1117],{"class":109},[32,2941,2942],{"class":34,"line":1772},[32,2943,244],{"class":109},[14,2945,2947],{"id":2946},"when-to-use-isolates-and-when-not-to","When to Use Isolates (and When Not To)",[19,2949,2950],{"language":21},[23,2951,2953],{"className":25,"code":2952,"language":21,"meta":27,"style":27},"\u002F\u002F ── USE isolates for: CPU-heavy work that blocks the event loop ──\n\u002F\u002F If a computation takes >16ms (one frame at 60fps), it drops frames.\n\u002F\u002F Parsing large JSON, compression, image processing, sorting large datasets.\n\n\u002F\u002F ✓ CPU-heavy: parse a 10MB JSON string.\nfinal data = await Isolate.run(() => jsonDecode(hugeJsonString));\n\n\u002F\u002F ✓ CPU-heavy: compress an image.\nfinal compressed = await Isolate.run(() => compressImage(rawPixels));\n\n\u002F\u002F ── DON'T use isolates for: I\u002FO-bound work ──\n\u002F\u002F I\u002FO (file, network, timers) is async — the event loop handles concurrency.\n\u002F\u002F Offloading I\u002FO to an isolate adds ~50ms spawn overhead + copy overhead.\n\n\u002F\u002F ❌ I\u002FO-bound: reading a file (async, event loop handles it).\nfinal content = await File(path).readAsString();  \u002F\u002F ✓ on main isolate\n\n\u002F\u002F ❌ I\u002FO-bound: HTTP request (async, event loop handles it).\nfinal response = await http.get(Uri.parse(url));  \u002F\u002F ✓ on main isolate\n\n\u002F\u002F ── Rule of thumb: ──\n\u002F\u002F - If it's CPU-bound and takes >16ms → Isolate.run.\n\u002F\u002F - If it's I\u002FO-bound → await on the main isolate (event loop handles it).\n\u002F\u002F - If it's many small CPU tasks → worker pool (reuse isolates).\n",[29,2954,2955,2960,2965,2970,2974,2979,3005,3009,3014,3041,3045,3050,3055,3060,3064,3069,3092,3096,3101,3133,3137,3142,3147,3152],{"__ignoreMap":27},[32,2956,2957],{"class":34,"line":35},[32,2958,2959],{"class":38},"\u002F\u002F ── USE isolates for: CPU-heavy work that blocks the event loop ──\n",[32,2961,2962],{"class":34,"line":42},[32,2963,2964],{"class":38},"\u002F\u002F If a computation takes >16ms (one frame at 60fps), it drops frames.\n",[32,2966,2967],{"class":34,"line":48},[32,2968,2969],{"class":38},"\u002F\u002F Parsing large JSON, compression, image processing, sorting large datasets.\n",[32,2971,2972],{"class":34,"line":54},[32,2973,76],{"emptyLinePlaceholder":75},[32,2975,2976],{"class":34,"line":60},[32,2977,2978],{"class":38},"\u002F\u002F ✓ CPU-heavy: parse a 10MB JSON string.\n",[32,2980,2981,2984,2986,2988,2990,2992,2994,2996,2998,3000,3002],{"class":34,"line":66},[32,2982,2983],{"class":126},"final",[32,2985,1977],{"class":109},[32,2987,172],{"class":126},[32,2989,297],{"class":126},[32,2991,139],{"class":105},[32,2993,142],{"class":109},[32,2995,145],{"class":119},[32,2997,466],{"class":109},[32,2999,469],{"class":126},[32,3001,472],{"class":119},[32,3003,3004],{"class":109},"(hugeJsonString));\n",[32,3006,3007],{"class":34,"line":72},[32,3008,76],{"emptyLinePlaceholder":75},[32,3010,3011],{"class":34,"line":79},[32,3012,3013],{"class":38},"\u002F\u002F ✓ CPU-heavy: compress an image.\n",[32,3015,3016,3018,3021,3023,3025,3027,3029,3031,3033,3035,3038],{"class":34,"line":85},[32,3017,2983],{"class":126},[32,3019,3020],{"class":109}," compressed ",[32,3022,172],{"class":126},[32,3024,297],{"class":126},[32,3026,139],{"class":105},[32,3028,142],{"class":109},[32,3030,145],{"class":119},[32,3032,466],{"class":109},[32,3034,469],{"class":126},[32,3036,3037],{"class":119}," compressImage",[32,3039,3040],{"class":109},"(rawPixels));\n",[32,3042,3043],{"class":34,"line":91},[32,3044,76],{"emptyLinePlaceholder":75},[32,3046,3047],{"class":34,"line":97},[32,3048,3049],{"class":38},"\u002F\u002F ── DON'T use isolates for: I\u002FO-bound work ──\n",[32,3051,3052],{"class":34,"line":102},[32,3053,3054],{"class":38},"\u002F\u002F I\u002FO (file, network, timers) is async — the event loop handles concurrency.\n",[32,3056,3057],{"class":34,"line":133},[32,3058,3059],{"class":38},"\u002F\u002F Offloading I\u002FO to an isolate adds ~50ms spawn overhead + copy overhead.\n",[32,3061,3062],{"class":34,"line":151},[32,3063,76],{"emptyLinePlaceholder":75},[32,3065,3066],{"class":34,"line":157},[32,3067,3068],{"class":38},"\u002F\u002F ❌ I\u002FO-bound: reading a file (async, event loop handles it).\n",[32,3070,3071,3073,3075,3077,3079,3081,3083,3086,3089],{"class":34,"line":163},[32,3072,2983],{"class":126},[32,3074,320],{"class":109},[32,3076,172],{"class":126},[32,3078,297],{"class":126},[32,3080,325],{"class":105},[32,3082,328],{"class":109},[32,3084,3085],{"class":119},"readAsString",[32,3087,3088],{"class":109},"();  ",[32,3090,3091],{"class":38},"\u002F\u002F ✓ on main isolate\n",[32,3093,3094],{"class":34,"line":181},[32,3095,76],{"emptyLinePlaceholder":75},[32,3097,3098],{"class":34,"line":223},[32,3099,3100],{"class":38},"\u002F\u002F ❌ I\u002FO-bound: HTTP request (async, event loop handles it).\n",[32,3102,3103,3105,3108,3110,3112,3115,3118,3120,3123,3125,3128,3131],{"class":34,"line":235},[32,3104,2983],{"class":126},[32,3106,3107],{"class":109}," response ",[32,3109,172],{"class":126},[32,3111,297],{"class":126},[32,3113,3114],{"class":109}," http.",[32,3116,3117],{"class":119},"get",[32,3119,273],{"class":109},[32,3121,3122],{"class":105},"Uri",[32,3124,142],{"class":109},[32,3126,3127],{"class":119},"parse",[32,3129,3130],{"class":109},"(url));  ",[32,3132,3091],{"class":38},[32,3134,3135],{"class":34,"line":241},[32,3136,76],{"emptyLinePlaceholder":75},[32,3138,3139],{"class":34,"line":247},[32,3140,3141],{"class":38},"\u002F\u002F ── Rule of thumb: ──\n",[32,3143,3144],{"class":34,"line":252},[32,3145,3146],{"class":38},"\u002F\u002F - If it's CPU-bound and takes >16ms → Isolate.run.\n",[32,3148,3149],{"class":34,"line":258},[32,3150,3151],{"class":38},"\u002F\u002F - If it's I\u002FO-bound → await on the main isolate (event loop handles it).\n",[32,3153,3154],{"class":34,"line":286},[32,3155,3156],{"class":38},"\u002F\u002F - If it's many small CPU tasks → worker pool (reuse isolates).\n",[14,3158,3160],{"id":3159},"tips-tricks","💡 Tips & Tricks",[3162,3163,3164,3176,3191,3200,3205],"ul",{},[3165,3166,3167,3171,3172,3175],"li",{},[3168,3169,3170],"strong",{},"Performance",": ",[29,3173,3174],{},"TransferableTypedData"," for large byte buffers between isolates — zero-copy transfer (O(1)) instead of deep copy (O(n)). Use for images, audio buffers, large arrays. The original buffer is invalidated after transfer.",[3165,3177,3178,3171,3181,3183,3184,3187,3188,3190],{},[3168,3179,3180],{},"Idiom",[29,3182,372],{}," for one-shot CPU-heavy work — ",[29,3185,3186],{},"await Isolate.run(() => heavyTask())"," offloads to a separate isolate. Simpler than ",[29,3189,376],{}," for fire-and-forget. The isolate is auto-killed after the function returns.",[3165,3192,3193,3195,3196,3199],{},[3168,3194,3180],{},": worker pool for many small tasks — spawning an isolate costs ~50ms. For many tasks, spawn N isolates once and reuse (send messages). Use ",[29,3197,3198],{},"package:worker_manager"," or build a pool.",[3165,3201,3202,3204],{},[3168,3203,3180],{},": keep isolate entry functions top-level or static — closures sent to isolates must be sendable (copied). Top-level functions and static methods are safely sendable. Avoid capturing non-sendable objects.",[3165,3206,3207,3171,3209,3212,3213,3216],{},[3168,3208,3180],{},[29,3210,3211],{},"debugName"," for isolates — ",[29,3214,3215],{},"Isolate.spawn(entry, msg, debugName: 'image-worker')"," names the isolate for DevTools. Helps identify isolates in the profiler\u002Fdebugger.",[14,3218,3220],{"id":3219},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[3162,3222,3223,3232,3241,3247,3255,3261,3286,3302,3311,3319],{},[3165,3224,3225,3228,3229,3231],{},[3168,3226,3227],{},"Spawn overhead (~50ms)",": for small tasks, the overhead exceeds the benefit. Use a worker pool (spawn once, reuse) for many small tasks. ",[29,3230,372],{}," is for one-shot heavy work.",[3165,3233,3234,3237,3238,3240],{},[3168,3235,3236],{},"Messages are deep-copied",": sending a large object to an isolate copies it (memory + time). Use ",[29,3239,3174],{}," for large byte buffers (zero-copy). After transfer, the original is invalidated.",[3165,3242,3243,3246],{},[3168,3244,3245],{},"Isolates don't share memory",": no shared mutable state. All communication is message passing. This is a feature (no races) but requires a different design (pass data, not share).",[3165,3248,3249,3171,3252,3254],{},[3168,3250,3251],{},"Web doesn't support isolates",[29,3253,372],{}," throws or runs on the main thread on web. The web is single-threaded. Use Web Workers (via JS interop) for parallelism on web.",[3165,3256,3257,3260],{},[3168,3258,3259],{},"Closures must capture sendable values",": a function sent to an isolate can capture variables, but they must be sendable (copied). Capturing a non-sendable object (e.g., a file handle) fails.",[3165,3262,3263,3268,3269,3271,3272,3275,3276,3278,3279,3282,3283,142],{},[3168,3264,3265,3266],{},"Errors propagate from ",[29,3267,372],{},": a thrown error in ",[29,3270,372],{}," is caught by the ",[29,3273,3274],{},"await","er. For ",[29,3277,376],{},", handle errors via ",[29,3280,3281],{},"onError"," port or ",[29,3284,3285],{},"errorsAreFatal",[3165,3287,3288,3294,3295,3297,3298,3301],{},[3168,3289,3290,3293],{},[29,3291,3292],{},"ReceivePort"," must be closed",": a ",[29,3296,3292],{}," keeps the isolate alive. Close it (",[29,3299,3300],{},"receivePort.close()",") when done, or the isolate won't exit (resource leak).",[3165,3303,3304,3310],{},[3168,3305,3306,3309],{},[29,3307,3308],{},"Isolate.kill()"," doesn't run finalizers",": forcibly kills the isolate. Use for cleanup, but prefer graceful shutdown (send a \"stop\" message, close ports) for clean resource release.",[3165,3312,3313,3318],{},[3168,3314,3315,3317],{},[29,3316,372],{}," copies the closure and captures",": the function and its captured variables are deep-copied to the new isolate. Mutations in the isolate don't affect the original.",[3165,3320,3321,3328],{},[3168,3322,3323,3324,3327],{},"No ",[29,3325,3326],{},"dart:mirrors"," in isolates (AOT)",": runtime reflection is unsupported in AOT-compiled isolates. Use code generation instead.",[14,3330,3332],{"id":3331},"spot-the-bug","🧠 Spot the Bug",[3334,3335,3336],"p",{},"A developer offloads file reading to an isolate, but it's slower than reading on the main thread:",[19,3338,3339],{"language":21},[23,3340,3342],{"className":25,"code":3341,"language":21,"meta":27,"style":27},"Future\u003CString> readFile(String path) async {\n  return Isolate.run(() => File(path).readAsStringSync());\n}\n",[29,3343,3344,3367,3390],{"__ignoreMap":27},[32,3345,3346,3348,3350,3352,3354,3357,3359,3361,3363,3365],{"class":34,"line":35},[32,3347,106],{"class":105},[32,3349,110],{"class":109},[32,3351,276],{"class":105},[32,3353,116],{"class":109},[32,3355,3356],{"class":119},"readFile",[32,3358,273],{"class":109},[32,3360,276],{"class":105},[32,3362,279],{"class":109},[32,3364,127],{"class":126},[32,3366,130],{"class":109},[32,3368,3369,3371,3373,3375,3377,3379,3381,3383,3385,3387],{"class":34,"line":42},[32,3370,136],{"class":126},[32,3372,139],{"class":105},[32,3374,142],{"class":109},[32,3376,145],{"class":119},[32,3378,466],{"class":109},[32,3380,469],{"class":126},[32,3382,325],{"class":105},[32,3384,328],{"class":109},[32,3386,331],{"class":119},[32,3388,3389],{"class":109},"());\n",[32,3391,3392],{"class":34,"line":48},[32,3393,244],{"class":109},[3334,3395,3396],{},"Why is this slower?",[3398,3399,3400,3404,3419,3422,3443,3446,3492,3502],"details",{},[3401,3402,3403],"summary",{},"Answer",[3334,3405,3406,3407,3410,3411,3414,3415,3418],{},"File reading is ",[3168,3408,3409],{},"I\u002FO-bound",", not CPU-bound. ",[29,3412,3413],{},"File.readAsStringSync()"," blocks the thread waiting for the disk — but ",[29,3416,3417],{},"File.readAsString()"," (async) yields to the event loop while waiting, allowing other work to proceed.",[3334,3420,3421],{},"Offloading I\u002FO to an isolate adds:",[3423,3424,3425,3431,3437],"ol",{},[3165,3426,3427,3430],{},[3168,3428,3429],{},"~50ms spawn overhead"," (creating the isolate).",[3165,3432,3433,3436],{},[3168,3434,3435],{},"Message copy overhead"," (the result string is deep-copied back to the main isolate).",[3165,3438,3439,3442],{},[3168,3440,3441],{},"No concurrency benefit"," — the main isolate could have awaited the I\u002FO directly.",[3334,3444,3445],{},"The fix — do async I\u002FO on the main isolate:",[23,3447,3449],{"className":25,"code":3448,"language":21,"meta":27,"style":27},"Future\u003CString> readFile(String path) async {\n  return File(path).readAsString();  \u002F\u002F async, event loop handles concurrency\n}\n",[29,3450,3451,3473,3488],{"__ignoreMap":27},[32,3452,3453,3455,3457,3459,3461,3463,3465,3467,3469,3471],{"class":34,"line":35},[32,3454,106],{"class":105},[32,3456,110],{"class":109},[32,3458,276],{"class":105},[32,3460,116],{"class":109},[32,3462,3356],{"class":119},[32,3464,273],{"class":109},[32,3466,276],{"class":105},[32,3468,279],{"class":109},[32,3470,127],{"class":126},[32,3472,130],{"class":109},[32,3474,3475,3477,3479,3481,3483,3485],{"class":34,"line":42},[32,3476,136],{"class":126},[32,3478,325],{"class":105},[32,3480,328],{"class":109},[32,3482,3085],{"class":119},[32,3484,3088],{"class":109},[32,3486,3487],{"class":38},"\u002F\u002F async, event loop handles concurrency\n",[32,3489,3490],{"class":34,"line":48},[32,3491,244],{"class":109},[3334,3493,3494,3495,3498,3499,3501],{},"Use isolates for ",[3168,3496,3497],{},"CPU-heavy"," work (parsing, compression, image processing) that blocks the event loop. For I\u002FO, ",[29,3500,3274],{}," on the main isolate — the event loop handles concurrency while the I\u002FO is in progress.",[23,3503,3505],{"className":25,"code":3504,"language":21,"meta":27,"style":27},"\u002F\u002F ✓ Correct isolate use — CPU-heavy JSON parsing:\nfinal data = await Isolate.run(() => jsonDecode(hugeJsonString));\n",[29,3506,3507,3512],{"__ignoreMap":27},[32,3508,3509],{"class":34,"line":35},[32,3510,3511],{"class":38},"\u002F\u002F ✓ Correct isolate use — CPU-heavy JSON parsing:\n",[32,3513,3514,3516,3518,3520,3522,3524,3526,3528,3530,3532,3534],{"class":34,"line":42},[32,3515,2983],{"class":126},[32,3517,1977],{"class":109},[32,3519,172],{"class":126},[32,3521,297],{"class":126},[32,3523,139],{"class":105},[32,3525,142],{"class":109},[32,3527,145],{"class":119},[32,3529,466],{"class":109},[32,3531,469],{"class":126},[32,3533,472],{"class":119},[32,3535,3004],{"class":109},[3537,3538,3539],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}",{"title":27,"searchDepth":42,"depth":42,"links":3541},[3542,3543,3545,3546,3547,3548,3549,3550,3551],{"id":16,"depth":42,"text":17},{"id":369,"depth":42,"text":3544},"Isolate.run vs Isolate.spawn",{"id":760,"depth":42,"text":761},{"id":1777,"depth":42,"text":1778},{"id":2062,"depth":42,"text":2063},{"id":2946,"depth":42,"text":2947},{"id":3159,"depth":42,"text":3160},{"id":3219,"depth":42,"text":3220},{"id":3331,"depth":42,"text":3332},"Deep-dive into Dart's isolate-based concurrency model, Isolate.run patterns, bidirectional message passing, TransferableTypedData zero-copy, worker pool architecture, and web platform limitations. Code-first engineering reference.","md",{},"\u002Fdart\u002F10-isolates-and-concurrency",{"title":5,"description":3552},"dart\u002F10-isolates-and-concurrency","Z_3eNFOhuHcgyRWHtZEaJmWl48KHJ-ZqxbY4nncJAN8",1789924647747]