You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
以下是 Node.js 官方的示例, 如何借助 inspector api 直接获取到当前进程的 CPU Profiler。Profiler.enable、Profiler.start、Profiler.stop等调试指令 Node.js 都会通过 dispatchProtocolMessage 发送给 v8
constinspector=require('node:inspector');constfs=require('node:fs');constsession=newinspector.Session();session.connect();session.post('Profiler.enable',()=>{session.post('Profiler.start',()=>{// Invoke business logic under measurement here...// some time later...session.post('Profiler.stop',(err,{ profile })=>{// Write profile to disk, upload, etc.if(!err){fs.writeFileSync('./profile.cpuprofile',JSON.stringify(profile));}});});});
通信过程
上面的例子在当前线程内直接通过 api 即可通知到 v8。如果是通过客户端 Chrome Devtool 去调试 Node.js 程序就是另外的实现
voidSameThreadInspectorSession::Dispatch(
constv8_inspector::StringView&message) {
auto client=client_.lock();
if (client)
client->dispatchMessageFromFrontend(session_id_, message);
}
v8 响应数据从主线程发送给子线程 WebSocket Server 的跨线程通信方式与之类似, 最后 WebSocket Server 把数据发送给调试客户端 Chrome Devtool
Node.js 内置的 Inspector 模块可以轻易的让开发者去调试一个 Node.js 程序, 常见的场景比如断点调试、查看内存占用与 CPU Profiler 等。下面简单记录一下它的实现原理
核心实现
Node.js 源码对这块封装的比较复杂, 弯弯绕绕的一下子很难看明白。拨开层层云雾其实 Node.js 只是在调试客户端比如 Chrome Devtool 与 v8 之间作了一层代理
调试客户端向 v8 发送消息
Node.js 通过调用 V8Inspector 的 connect 方法即可获得一个与 v8 通信的会话 V8InspectorSession, 把需要调试的指令通过 dispatchProtocolMessage 方法即可告知到 v8
v8 给调试客户端发送消息
connect 方法的第二个参数 ChannelImpl 的类型定义可知, v8 的任何响应结果会通过调用传入的 ChannelImpl 实例的 sendResponse 方法来告知到调试客户端
例子
以下是 Node.js 官方的示例, 如何借助 inspector api 直接获取到当前进程的 CPU Profiler。
Profiler.enable
、Profiler.start
、Profiler.stop
等调试指令 Node.js 都会通过 dispatchProtocolMessage 发送给 v8通信过程
上面的例子在当前线程内直接通过 api 即可通知到 v8。如果是通过客户端 Chrome Devtool 去调试 Node.js 程序就是另外的实现
此时 Node.js 是在子线程中起了一个 WebSocket Server, 来处理调试客户端 Chrome Devtool 发送来的调试指令, 然后通知主线程, 最后再发送给 v8
通过 CrossThreadInspectorSession 类进行实现
AnotherThreadObjectReference 类调用了 Post 方法, 该方法中通过 agent_->env()->RequestInterrupt 方法向 env->native_immediates_interrupts_ 队列 push 了一个数据
然后就是经典的 libuv 异步 i/o 通信模型, 在子线程中通过 uv_async_send 标识 task_queues_async_ 有数据可读
在主线程中的事件循环 epoll 阶段发现 task_queues_async_ 处于兴奋状态, 于是运行事先通过 uv_async_init 注册的回调函数
此时代码运行到主线程的回调函数 Dispatch, 如下 dispatchMessageFromFrontend 方法最终调用了 dispatchProtocolMessage 发送给 v8
v8 响应数据从主线程发送给子线程 WebSocket Server 的跨线程通信方式与之类似, 最后 WebSocket Server 把数据发送给调试客户端 Chrome Devtool
WebSocket Server 与 Chrome Devtool 的数据请求可以通过 More tools > Protocol monitor 面板进行查看, 需要先在 Settings > Experiments 中 ☑️ 开启 Protocol monitor
The text was updated successfully, but these errors were encountered: