2021年January月 发布的文章

不要买技嘉 X570 Gaming X 主板

装了这么多年电脑,头一次遇到被电脑主板散味熏的头疼了好几天的情况。。。

之前台式机是 3700X + MSI Mortar B450m, 用的没啥问题就是槽不够用,因为有加设备的需求,打算借机就换个 X570 飞一下,于是选择了一线品牌里面最便宜的这个 GIGABYTE X570 Gaming X,1099 大元入手。

拿到以后一看 PCB 觉得比较一般,看上去不像一线品牌应该有的样子,也没多想就直接上机了。结果开始烤机以后电脑机箱里面温度上升,主板就开始发出比较浓的化学品味道,熏得人坐立不安,大冬天的不得不开窗放气。开始想着这可能是临时现象,没想到过了几天依然如此,而且不开电脑时候依然有味,整个书房里面都充满了化学品的味道,简直要疯掉。

最后忍无可忍,简单做了一下功课以后,直接狗东下单微星 B550 暗黑,虽然是 B550 但是供电比 570 GAMING X 好太多,看在算是相对高端定位的份上,应该不会太差把。拿到以后上机果然没味。

以后买东西还是坚决不能买丐版,钱包不够好的话,还是稍微差一点的品牌的旗舰级别产品会更好一些。宁为鸡首不为牛后。

Golang socket 里面奇怪的 pipe 使用

有个 golang 写的 proxy server, 大概日常 tcp 连接数两万多左右,结果某次在 /proc/pid/fd 下面一看,竟然有五到六万多文件,ls -l 一看,居然 socket 只有两万多,pipe 反而有三万多小四万,这就奇了怪了,哪儿来的这么多 pipe?

读了一阵子源码搞清楚了,golang 在 Linux 下面,对于 fd 对拷这种操作【具体是 net.Conn.readFrom(net.Conn)】,有个用 splice 系统调用的优化,会先试着用 splice 调用在内核里面完成两个 fd 之间的拷贝,这个可以省去将大量数据从 kernel 里面拷贝到 user space 的操作。如果失败才正常拷贝。

然而 splice 这个调用可能是为了内部实现方便,目标一方必须是 pipe 类型的 fd。所以 golang 里面的实现其实比较龌龊,先创建一对 pipe fd,然后从源 fd splice 进 pipe 入端,接下来从 pipe 出端 splice 到目标 fd。 这样下来一个 readFrom 操作,里面要一次 pipe2 调用,2 次 splice 调用,还有 2 次 close 操作关掉 pipe。有趣的是,即使这么龌龊的实现,在数据量大的应用,比如 proxy 上面,依然可以达到比直接拷贝更好的性能,可以参考下面的第一个链接。

唯一感觉比较不爽的也就是每次 readFrom 都要创建 pipe 再销毁了,这个为了不影响 golang 的架构设计,可能也只能这么做。不过一般 proxy 里面最后大多是 io.Copy ,而这个调用一旦调用就直到 tcp 连接断开了,生命周期不会太短,所以完全没有必要再做任何优化了。

参考传送门

https://github.com/golang/go/issues/10948
https://github.com/golang/go/blob/0e85fd7561de869add933801c531bf25dee9561c/src/net/tcpsock_posix.go#L47
https://man7.org/linux/man-pages/man2/splice.2.html

用RenderDoc和安卓模拟器抓帧手游

知乎上有一篇用 Intel GPA 和安卓模拟器抓帧手游的帖子,不过 Intel GPA 配置相对比较繁琐,还有版本问题。还是 RenderDoc 比较习惯。所以研究了一下如何用RenderDoc来抓帧模拟器,倒是蛮简单的。这样手游只要能用模拟器运行,就一定可以被抓帧,什么 ro.debuggable 啊,USB 调试啊都不需要管,root 也不用开,绝无被检测到的可能。

首先要设置 Windows 环境变量 RENDERDOC_HOOK_EGL = 0 ,这个是为了防止 RenderDoc 把模拟器里面实现的 GLES API 给 Hook 了的同时还 Hook 了 DirectX 造成冲突。设置的时候需要右键点击我的电脑(Win10里面叫此电脑),选择属性里面有个修改环境变量的地方。不要试图在命令行上设置,没有用。

其次把模拟器的渲染模式改成 DirectX,原因同上。

在 RenderDoc Tools->Settings->General 里面找到 Allow global process hooking 并勾选

然后找到模拟器的核心文件,一般是一个叫 XXXHeadLess.exe 的文件,也可能是其他的。找到的方法很简单,模拟器里面随便运行一个手游,然后任务管理器里面按照 CPU 使用排序,排在最前面的就是,右键点击之,选择打开文件所在位置。就可以找到核心文件的位置。

在 RenderDoc 的 Launch Application 页面里面。Executable Path 选择刚才找到的模拟器核心。然后在下面 Global Process Hook 里面点 Enable Global Hook,如果提示需要 Administrator 启动就确定以后再点 Enable Global Hook 按钮。

退掉所有模拟器,(注意一定要退干净,有时候模拟器界面关掉了,核心还在后台运行。可以在任务管理器里面查看模拟器的核心是否还在运行,还在运行的话用任务管理器杀掉)然后重新启动模拟器,这时候应该能看到模拟器画面左上角已经显示 RenderDoc 的信息了,如果没有,请检查前面操作是否正确,没有RenderDoc的显示信息说明完全没有加载成功。

RenderDoc File 菜单 Attach to Running Instance , 在 localhost 下面可以看到模拟器核心程序,选中并点击 Connect to app ,之后就正常抓帧即可。

* 如果模拟器里面没有启动手游,而是停在桌面上的话,刚 Connect 上的时候有可能会显示 D3D11 Not Present,没法抓帧,不用担心,这是因为模拟器没有渲染动作。正常启动游戏就可以抓了

* 模拟器毕竟是把安卓的渲染 API 给翻译到 D3D11 API,所以确实有可能和实际渲染操作有些许差别,特别是采用多线程渲染方式的手游,抓帧下来的结果时序很有可能是不对的,这个就没有办法了,就当个补充好了。

* 我测试都是用 64 位模拟器做的,没试验 32 位的行不行

最近评论

时光机

其他