Dart中的隔离区是否会利用多核环境中的所有可用内核并行运行,还是会在单个内核上进行多路复用?
谷歌已经将Dart编程语言中的隔离(单线程并发单元)描述为一个"轻量级线程",它在主堆栈上运行,没有阻塞.
因此,在我看来,它只能在单个内核上进行多路复用,并且无法在SMP,双核,多核或集群环境中的多个内核上并行运行.
虽然,我找不到任何关于此的信息,因此我的谦虚问题.
我试图在Dart中编写一个可以并行处理多个请求的HTTP服务器.到目前为止,我没有成功实现"并行"部分.
这是我最初尝试的内容:
import 'dart:io';
main() {
HttpServer.bind(InternetAddress.ANY_IP_V4, 8080).then((HttpServer server) {
server.listen((HttpRequest request) {
Stopwatch stopwatch = new Stopwatch();
stopwatch.start();
while (stopwatch.elapsedMilliseconds < 1000) { /* do nothing */ }
request.response.statusCode = HttpStatus.OK;
request.response.write(stopwatch.elapsedMilliseconds.toString());
request.response.close().catchError(print);
});
});
}
Run Code Online (Sandbox Code Playgroud)
在每个请求上它忙于工作一秒钟,然后完成.我让它以这种方式处理请求,以便它的时间可以预测,因此我可以很容易地看到Windows任务管理器中的请求的效果(CPU核心跳到100%使用率).
我可以说这不是并行处理请求,因为:
如果我将几个浏览器选项卡加载到http://example:8080/
然后全部刷新,则选项卡依次加载,每个选项卡之间大约1秒钟.
如果我使用带有这些设置 的负载测试工具wrkwrk -d 10 -c 8 -t 8 http://example:8080/
......它在我给它的10秒内完成了5到8个请求.如果服务器使用我的所有8个核心,我预计一个数字接近80个请求.
当我在wrk测试期间打开Windows任务管理器时,我发现我的核心中只有一个接近100%的使用率,其余的几乎都是空闲的.
所以,然后我尝试使用隔离,希望为每个请求手动生成一个新的隔离/线程:
import 'dart:io';
import 'dart:isolate';
main() {
HttpServer.bind(InternetAddress.ANY_IP_V4, 8080).then((HttpServer server) {
server.listen((HttpRequest request) {
spawnFunction(handleRequest).send(request);
});
});
}
handleRequest() {
port.receive((HttpRequest request, SendPort sender) { …
Run Code Online (Sandbox Code Playgroud) 隔离如何分布在 CPU 核心上
在 Dart 中,您可以同时运行多个隔离,但我尚未找到使用隔离的指南或最佳实践。
我的问题是,同时运行的isolate 数量会如何影响整体CPU 使用率和性能,以及使用少量isolate(甚至仅一个)是否更好。
我怎么解决这个问题:
\nE/flutter (18287): [ERROR:flutter/shell/common/shell.cc(89)] Dart Error: Dart_LookupLibrary: library 'package:background_fetch/background_fetch.dart' not found.\nE/flutter (18287): [ERROR:flutter/runtime/dart_isolate.cc(668)] Could not resolve main entrypoint function.\nE/flutter (18287): [ERROR:flutter/runtime/dart_isolate.cc(168)] Could not run the run main Dart entrypoint.\nE/flutter (18287): [ERROR:flutter/runtime/runtime_controller.cc(389)] Could not create root isolate.\nE/flutter (18287): [ERROR:flutter/shell/common/shell.cc(605)] Could not launch engine with configuration.\n
Run Code Online (Sandbox Code Playgroud)\n问题就出在模式发布上下出现,但在调试模式下插件工作正常。
\n更多细节:
\n[\xe2\x9c\x93] Flutter (Channel master, 3.4.0-36.0.pre.8, on Ubuntu 22.04.1 LTS 5.15.0-48-generic, locale en_US.UTF-8) Checking Android licenses is taking an unexpectedly long time...[\xe2\x9c\x93] Android toolchain - develop for Android devices …
Run Code Online (Sandbox Code Playgroud) 我可能会对Isolate和Future有错误的想法,请帮我清理一下.以下是我对两个科目的理解.
隔离:在自己的事件循环中隔离运行代码,并且每个事件可以在嵌套的微任务队列中运行较小的任务.
未来:未来用于表示将来某个时间可用的潜在价值或错误.
我的困惑是:
文档说Isolate有它自己的循环?我觉得拥有自己的事件队列对我来说更有意义,我错了吗?
未来是否会在主Isolate上异步运行?我假设未来的任务实际上被放置在事件队列的末尾,所以如果它将来会循环执行.如我错了请纠正我.
为什么在有未来的时候使用Isolate?我看到一些使用Isolate的例子用于一些繁重的任务,而不是Future.但为什么?当将来在主隔离队列上异步执行时,它才对我有意义.
谢谢大家,感谢您的回复.
框架/SDK版本:
Flutter: 3.10.4
Dart: 3.0.3
Run Code Online (Sandbox Code Playgroud)
这是我的main()
代码:
Future<void> main() async {
//debugPaintSizeEnabled = true;
//BindingBase.debugZoneErrorsAreFatal = true;
WidgetsFlutterBinding.ensureInitialized();
EasyLocalization.ensureInitialized()
.then((value) => Fimber.plantTree(DebugTree()))
.then((value) => SentryFlutter.init(
(options) {
options.dsn = '***';
// Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
// We recommend adjusting this value in production.
options.tracesSampleRate = 1.0;
//options.attachScreenshot = true;
},
appRunner: () => runApp(
EasyLocalization(
supportedLocales: const [Locale('en', 'US'), Locale('de', 'DE')],
path: '../assets/translations/',
fallbackLocale: const Locale('en', 'US'),
assetLoader: const CodegenLoader(),
child: …
Run Code Online (Sandbox Code Playgroud) 我想动态构造和加载Dart脚本.我该怎么做呢?
我知道我可以使用Isolate.spawnUri动态加载Dart脚本.但是,我只知道我可以从file:和http:URIs加载.这意味着我需要将我的脚本放在某处加载,这是我想避免的复杂问题.
在这篇文章中,他们产生了这样的隔离:
import 'dart:isolate';
void main() async {
final receivePort = ReceivePort();
final isolate = await Isolate.spawn(
downloadAndCompressTheInternet,
receivePort.sendPort,
);
receivePort.listen((message) {
print(message);
receivePort.close();
isolate.kill();
});
}
void downloadAndCompressTheInternet(SendPort sendPort) {
sendPort.send(42);
}
Run Code Online (Sandbox Code Playgroud)
但我只能传入接收端口。我如何传递其他参数?
我找到了答案,所以我将其发布在下面。
谁能告诉我这段代码有什么问题吗?
void onPressed() async {
//Navigator.pushNamed(context, "/screen2", arguments: []);
var receivePort = ReceivePort();
await Isolate.spawn(gotoNext, [receivePort.sendPort]);
final msg = await receivePort.first;
print(msg);
}
void gotoNext(List<dynamic> args) {
SendPort sendPort = args[0];
log(args.toString());
Isolate.exit(sendPort, "OK");
}
Run Code Online (Sandbox Code Playgroud)
E / flutter(12062):[错误:flutter/lib/ui/ui_dart_state.cc(209)]未处理的异常:无效参数:隔离消息中的非法参数:(对象扩展NativeWrapper - Library:'dart:ui'类:路径)
在Dart中,有一个隔离概念.我有一个应用程序(我在Dart中进行实验),它有很多异步IO,每次调用(它们都是数据库调用)都依赖于前一个.所以我最终陷入了嵌套的回调地狱.
我想知道Isolates是否可以解决那个嵌套的回调汤,但它看起来有点冗长,我不确定它是否适合它.
在下一个ECMAScript Harmony中也提出了可以解决这些问题的Generators,但是你现在如何以干净的方式在Dart中做很多异步IO呢?