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
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
刚刚读文章发现两个有意思的写法(但没用!)
上面两个在 non-strict mode 下都可以运行。想了想第二个可以实现匿名函数递归,不过一般不用 arguments.callee。
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准确说是跑起来了,也没报错,但就是没声,我也懒得调了。
Firefox 不支持在 AudioWorkletNode 中 import ES6 modules,Chrome/Edge 支持。不过 AudioWorklet Wasm 支持在 Chrome/Edge、Firefox 都挺好。
至于 Safari,我的几个 demo 都跑不起来,emm准确说是跑起来了,也没报错,但就是没声,我也懒得调了。
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/
* 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/
Hex-Rays
IDA 8.0 | Hex-Rays Docs
Chrome 104 现支持 HEVC 硬解
刚刚发布的 Chrome 104 支持了 HEVC 硬解,但目前需要手动开启,在启动时添加
该功能由字节跳动开发,并提交给 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
刚刚发布的 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
在 Go 中复用一个 io.Reader
io.Reader 表示一个 stream,而 stream 只能被读一次。因此有两种复用方式:
一、边读边缓冲到 Buffer
二、使用 Pipe,本质是个 ReaderWriter
由于 Pipe 是无 internal buffering 的,因此需要使用两个 goroutine 并行读写。对于多个 Pipe 可以:
#experience
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 之间转移
二、在 clone 时转移
#learning
像 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
HTTP/2 可能没 HTTP/1.1 快
HTTP/2 最大变化是引入单独的成帧层,支持了多路复用,允许交错接收多个资源。如
但这种交错对浏览器来说,不一定是好事,因为浏览器必须完整接收整个文件,才能开始执行它,
其它方式呢,如
将多个文件相互交错,还更容易受到丢包影响,而被阻塞。丢包由网络路径中的路由缓冲区暂时溢出导致,一般发生在相邻几个流之间,
结果就是,对浏览器而言,某些情况 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
HTTP/2 最大变化是引入单独的成帧层,支持了多路复用,允许交错接收多个资源。如
a.js 与 b.css,HTTP/1.1 只能顺序的 aaaabbb 接收,而 HTTP/2 允许 abababa。但这种交错对浏览器来说,不一定是好事,因为浏览器必须完整接收整个文件,才能开始执行它,
abababa 意味着直到最后才能开始执行 a.js,直到最后第二个才能开始执行 b.css。其它方式呢,如
aaababb,确实可以,但面对一众突发请求,很难有效控制,HTTP/2 确实出现过流优先级系统,但在 HTTP/3 中被彻底删除,当然很大一部分归因于 QUIC 流之间无序。将多个文件相互交错,还更容易受到丢包影响,而被阻塞。丢包由网络路径中的路由缓冲区暂时溢出导致,一般发生在相邻几个流之间,
aXXXbbb 和 aXXXaba(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,如
如对
首先
之后是
最后的
如果得到 5 个数,则在上面 4 个基础上,再追加一个 name index,对应于 JSON 中的
#learning
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