🌸
357 subscribers
127 photos
17 videos
197 links
记录一些 学习笔记,工具,和其它奇怪的东西
Download Telegram
选择视频编解码器

了解了下各个 codec,从编码质量和压缩率来看,目前开放格式里最好的选择就是 WebM/AV1/Opus 这组了,专利格式则是 MP4/HEVC/AAC

不过 AV1 目前并未得到浏览器广泛支持,就连硬解在各个平台上都还不太支持。考虑上这点的话,WebM/VP9/Opus 会更具有吸引力。

尽管如此,如果有可能,始终需要为最坏情况准备好 MP4/AVC (H.264)/AAC 的 fallback 选项。

#learning
HTTP/2 Server Push 细节

HTTP/2 push cache 独立于 HTTP cache,由 server 推送的资源,仅在使用后进入 HTTP cache 并从 push cache 中移除,在推送时也不会检查其 Cache-Control header。

它基于 connection,若 connection closed,则 push cache 消失。由于 HTTP/2 中的一个 connection 除了被多个 requests 复用,还可以在多个 pages 间共享,因此 push cache 也会相应得到共享。这甚至意味着,它可以在具有同一 IP、同一 cert 的跨多个 origin 间共享缓存(即使包含任何应用状态)。

push cache 与其它一众 cache 相比,具有最低的 priority,若 pushed resource 已出现在 HTTP cache 且尚未过期,则使用“较旧的” HTTP cache,若该 resource 仍在传输,则浏览器应该发送一个 CANCEL 或 REFUSED_STREAM frame 以终止 stream。

另外,出于隐私目的,浏览器可能会为带有 credentials 和未带有它的 requests 创建两个独立的 connection,这里的 credentials 可能是 Cookies、HTTP authentication 或 Client certificate。

#learning
刚刚读文章发现两个有意思的写法(但没用!)

false.true = ''

(function () { return arguments.callee })()()


上面两个在 non-strict mode 下都可以运行。想了想第二个可以实现匿名函数递归,不过一般不用 arguments.callee。
发现不同浏览器对 AudioWorklet 支持都多少有点问题,比如 Chrome/Edge 不会在 DevTools Network 记录 audioWorklet.addModule() 的请求,包括后续 import 的模块,这是个 BUG,Firefox 正常。

Firefox 不支持在 AudioWorkletNode 中 import ES6 modules,Chrome/Edge 支持。不过 AudioWorklet Wasm 支持在 Chrome/Edge、Firefox 都挺好。

至于 Safari,我的几个 demo 都跑不起来,emm准确说是跑起来了,也没报错,但就是没声,我也懒得调了。
A visual depiction of glyph metrics

src, src #learning
Go 1.18.4 泛型支持还是有点问题,带 chan 的 union type 自动推断不出来。需要先 any(),再用子类型 T 手动构造
Forwarded from r0 Crew (Channel)
IDA Pro 8.0 released!

* Golang 1.18
* iOS 16 dyld shared cache support
* ARC decompiler
* Better firmware analysis
* FLAIR pattern generator (makepat)

https://hex-rays.com/products/ida/news/8_0/
Chrome 104 现支持 HEVC 硬解

刚刚发布的 Chrome 104 支持了 HEVC 硬解,但目前需要手动开启,在启动时添加 --args --enable-features=PlatformHEVCDecoderSupport 参数。可以使用 https://h265.webmfiles.org/embed-h265-video.php 测试是否成功。

该功能由字节跳动开发,并提交给 Chromium,使用的是操作系统解码能力(Windows D3D11,macOS VideoToolbox),因此不需要交专利费。由于 Windows 7 以下系统仅支持 VDA Decoder,因此不支持 HEVC 硬解。

此外,部分网站通过浏览器 UA 检查是否支持 HEVC,如 Bilibili,因此除添加上述参数外,还需要修改 UA 为先前已经支持的其它浏览器,如 Safari。

ref:
https://v2ex.com/t/870362
https://github.com/StaZhu/enable-chromium-hevc-hardware-decoding
👍1
macOS 的文件单位好混乱,文件大小是按 kB,不是 KB/KiB,但又会显示成 KB。
与 Tab 缩进和解

很长一段时间我都在坚持“2-spaces”缩进,但直到今天我才意识到,这种风格的要点,不在“Space”,因为即使是“Tab”,只要将 size 调整为 2 就行了。

这算是长久以来我对“Tab”的和解,纠结 Spaces or Tabs 是没意义的,现在看来,我只是在纠结缩进的宽度。

在下个项目,我将尝试使用 1-tab 缩进,并设置 tab 的 size 为 2。

这样做有 2 个显而易见的好处:更少的字符占更少的空间;其他人可以根据自身偏好设置 tab 的 size。

BTW:GitHub 也提供了 设置 tab size 的选项,我目前把它设置为 2。

#thinking
在 Go 中复用一个 io.Reader

io.Reader 表示一个 stream,而 stream 只能被读一次。因此有两种复用方式:

一、边读边缓冲到 Buffer

var (
r = strings.NewReader("hello world")
buf = new(bytes.Buffer)
)
foo(io.TeeReader(r, buf))
bar(buf)

二、使用 Pipe,本质是个 ReaderWriter

var (
r = strings.NewReader("hello world")
pr, pw = io.Pipe()
)
go foo(io.TeeReader(r, pw))
go bar(pr)


由于 Pipe 是无 internal buffering 的,因此需要使用两个 goroutine 并行读写。对于多个 Pipe 可以:

var (
r = strings.NewReader("hello world")
pr1, pw1 = io.Pipe()
pr2, pw2 = io.Pipe()
pr3, pw3 = io.Pipe()
)
go foo(pr1)
go bar(pr2)
go baz(pr3)
io.Copy(io.MultiWriter(pw1, pw2, pw3), r)


#experience
Transferable objects in JavaScript

像 Buffer、Stream、Bitmap 这类对象,都做成了 Transferable,它们可以安全地在两个线程间转移,这是一种 zero-copy 操作。

一、在 Worker 之间转移

const u8 = new Uint8Array(1<<10)
const worker = new Worker(URL.createObjectURL(new Blob()))

u8.byteLength // 1024
worker.postMessage(u8, [u8.buffer])
u8.byteLength // 0

二、在 clone 时转移

const u8 = new Uint8Array(1<<10)
u8.byteLength // 1024

const trans = structuredClone(u8, {transfer: [u8.buffer]});
u8.byteLength // 0
trans.byteLength // 1024


#learning
渐变好难调啊,调了半天感觉我已经成了色盲了,分不清红绿蓝了,红里透着绿,绿里透着蓝emm
HTTP/2 可能没 HTTP/1.1 快

HTTP/2 最大变化是引入单独的成帧层,支持了多路复用,允许交错接收多个资源。如 a.jsb.css,HTTP/1.1 只能顺序的 aaaabbb 接收,而 HTTP/2 允许 abababa

但这种交错对浏览器来说,不一定是好事,因为浏览器必须完整接收整个文件,才能开始执行它,abababa 意味着直到最后才能开始执行 a.js,直到最后第二个才能开始执行 b.css

其它方式呢,如 aaababb,确实可以,但面对一众突发请求,很难有效控制,HTTP/2 确实出现过流优先级系统,但在 HTTP/3 中被彻底删除,当然很大一部分归因于 QUIC 流之间无序。

将多个文件相互交错,还更容易受到丢包影响,而被阻塞。丢包由网络路径中的路由缓冲区暂时溢出导致,一般发生在相邻几个流之间,aXXXbbbaXXXaba(X 表示丢失),当然前者更好,因为 b.css 未受到丢包影响。

结果就是,对浏览器而言,某些情况 HTTP/1.1 会更快,即使存在 HOL blocking 问题(HTTP/2 也仍存在 TCP 层的 HOL blocking),但 HTTP/1.1 将这些请求分摊到 6 个连接,可以很大程度避免它。

与 HTTP/2 的单一连接不同,HTTP/1.1 是真正意义上的并行请求,每个连接都有自己的拥塞控制,对于 HTTP/2 即使是单个数据包丢失,也会导致整体变慢,而 HTTP/1.1 其中一个连接丢包,只会减慢该连接的速度。同时 6 个连接的初始拥塞窗口也会更大 6*14K=84KB,而非单一连接的 14KB。

#learning
👍5
Source map 原理

Source map 本身是一个 JSON,如 {"version":3, "mappings":";;;MADF,cAtBF;mBAAkB", "sources":["~/code/Cat.tsx"], ...}

mappings 是 source map 关键,它记录了源码与转换后代码的映射关系。每个 ; 表示新的一行,因此其后的 MADF 在第 4 行,表示该行的列映射关系,多个使用 , 隔开,它的每个字符基于 Base64 编码,解码后正好是 6 bits。

如对 cAtBF 解码,c:011100 A:000000 t:101101 B:000001 F:000101,解码后的数据以 VLQ(variable-length quantity) 形式表示,每组的最高位是 continuation(C),表示是否连续,最低位是 sign(S),1 为负。

首先 c:011100,C、S 都是 0,表示“非连续正数”,因此可以直接拿中间的位 1110=14。其后 A:000000 按照同样方式,0000=0

之后是 t:101101,C、S 均为 1,表示“连续负数”,“连续”指其后的 B:000001 也是它的一部分,为了更加充分利用空间,后面每组都省去了 S,因此最终是 t:0110(除去 C、S),B:00001(除去 C),连起来 00001 0110=22,补上符号 -22

最后的 F:000101,C=0,S=1,表示“非连续负数”,因此 0010=2,补上符号后 -2。最终 cAtBF 得到 [14,0,-22,-2] 四个数,分别表示 output column、input filename index、input line、input column,所有数字都是相对于当前的偏移量,input filename index 对应于上面 JSON 中的 sources

如果得到 5 个数,则在上面 4 个基础上,再追加一个 name index,对应于 JSON 中的 names(未列出)。如果只有 1 个数,那么仅表示 output column,无其它更多信息。

#learning