• 不是必须的, 只是 webpacker 把它们都用上了而已.

    webpack 的配置很复杂, 配置它的 file-loader / url-loader 也可以. 但感觉你也不想花功夫了解, 所以还是建议拷进来...

  • 和 yarn 没关系, 和你用的包, 和你打包工具 (webpack?) 的 resolve 方式有关系.

    如果你用的包很久没更新过了, 估计它对现在的打包工具没什么概念 (例如 simple-line-icons), 你就直接拷过来好了.

  • select2 有点大啊... 其实用 bootstrap 那样的 dropdown 就可以了

  • 挺好的,但是软件支持不好。

    macOS 的双拼增加了 sougou 键位(以前的微软拼音双拼键位)就回来用了一下

    感觉已经不错了,比默认的键位好。但是 mac 的拼音翻页键不能自定义,不如鼠须管双拼定制性强。

    虽然鼠须管对简体支持实在不怎么样,而且词典不太行……

  • node 不适合 docker, node_modules 这么多, 在 Mac / Windows 会非常慢...

  • 前排

  • File.write 'test1.txt', "标题信息:#{@task.title}", encoding: 'gbk'

  • 楼主的应用性能算不错了, 但当性能优化到一定程度时, 这些追踪的代码就很可能会成为比较大的影响因素了

    1. 本机通信例如应用服务器和 Nginx 之间都用 Unix Domain Socket 而不用端口, 负载均衡/应用服务器/数据库都开启 BBR 和 TCP fast open

    2. 看看火焰图找瓶颈

    • 基于 ruby-prof 的: ruby-prof-flamegraph , 但是 ruby-prof 需要 require 进去, 本身会影响性能. 但是结果基本会反映各方法的 CPU 占用率, 容易找出计算密集的方法
    • rbtrace 类似 strace, 不用 require 就能 sample 请求, 对真机性能基本无影响, 采样结果反映各方法的栈顶耗时, 容易找出网络 IO 耗时长的方法

    \3. 升级 Ruby 或者修改编译参数, 会有一些性能改进

    \4. 日志采集/sentry/newrelic 也很耗性能... 看看线程数有没有大超标

    ActiveModelSerializer 或者 jbuilder 的设计都比较臃肿, 都是消耗 CPU 比较大的库, 可以换个快一点的.

    把不要的 Rack 中间件都去掉, 例如基于 token 的 API 请求就不需要 session 了

  • JIT for MRI 开始开发了 at 2018年03月04日

    但 GCC 的 RTL 和 Markorov 的 RTL 确切来说不是同一套东西, 虽然都属于寄存器机指令...

    现在 Ruby 的字节码指令比较接近栈机指令, 栈机指令特征是很多操作数都是栈上 implicit 的, 总长度可以比较短. 典型的栈机指令是类似这样的:

    push a
    push b
    add # 在栈上 pop 两个元素, 相加, 然后压回栈上
    

    而寄存器机指令, 其中的寄存器也不是指 CPU 里的寄存器, 直接理解为局部变量好了. 典型的寄存器机指令是类似这样的:

    c = add a, b
    

    其中 a, b, c 都是代表局部变量位置的整数.

    稍微跑题一下: 寄存器机指令的好处是总指令数会变少, 但指令编码后会比栈机指令长 (例如 JVM bytecode 编译到 Dalvik bytecode 占空间会变多 30% 左右). 就用上面两个例子来说, 如果用 1 个字节代表 opcode, 那最终编码出来占用空间就是 3 + sizeof(a) + sizeof(b) 字节, 而寄存器机指令编码后占用空间是 1 + sizeof(a) + sizeof(b) + sizeof(c) 字节, sizeof(c) 往往是占空间大于 2 字节的, 不然就得受诸如局部变量不能超过 512 个之类的限制...

    但 YARV 和 JVM 字节码不太一样的地方是, 因为 YARV 的指令是 Direct threading 的, 也就是说 opcode 已经用内存地址替换了. 直接放内存地址可以提高分支预测的命中, 从而提高执行速度.

    再稍微跑题一下: 也有人说 direct threading 是 folk lore, 以现在 CPU 强大的分支预测和推测执行, 用 call threaded 也相差无几. 当然推测执行的副作用不加清理的话, 也会带来类似 spectre 的 bug...

    回题: 内存地址本身占空间巨大, 本来一字节或者不到一字节能表示的 opcode 在 64 位平台就变成了 8 字节, 所以 Ruby 用栈机的空间优势其实不大... 所以替换成寄存器字节码的空间损失并不大, 甚至能省一些内存. 而从寄存器代码生成 JIT 的 C 代码比栈机代码更直接一些, 也更容易让 C 编译器优化一些.

    现在是逐步增强的方式, 先上 mjit, 再上 YARV 转译的 RTL mjit (这时就是 源代码 -> YARV 字节码 -> RTL 中间表示 -> C 代码 -> 编译成动态链接库 -> 载入 的复杂流程...).

    未来会不会把 YARV 替换掉, 或者把 C 换成别的中间表示来缩短这个 JIT 的流程, 就再说咯.