中文圈程序员的碎碎念
509 subscribers
3.52K photos
21 videos
129 files
28.7K links
嘿!你也来看码农又在写啥BUG了吗
Download Telegram
20250808

人要做到自律真的太难。说好的早上看书下午写代码,结果七点起来坐到餐桌前,就忍不住打开 Vibe Tunnel 连上办公室电脑开始让它写了,吃早餐前已经消耗了五千万 token。

说实话这种状态让我很难受,最近写代码这件事已经打破了我好不容易得来的内心平静。最难受的还不是这个,而是消耗了一亿 token 的改动被我放弃了。昨天我还说现在创造的方式是直接让 AI 写,写得好的留下,不好的重新写。实际上放弃让我痛苦,虽然我一行也没写,但是我在计算我监工的时间。人是贪婪的,即使比以前快了十倍,依然不会满足。我得快点调整,对我来说最珍贵的依然是内心的宁静。

这个时候我又会看看我自己的文档《如何过好每一天》,然后继续听音乐、看书,记一些今天学到的东西。

今天听《Misty》,我又买了一张 45 转的高音质版。上周末调音后,真觉得改变很大。

via 61’s life
Cocos 2.X如何通过命令行指定自定义引擎路径

最近转型成了无情的流水线工程师,天天就是帮组里的同事编写构建流水线。


需求

目前有个需求就是希望可以在流水线构建的过程中,指定自定义路径的引擎。

困境

翻遍了整个Cocos文档和论坛,在Google上找了2-3个月都没找到2.X的项目,究竟要怎么样才能在命令行构建的时候指定自定义引擎路径。3.X官方倒是给命令行新增了参数,用于指定自定义引擎的位置。

3.x可以通过–engine参数来手动指定引擎路径 https://docs.cocos.com/creator/3.8/manual/zh/editor/publish/publish-in-command-line.html

解决

今天在翻看定制化引擎的时候,偶然发现了这个技巧,超级无敌简单。就是在项目的根目录下创建一个local文件夹,然后在里面设置一个settings.json,就可以轻松指定项目所使用的自定义引擎路径了。

我这里还写了个nodejs的脚本来辅助创建,分享给大家使用:

https://gist.github.com/7gugu/ecee1fa0f14a91615c0f94ee6496b138

使用方法:

在项目根目录下运行这个脚本

node customEnginePath.js --path=&LTYour Custom Engine Path>

使用CocosCreator构建的时候,就会自动使用你指定的引擎进行构建。

CocosCreator内看不到这个设置是正常的,构建的时候是会使用自定义引擎进行构建的。

via 7gugu's Blog
Arduino烧录hex固件的多种方法

Arduino MCU HEX 文件下载器(烧录软件)我搜了一下,还是有不少的,但很多只支持原生 Arduino 开发板,对于 STM32,ESP32,ESP8266 很少有支持的,目前我找到的仅有 Freematics Builder 支持 ESP32。

ZTFlashWriter

ZTFlashWriter 是哲涛工程师基于 Arduino 1.8.9 软件开发的离线 Arduino HEX 文件下载工具。 本工具不需要 Arduino IDE,即可直接把 HEX 文件下载到 Arduino 相关主板上。 本软件支持批量烧录,可以同时给连接在一台主机上的15个主板烧录同样的固件(HEX文件)。
本软件支持常见的所有 Arduino 原生开发板。
本软件不需要安装, 下载后解压即可打开使用。
本软件仅适用Windows系统,建议在Windows10+中使用。
下载链接:
https://www.zhetao.com/mcu-download-tools.html

ZTFlashWriter

OpenJumper Serial Assistant

同样的一款 Windows 下的 HEX 下载工具,看文件目录,下载应该是基于 avrdude,仅支持原生的 Arduino 开发板。而且该软件不开源,还停留在十几年前,适合老电脑使用。
下载链接:
OpenJumper Serial Assistant 1.3.6beta.zip 链接:https://pan.quark.cn/s/b056c8c8bff6
提取码:QsLB

软件介绍:
https://openjumper.com/doc/install
https://www.cnblogs.com/wind-under-the-wing/p/14686625.html

Freematics Builder

这是一个卖 OBD 公司开发的,主要是针对自己的产品,所以只有几种型号的 Arduino 支持,但是可以下载到 ESP32。
下载链接:
FreematicsBuilder-1.3.1-win32.zip 链接:https://pan.quark.cn/s/9b9790da046a
提取码:7Rxy

Freematics

有在 GitHub 提供下载,但似乎没有开放源码:https://github.com/stanleyhuangyc/Freematics/releases
使用介绍:https://blog.csdn.net/LostSpeed/article/details/129730169

avrdude

这个是命令行下载工具,支持 Windows,Linus,Mac,也仅支持 Arduino 原生开发板。
开发者源码:
https://github.com/avrdudes/avrdude
使用介绍:
https://hackmd.io/@Jub9Bu1BR0qRYeSAA0wUJQ/SkvOGZIE6

Arduloader

也是一款 Windows 下的工具,十年前的软件,仅支持 Arduino 原生开发板。
开发者源码:
https://github.com/uname/Arduloader
使用介绍:
https://uname.github.io/2015/07/15/arduloader/

via 不吐不快
SetWindowText 引起的死锁

最近发现我在写的小游戏在启动时有很小的概率黑屏。我使用的是 ltask 多线程框架,在黑屏时感觉 ltask 并没有停止工作,似乎只是管理窗口的部分(线程/服务)卡死了。

窗口管理使用的是 sokol_app 做的多平台封装,这只是一个很浅的封装层,但已经够用。我觉得美中不足的是,sokol_app 的 frame 回调函数是放在 WinProc 中,由 Windows 的消息循环被动调度,而不是放在外层的主动 GetMessage 循环中。

即,在 Windows 程序中,线程通常会在最外面写一个这样的 while 循环:

for (;;) {
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
return;
TranslateMessage(&msg);
DispatchMessage(&msg);
}

// 在这里,我们可以做一些额外的工作,比如渲染游戏画面、处理游戏逻辑。
}

但我们也可以选择在窗口的 WinProc 中,通过响应 WM_TIMER 等消息的方式来做这些工作:

LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_TIMER :
// 在这里,可以定时做一些工作。
break;
}
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}

// 外面的消息处理循环则可以使用 GetMessage 而不是 PeekMessage

while(GetMessage(&msg, NULL, 0, 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}


无可厚非,后一种方法显得更正规一点:让 Windows 自身调度所有任务,系统如果做的正确,和系统的窗口系统本身契合的更好一点。这个模式是 Window 的历史设计造成的。把窗口系统的工作流程放在用户线程内,用户的程序其它部分配合它,换取交互的流畅度。

但是,一旦采用多线程设计,就变得有点不同了。窗口只是多线程任务的一部分,需要一个更高阶的框架来调度任务,例如 ltask 干的那些。通过在 WinProc 中处理对应消息,在没有消息进入的时候,线程会堵塞在 GetMessage 函数中。这对 ltask 这样的调度器来说非常的不友好。通常一个任务调度器需要的行为是:每个任务要么完成,要么让出,而不是阻塞。Windows 的 GetMessage/DispatchMessage 也是这样的循环,只不过是单线程的。

ltask 处理这样的模块,也不是完全没有办法。这得益于 ltask 的任务都运行在 lua 虚拟机上,和 C 层有一定的隔离。对于 C 代码来说,stack 是绑定在线程上的,所以无法在一个线程运行一半,然后在另一个线程继续工作(因为 stack 不同);但 Lua 的 stack 在 heap 上,迁移完全没有问题。

我曾经做过类似的尝试 ,但最终又从 ltask 主干上撤销了这个特性。倒不是实现的不对,而是配合它使用的 C 代码如果重入问题解决不好,隐藏的 bug 很难发现。这需要 C 部分最好在设计时就考虑过并行/重入问题。sokol 显然不是这样设计的。

----------------------

为了让 sokol 可以在 ltask 下工作,我做了不少工作。sokol_gfx 的图形 api 部分倒是简单,我只需要保证在同一个服务中调用就可以了;比较麻烦的是 sokol_app 中处理窗口的部分。直接让 frame 回调函数运行在 ltask 的一个服务中非常困难。原因上面已述:这个回调函数结束后线程会挂起在 Windows 的消息处理循环中,而没有将控制权归还 ltask 。虽然可以通过 ltask 那个实验特性解决这个问题,但 sokol 并没有为多线程设计,很可能隐藏多线程 bug ,一旦出现难以调试。

我试过几个方案后,最终采用了最简单粗暴的方法:利用锁来同步任务。也就是在 frame callback 开始时抛出一个消息,并阻塞在一个锁上。这个消息会开启另一个 ltask 掌握的线程中对应的 render 服务;而在 render 服务渲染完当前帧,解开这个锁,frame callback 就会顺利返回。

在绝大多数场景中,这个方案工作的很好。但我最近偶尔发现在启动程序时,会有很小的概率,锁并没有解开。

一开始我并不为意,觉得或许是一些同步代码没有写好,因为有更想做的特性要开发,这种偶发死锁 bug 出现概率很低,且只出现在启动阶段,想着有空稍微复查一下启动代码就能解决。

这两天感觉的确“有空”了,花了一晚上,终于定位了问题。

问题出在游戏启动阶段改变窗口的标题上。固然,可以在窗口创建时就把标题设置好。但标题需要根据多语言环境设置不同的文本,处理多语言文本的这块逻辑不算简单,我不想放在启动的最初阶段(创建窗口之前),所以窗口创建时使用了一段默认文本,之后才修改它。

sokol_app 的 api 只是间接调用了 SetWindowTextW() 。显然不是 sokol_app 的封装问题。我查阅了 msdn ,发现 SetWindowTextW 只是给 WinProc 发送了一个 WM_SETTEXT 消息。也就是说,等价于调用 SetMessageW()

如果在 WinProc 所在线程中调用它当然没有问题,只是引起了 WinProc 重入:调用方在 frame callback 内,而 frame callback 处于 WinProc 的 WM_TIMER 的消息处理环节。这时调用 SetWindowTextW 等于递归再运行一次 WinProc 本身,但消息变成了 WM_SETTEXT ,新的调用返回后窗口的标题栏就被改变了。

可是,我现在在另外一个线程调用 SetWindowTextW 行为有所不同。这时 WM_SETTEXT 被投递到窗口消息处理线程,它需要排队等待 WinProc 再次被处理,也就是外层循环的下一次 DispatchMessage 调用。但是,这个时候当下的 DispatchMessage 还阻塞在 frame callback 的锁上面无法返回。这就是死锁产生的原因:

1. DispatchMessage 调用 WinProc 处理 WM_TIMER 消息,它调用了 sokol 的 frame callback 。我的程序在 frame callback 中发出消息唤醒真正的处理流程,并等待在锁上。
2. 真正的处理流程运行在另外线程,它调用了 SetWindowTextW ,其通过 SetMessageW 投递 WM_SETTEXT 到窗口线程的消息队列,等待返回。
3. 窗口线程需要等当前的 WM_TIMER 处理完毕才 DispatchMessage 才可以结束,后续的 GetMessage 才可以拿到 WM_SETTEXT 消息处理它。

了解了死锁的原因后,最直接的解决方案是在窗口线程调用 SetWindowTextW 。因为这样会直接运行设置文本的逻辑,消息不需要进入消息队列,当然就没有锁的问题。但这个方案不适合现在的 ltask 框架。目前窗口线程不在 ltask 的管辖之下,也就无法在 lua 服务中调用 SetWindowTextW ,也无法直接通过 ltask 内部的消息把这个任务传递过去。

但在 ltask 中,开启新的线程却非常容易。只需要用一个独立的服务调用 SetWindowTextW 就够了。frame 的处理流程所在的服务/线程向它投递一个 ltask 消息,通知这个独立服务改变窗口标题,就不会阻塞 frame 流程。

via 云风的 BLOG
SetWindowText 引起的死锁

最近发现我在写的小游戏在启动时有很小的概率黑屏。我使用的是 ltask 多线程框架,在黑屏时感觉 ltask 并没有停止工作,似乎只是管理窗口的部分(线程/服务)卡死了。

窗口管理使用的是 sokol_app 做的多平台封装,这只是一个很浅的封装层,但已经够用。我觉得美中不足的是,sokol_app 的 frame 回调函数是放在 WinProc 中,由 Windows 的消息循环被动调度,而不是放在外层的主动 GetMessage 循环中。

即,在 Windows 程序中,线程通常会在最外面写一个这样的 while 循环:

for (;;) {
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
if (msg.message == WM_QUIT)
return;
TranslateMessage(&msg);
DispatchMessage(&msg);
}

// 在这里,我们可以做一些额外的工作,比如渲染游戏画面、处理游戏逻辑。
}

但我们也可以选择在窗口的 WinProc 中,通过响应 WM_TIMER 等消息的方式来做这些工作:

LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_TIMER :
// 在这里,可以定时做一些工作。
break;
}
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
}

// 外面的消息处理循环则可以使用 GetMessage 而不是 PeekMessage

while(GetMessage(&msg, NULL, 0, 0) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}


无可厚非,后一种方法显得更正规一点:让 Windows 自身调度所有任务,系统如果做的正确,和系统的窗口系统本身契合的更好一点。这个模式是 Window 的历史设计造成的。把窗口系统的工作流程放在用户线程内,用户的程序其它部分配合它,换取交互的流畅度。

但是,一旦采用多线程设计,就变得有点不同了。窗口只是多线程任务的一部分,需要一个更高阶的框架来调度任务,例如 ltask 干的那些。通过在 WinProc 中处理对应消息,在没有消息进入的时候,线程会堵塞在 GetMessage 函数中。这对 ltask 这样的调度器来说非常的不友好。通常一个任务调度器需要的行为是:每个任务要么完成,要么让出,而不是阻塞。Windows 的 GetMessage/DispatchMessage 也是这样的循环,只不过是单线程的。

ltask 处理这样的模块,也不是完全没有办法。这得益于 ltask 的任务都运行在 lua 虚拟机上,和 C 层有一定的隔离。对于 C 代码来说,stack 是绑定在线程上的,所以无法在一个线程运行一半,然后在另一个线程继续工作(因为 stack 不同);但 Lua 的 stack 在 heap 上,迁移完全没有问题。

我曾经做过类似的尝试 ,但最终又从 ltask 主干上撤销了这个特性。倒不是实现的不对,而是配合它使用的 C 代码如果重入问题解决不好,隐藏的 bug 很难发现。这需要 C 部分最好在设计时就考虑过并行/重入问题。sokol 显然不是这样设计的。

----------------------

为了让 sokol 可以在 ltask 下工作,我做了不少工作。sokol_gfx 的图形 api 部分倒是简单,我只需要保证在同一个服务中调用就可以了;比较麻烦的是 sokol_app 中处理窗口的部分。直接让 frame 回调函数运行在 ltask 的一个服务中非常困难。原因上面已述:这个回调函数结束后线程会挂起在 Windows 的消息处理循环中,而没有将控制权归还 ltask 。虽然可以通过 ltask 那个实验特性解决这个问题,但 sokol 并没有为多线程设计,很可能隐藏多线程 bug ,一旦出现难以调试。

我试过几个方案后,最终采用了最简单粗暴的方法:利用锁来同步任务。也就是在 frame callback 开始时抛出一个消息,并阻塞在一个锁上。这个消息会开启另一个 ltask 掌握的线程中对应的 render 服务;而在 render 服务渲染完当前帧,解开这个锁,frame callback 就会顺利返回。

在绝大多数场景中,这个方案工作的很好。但我最近偶尔发现在启动程序时,会有很小的概率,锁并没有解开。

一开始我并不为意,觉得或许是一些同步代码没有写好,因为有更想做的特性要开发,这种偶发死锁 bug 出现概率很低,且只出现在启动阶段,想着有空稍微复查一下启动代码就能解决。

这两天感觉的确“有空”了,花了一晚上,终于定位了问题。

问题出在游戏启动阶段改变窗口的标题上。固然,可以在窗口创建时就把标题设置好。但标题需要根据多语言环境设置不同的文本,处理多语言文本的这块逻辑不算简单,我不想放在启动的最初阶段(创建窗口之前),所以窗口创建时使用了一段默认文本,之后才修改它。

sokol_app 的 api 只是间接调用了 SetWindowTextW() 。显然不是 sokol_app 的封装问题。我查阅了 msdn ,发现 SetWindowTextW 只是给 WinProc 发送了一个 WM_SETTEXT 消息。也就是说,等价于调用 SetMessageW()

如果在 WinProc 所在线程中调用它当然没有问题,只是引起了 WinProc 重入:调用方在 frame callback 内,而 frame callback 处于 WinProc 的 WM_TIMER 的消息处理环节。这时调用 SetWindowTextW 等于递归再运行一次 WinProc 本身,但消息变成了 WM_SETTEXT ,新的调用返回后窗口的标题栏就被改变了。

可是,我现在在另外一个线程调用 SetWindowTextW 行为有所不同。这时 WM_SETTEXT 被投递到窗口消息处理线程,它需要排队等待 WinProc 再次被处理,也就是外层循环的下一次 DispatchMessage 调用。但是,这个时候当下的 DispatchMessage 还阻塞在 frame callback 的锁上面无法返回。这就是死锁产生的原因:

1. DispatchMessage 调用 WinProc 处理 WM_TIMER 消息,它调用了 sokol 的 frame callback 。我的程序在 frame callback 中发出消息唤醒真正的处理流程,并等待在锁上。
2. 真正的处理流程运行在另外线程,它调用了 SetWindowTextW ,其通过 SetMessageW 投递 WM_SETTEXT 到窗口线程的消息队列,等待返回。
3. 窗口线程需要等当前的 WM_TIMER 处理完毕才 DispatchMessage 才可以结束,后续的 GetMessage 才可以拿到 WM_SETTEXT 消息处理它。

了解了死锁的原因后,最直接的解决方案是在窗口线程调用 SetWindowTextW 。因为这样会直接运行设置文本的逻辑,消息不需要进入消息队列,当然就没有锁的问题。但这个方案不适合现在的 ltask 框架。目前窗口线程不在 ltask 的管辖之下,也就无法在 lua 服务中调用 SetWindowTextW ,也无法直接通过 ltask 内部的消息把这个任务传递过去。

但在 ltask 中,开启新的线程却非常容易。只需要用一个独立的服务调用 SetWindowTextW 就够了。frame 的处理流程所在的服务/线程向它投递一个 ltask 消息,通知这个独立服务改变窗口标题,就不会阻塞 frame 流程。

via 云风的 BLOG
Weekly Issue-《初步举证》

文章

技术

iPotato | 使用 Cloudflare Workers 搭建轻量级 LLM API 网关

LLM API Gateway 确实很适合 Cloudflare Worker 的场景啊。

----------------------

再也别问 Singleton 了好吗? - Frost’s Blog
先说结论:在 Python 中,你不需要 Singleton。如果需要,就用模块级别的变量。

----------------------

Nil channels in Go

for select 一个 nil chan 相当于跳过这个 case,没有 default 的场景就死循环了。

----------------------

“As Code”
My intent with “X as Code”3 was always to get knowledge out of people’s heads and into a more inscribed system. Once inscribed, knowledge and process can be shared, versioned, iterated upon, etc.

----------------------

生活

How to pick a starter project that’ll make someone quit

翻译为人话就是:如何快速让一个员工主动离职?边看边笑,笑着笑着就哭了,感觉在小公司里很容易发生这样的事情:

不要让他们安顿下来;
选择一个大型项目;
选择有争议的项目;
让他们自己决定需求;
尽可能多让他们处理跨团队的工作;
引入新的技术栈;
引入非编码工作;
确保他们负责的项目是 blocking;
让最忙碌的人是他的 mentor;
延迟回复所有疑问;

----------------------

习得送礼的技能 - 白宦成

[[送礼]]确实是需要学习的,我之前是一个完全的实用主义,送的东西都是对方可能会用到的东西。后来去学习了一下,发现这是完全错误的方式。一个好的礼物可以拓展对方的生活边界,比如一个新的兴趣方向,一次美好的体验等等。

----------------------

书影

《善意的竞争》,我觉得属于烂尾了。想想它毕竟是一个漫改剧,稍微有些跳脱好像也能理解了,那就是编剧不行。

----------------------

《“骗骗”喜欢你》,金晨主演,大鹏监制(最近可能会在很多热门院线电影看到监制这个词,宋方金在播客里提到,现在有一种站台/背书的意思)。符合谐音梗喜剧的预期,算是及格吧,属于那种在院线上映后可看可不看的类型。王皓的脸很僵硬,撑不起大荧幕。

----------------------

《愤怒到凌晨4:00》,夏夏单口喜剧专场。上次看完嘻哈的《茁壮》之后,写到“在演出结束之后,我脑子里想到的一个演员是夏夏,北京单立人的单口演员,是陕西人,因为她俩在演出过程中表现的那种愤怒,是一致的,只是夏夏的愤怒带来的更多是不解,去内化,而嘻哈的愤怒带来的是行动,这点真是少见。“。夏夏变了,和《焦虑青年》中的她变化很大,变化的原因我觉得也正是这个专场中提到的几件事情,是这些事情让她变得更加强大,无畏。现在的她,还是会愤怒,愤怒之后带来的是行动,极强的行动力,且有一种不达目的不罢休的态度,也可以用”疯“来形容。

----------------------

《初步举证》,朱迪·科默独角戏,话剧电影版,强烈推荐每一个朋友去看,我看的那场算上我一共 4 个人,一对情侣,还有一个男生看了半小时走了。刚开始的 10min,台词密集、角色穿插、主角一个人快速高强度的交代背景,让我有些不适应,但是随着剧情的推进,很快的沉浸其中。

剧情本身是简单的,年轻有为的刑辩律师,面对自己的法律信仰,当自己的角色被告律师转为原告,会发生什么?律师角色的她是自信的,是对未来生活抱有向往的,觉得原告失败与自己无关,是警察能力不行;原告角色的她,无助,惊慌失措,自我怀疑,之后站在法庭上的她又是那么的勇敢。影片全篇信息量很密集,唯独一段,782 天,难以想象这 782 天是如何度过的。

朱迪·科默,最早知道她是在《杀死伊芙》中,演绎一个女杀手,留下了很深的印象,我在看《初步举证》之前还在担心,是否会跳戏,事实是不会。她的表演太震撼了,角色穿插,表情的变换,时空的转换,那么的自然和真实。致敬。

碎碎念

我好像遇到问题,第一想法是先找自己的问题,不会去想是否是对方做的不对。
在日常场合聊 NSFW 的话题我就很抵触,更不用说工作场合了。
ByoCoreBMC 是我用过最垃圾的 BMC,明明是基于 OpenBMC 来的,怎么搞成这个样子呢?
“现象”和“问题”是两个概念,为啥总混为一谈呢。
对自己说过的话要负责,可能一句话会给别人带来不少的工作量。
嘿,我今天控制住了自己的一次输出冲动,真不错。
蝴蝶机 65kg,还挺顺利的,也许我早就可以上 65 了?
现在国产剧的广告已经嵌在剧集本身了,不给跳过的机会啊。

via Yiran's Blog
Weekly Issue-龙架构双周会

文章

技术

Why Go? · microsoft/typescript-go · Discussion #411 · GitHub

X
Snobbery looking down on anyone not using it and a completely irrational feeling culture of rewriting everything. As Steve says, this may be perception more than reality. It may be a small (but obnoxiously loud) minority. It really might. But it was enough that at the time it was my reality and I wanted nothing to do with it.
尽管已经给出了详细的原因,评论中的很多人还是充满了傲慢。

----------------------

踩坑异闻录——Windows 前端工具链之痛 - 三咲智子 Kevin Deng

身边用 [[Windows]] 开发的同事只有一个,如果只是兼容性问题还是好的,大部分项目中的 Makefile/Taskfile 等 setup 工具,有可能完全没有考虑 Windows 用户,经常会遇到一些只有他会遇到的问题。

----------------------

第 6 次龙架构双周会

这个报告中的“浅评商业软件发型乱象”,如果是平时工作中涉及到一些 Linux 发行版内容的,强烈推荐阅读,看着看着就笑了,笑着笑着就哭了。里面提到了一些商业软件存在的问题:

明明程序对其他 so 有依赖,但是不在包管理器中指定; “只要有群友教,没什么不可以解决的”
安装程序权限控制不明确,影响范围不可控
通过包管理器的 postinst 脚本来做一些隐蔽的事情
不使用系统提供的基础设施进行系统状态探测、随意猜测配置文件内容


只要是涉及到软件交付的,都会面临这样的问题,无论是 2C 还是 2B,2B 的单一软件还是软硬件一体,都面临这个问题。有时候以为自己交付的 OS 是自己可以控制的,所以做了一些hack 的事情,假设了用户不会对 OS 内部做变更,但最终软件是在用户环境中运行的,很多假设都是不成立的(也是不合理的),导致后续引发更多的问题。

平时都会吐槽外部的软件不遵循一些业内通用标准,其实公司内部的软件也没几个遵循的,“又不是不能用”的理念到处存在。最终只会导致软件越来越臃肿,一个又一个补丁,最终陷入恶性循环。

----------------------

从 DeepSeek LLM 到 DeepSeek R1 —— DeepSeek LLM | Oilbeater 的自习室
从论文的路径上来看就是 DeepSeek LLM -> DeepSeek MoE -> DeepSeek V2 -> DeepSeek V3 -> DeepSeek R1。在整理论文时我才发现,DeepSeek 第一篇对外发布的论文是在 2024 年的 1 月,当时他们刚发布第一版模型,即使在 AI 行业内也不被认为是个主要竞争者。然而仅仅一年后的 2025 年 1 月,就已经进化到了 R1 这种业界领先水平。都说 AI 一天,人间一年,但是当真看到人间一年的进展时,还是深深的被 DeepSeek 的速度所震撼。

----------------------

Yoke is really cool - Xe Iaso
官方文档: | yoke
示例代码:yoke-stuff/within-website-app/v1/app.go at main · Xe/yoke-stuff · GitHub

[[Yoke]] 是一个 [[kubernetes]] 的包管理器,定位与 [[Helm]] 和 [[Timoni]] 相同,Yoke 的 Flights 相当于 Helm 的 Chart。主要的区别是 Yoke 不使用 YAML/CUE 等配置语言,而是使用通用的编程语言来描述资源,可能会想到 [[Pulumi]] ,与 [[Pulumi]] 不同的是,Pulumi 需要准备对应语言的 runtime 和 deps,Yoke Flights 的发布形态是 [[WASM]],Flights 接收输入参数,输出 Kubernetes 资源描述,这里有点疑问,Flights 的接收参数如果过多,最终不会演进为需要一个配置文件的程度么?

Yoke 引入了 ATC 解决这个问题,ATC 是一个 Kubernetes controller,通过定义 CRD,并与对应的 Flights 进行关联,从而将用户声明的配置转换为 Flights 需要的输入,最终部署到集群中。相当于一个简化版的 Operator ?

Flights 的发布形式是 WASM,那其他人如何了解对应的 Flights 的定义?需要引入其他的文档描述?关于 WASM 的能力,官方文档提到 Yoke 暴露了 K8s lookup 接口,这个接口能力足够么,会是一个限制么?

----------------------

IO devices and latency — PlanetScale

[[PlanetScale]] 的博客,图示生动形象。

----------------------

生活

《双影奇境》:一部无与伦比、超乎想象、精彩绝伦的双人游戏作品 - Simon’s Blog
对于电子游戏,在很长一段时间里,我都陷入了“电子阳痿”的状态里:虽然我有switch、ps5、pc等一众游戏设备,但几乎对所有的游戏都提不起兴趣;在近几年中,我尝试玩过很多优秀的电子游戏大作,但没有任何一款游戏可以让我持续坐在电脑前面、全神贯注地游玩几天,直至通关。我得承认,随着年龄的增长,电子游戏似乎已经离我越来越远,我也对游戏的兴趣越来越少。
但《双影奇境》这款游戏让我前面所提到的一切负面状态近乎完全消失。《双影奇境》是近几年唯一让我能够废寝忘食地在电脑面前持续游玩了14.8小时,直至通关的游戏。
非常高的评价了。

----------------------

聊天也要讲逻辑 | So!azy
对话中存在两种让我头疼的现象:一种是「驴唇不对马嘴」,另一种是对方把「两件事」揉在一起聊。这两种情况虽然有些相似,但本质上不太一样,却都会让我觉得沟通变得异常艰难。
这种对话让我反思,逻辑清晰真的很重要。不是每个人都要像科学家一样严谨,但如果连基本的事实和因果都串不起来,那得出的结论只能是空中楼阁。我不否认情绪和直觉有它的价值,可如果完全抛开理性,把毫不相关的碎片硬凑在一起,这样的沟通不仅解决不了问题,反而会制造更多误解。
一个可能得解决方式是,在无法清楚的表达自己想法的时候,保持沉默,思考,理清之后再回复。

----------------------

书影

《流氓读书会》,漫改韩剧,下饭局,只有 10 集。武状元一心想当文秀才的故事。

《仁心俱乐部》,都市医疗剧,看的时候一直在想,为什么和《机智的医生生活》差距那么大,是哪些原因造成的?目前能够想到的是:编剧能力差距太大;对快节奏的变态追求。

碎碎念

买了佳明手表,感觉买晚了,应该早点买。
“Mushroom 听起来像是天津人问 room 这个词“,有笑到。
Narcissistic personality disorder,自恋型人格障碍。
2025 了,一个标准的服务配置居然不提供 container ,而是让我 dnf install mysqld ,有点离谱了。
很多时候大家都知道自己做的东西不好用,只是因为各种各样的原因改不动。
人总是倾向自己更喜欢的推论,老板也喜欢看,大家都开心
新室友是个社牛。
早上问了下写字楼楼下的保安,我所在的这个2号楼,每天上班的人数大概在1000左右。
高驰的表带贵是贵,舒服也是真舒服。
尝试用佳明训练制定了一个跑步计划,4 个月后看看效果
环球港也太大了,体验超大型商场需要充足的体力。

via Yiran's Blog
Weekly Issue-吃早饭!

文章

技术

Why our 5.2k-star K8s platform struggles overseas while thriving in China? Need your brutal feedback : r/kubernetes

[[Rainbond]] 在海外推广遇到了困难,他们观察到的 3 个明显问题是:

声称自己是 “Heroku for Kubernetes” 替代品
Open Source != Trust
Deployment Culture Clash: 75% of Chinese clients demand air-gapped installs (even on edge nodes!), while Western teams expect SaaS-first. 这好像几乎是国内特有的情况了?

评论区中提到了 [[Harbor]] 在世界范围内被采用,是因为他们隐藏了是中国地区开发的。我觉得可能不是主要原因,当时 Harbor 是顶着 [[vmware]] 的光环在的,大家看重的更多应该是 [[vmware]]。对于评论区中的产品选型原因,感觉和行业或者技术壁垒有直接关系,比如 [[TiDB]] 那么多海外用户,[[Clickhouse]] 背后的投资人 [[Yandex]] 是俄罗斯公司,[[Deepseek]] 的开源项目引起的轰动,他们会没有考虑中国/俄罗斯的政治风险么?我觉得肯定考虑了。

下面那篇 TiDB 的文章中,也提到了国际化:
“最好的国际化,就是本地化。”
不同地区的文化差异太大,技术再牛逼,客户支持做不好,客户一样骂你没商量。

----------------------

Storage suppliers stare down Trump slump after tariff mayhem – Blocks and Files

不确定性会阻碍公司进行长远计划(这句话印象中之前一直是用来描述大陆的),现在看由于关税影响,短期内的报价工作都无法正常进行了。。

----------------------

极限编程和命名
尝试去应对变化,而不是预测变化,因为你永远不知道明天的需求是什么。

----------------------

十年再出发:回顾我与 TiDB 的成长之旅

值得反复阅读的经验总结。

----------------------

《The Mom Test》读后感

关于如何做用户调研的一些技巧。我的总结是,如果带有预设的去聊,对方作为用户可能什么都要,但是这些并不是真正需要的,不能看对方说了什么,要看对方 做过 什么,从对方 做过 的事情来吸取经验。

----------------------

DuckDB’s CSV Reader and the Pollock Robustness Benchmark: Into the CSV Abyss – DuckDB

[[DuckDB]] 尽可能的以兼容方式来读取 [[CSV]] 的方法:
FROM read_csv('cafes.csv',
strict_mode = false,
null_padding = true,
quote = '"',
escape = '"'
);

想到之前帮朋友处理一个奇奇怪怪数据的 Excel 的痛苦,当时好像用 [[pandas]] 手动处理了很多边界场景。

----------------------

Building OpenAPI Based REST API In Go Using HUMA Framework, With SurrealDB | by Shiju Varghese | Apr, 2025 | Medium

这篇文章中推荐了 GitHub - danielgtaylor/huma: Huma REST/HTTP API Framework for Golang with OpenAPI 3.1 ,之前在做新项目的时候,考虑使用自动生成 [[openapi]] 文档的框架,不想在 Gin 里面手动写注释生成,当时的选型还有 GitHub - go-fuego/fuego: Golang Fuego - Web framework generating OpenAPI 3 spec from source code - Pluggable to existing Gin & Echo APIs,好像是因为在自定义错误码的处理上不灵活,最终都没有使用,选择了 [[grpc]] + grpc-gateway + buf 自动生成的方式。

----------------------

Automating Linux bare-metal server deployment in Hetzner with Ansible – Palark | Blog

最近因为一个内部 BeraMetal 相关项目的后续迭代方向进行了一些思考,做 BareMetal 太苦了,比如这篇文章中的实现方式,如果没有 [[Hetzner]] API,会非常痛苦。痛苦的点在于:

需要适配大量的服务器品牌(国内和国外是两套生态)
需要适配同一个服务器 BMC 的不同版本 看似存在 Redfish 这样的通用协议,但是落地下来各有不同
需要支持多种引导方式:ISO、PXE、PXE with DHCP
很多操作需要重启才可生效,涉及到上层的业务交互

----------------------

生活

来美国的两年后 - GeekPlux

我发现我越来越喜欢用年为单位去描述事情,可能这就是时间加速感的体现。希望自己能在未来的日子里:

保持好奇,保持谦逊,保持怀疑精神
接受随机,接受老化,接受自我平庸

最近也在想,是否“需要”换一个城市生活,还没有想法。

----------------------

GitHub - jlevy/og-equity-compensation: Stock options, RSUs, taxes — read the latest edition: www.holloway.com/ec

[[股权]]激励指南。 有需要的朋友可以看看,避免发生 zhihu 惨案。

----------------------

2025 清明凤凰经重装徒步 | Xigou Blog

看着确实太苦了,平时我都不徒步,重装徒步就更不可能了。

----------------------

我们高估了智力的重要性 | Randy’s Blog

在知识获取越来越“容易”的时候,其他方面的影响被放大了。

----------------------

I’m Leaving Sentry | Armin Ronacher’s Thoughts and Writings

十年。

----------------------

书影

《火锅艺术家》,一部典型的东北喜剧人电影。

《饥饿站台 2》,和朋友聊到才发现《饥饿站台》出了第二部,能够感受到创作团队想要表达的内容很多,但是最终呈现出来的效果不好。

碎碎念

发现自己之前写的单测完全没生效。。
买了水月雨的 pill 耳机,第一次用耳夹式耳机,使用感觉上还不错,跑步也没有要掉的感觉。耳机壳是败笔,很多人吹有多好“耍”,可以作为解压玩具,但是平时放在包里和裤兜中,经常自己就打开了,缺少固定锁。
吃早饭!不管如何,要吃早饭!

via Yiran's Blog
Weekly Issue-Artificial Intelligence and Human Intelligence

文章

技术

AI Code Review: Should the Author Be The Reviewer?
Humans are bad at catching the types of bugs that AI introduces
之前有过很多次引入的错误很隐蔽的情况,然后靠着单测发现改正的情况。最近貌似没怎么遇到。

----------------------

2025.04 云原生相关信息简报

Cloud Service: What Pope Francis Thought About AI - The New Stack

Antiqua et nova. Note on the Relationship Between Artificial Intelligence and Human Intelligence (28 January 2025)

同事整理的 4 月份云原生相关信息简报,与之前两期相比,这个月的信息量明显大了不少,完整阅读起来需要一些时间,关于教皇对 AI 的看法的文章,截取一些机翻挺有趣的:
将人类智能与人工智能过度等同,有陷入功能主义视角的风险,在这种视角下,人的价值取决于他们能够完成的工作。然而,人的价值并不取决于拥有特定的技能、认知和技术成就或个人成功,而是取决于人固有的尊严,这种尊严根植于人是按照天主的形象创造的。
尽管使用了拟人化的语言,但没有任何人工智能应用能够真正体验到共情。情感不能被简化为面部表情或响应提示而生成的短语;它们反映了一个人作为一个整体,如何与世界以及他或她自己的生活相关联,而身体在其中扮演着核心角色。真正的共情需要倾听的能力,认识到他者不可化约的独特性,接纳他们的差异性,并理解他们沉默背后的含义。
人工智能目前正在取代一些曾经由人类完成的工作。如果人工智能被用来取代人类工人而不是补充他们,那么“极少数人以牺牲多数人的贫困为代价而获得不成比例的利益,存在着巨大的风险。”[126] 此外,随着人工智能变得越来越强大,人类劳动在经济领域失去其价值的风险也随之增加。这是技术官僚范式的逻辑结果:一个人类被效率奴役的世界,最终,人类的成本必须被削减。然而,人类生命本身就具有内在价值,独立于其经济产出。尽管如此,教宗方济各解释说,“当前的模式似乎并不倾向于投资那些帮助行动迟缓、体弱或天赋较差的人在生活中找到机会的努力。”[127] 鉴于此,“我们不能允许像人工智能这样强大且不可或缺的工具来强化这种范式,相反,我们必须使人工智能成为抵御其扩张的堡垒。”[128]
既然工作是“今生意义的一部分,是成长、人类发展和个人成就的途径”,“目标不应该是技术进步日益取代人类工作,因为这对人类将是有害的”[132]——相反,它应该促进人类劳动。从这个角度来看,人工智能应该辅助而不是取代人类的判断。同样,它绝不能贬低创造力或将工人贬低为仅仅是“机器中的齿轮”。因此,“尊重劳动者的尊严以及就业对于个人、家庭和社会经济福祉、对于工作保障和公正工资的重要性,在这些技术更深入地渗透到我们的工作场所时,应该成为国际社会的高度优先事项。”[133]

----------------------

No More BYOK - Amp

随着越来越多应用层面的功能特性追求差异,模型之间的差异会被放大,如果用户使用了非最佳的模型最终得到了较差的使用体验,会直接转换为应用的使用体验。如果反过来呢,应用对模型的要求越低,使用体验越好,大家对应用的体验也越好?这样的应用通常是简单专一的方向么?

----------------------

生活

跑步一年多的一些总结和感想 - 张小凯的博客

看完感觉是厚积薄发的例子,从开始跑 5 公里的 7 分配到 5 分配,只用了 1 个月,羡慕。

----------------------

日本旅游攻略:赴日前的准备与注意事项 - Simon’s Blog

简单有效的[[日本]] [[攻略]]。

----------------------

碎碎念

早上跑完步才发现,已经5月了,4月跑了 108.70 公里,5月继续。
逛公园听到了一句“小男孩要有点阳刚之气”,em
决策质量应基于过程而非结果: 行为科学家和心理学研究表明,一个决策的质量应取决于决策时的信息分析和逻辑过程,而非最终结果的成败。
花了很多时间准备东京旅行上,发现大家写的攻略非常详细,这时候就想反驳 AI 总结论,如果直接用 AI 总结,那么会漏掉很多细节,而且会少了很多对当地的了解。

via Yiran's Blog