2022年汇总-今日阅读-工作相关内容
记录日常读到的和工作相关的文章/链接
长期更新
缘起
虽然看过很多好文章, 但一直没找到整理的地方, 后续再找时也不方便. 最近翻 github 时看到了陶文整理的今日阅读文件, 记录每天看到的优秀文章, 贴下链接, 附一两句简单的评论, 感觉是一个不错的方案
一方面, 阅读经历本身不涉及关键隐私, 分享好文可以创造信息. 另一方面, 也可以作为外人了解我们的途径. 没有明显坏处但成本低有收益的事, 是可以做一做的.
故有此页面
2022 年 11 月 23 日
- git 飞行规则
git使用
- 指导程序员在使用 Git 问题出现后的应对之法
- https://github.com/k88hudson/git-flight-rules/blob/master/README_zh-CN.md
- 飞行规则(Flight Rules) 是记录在手册上的来之不易的一系列知识,记录了某个事情发生的原因,以及怎样一步一步的进行处理。本质上, 它们是特定场景的非常详细的标准处理流程
- 日常工作中也可以启用飞行规则
2022 年 11 月 10 日
- Nginx 团队博客(官方中文版)
Nginx
- 官方出品的 Nginx 指南
- 通过配置 errorPage 在触发限流后返回指定内容
Nginx
- 梅克尔树储备证明
加密证明
- 通过加密数据结构证明交易所未挪用任何用户资金
- 梅克尔树,它是一种数据结构。如图我们有 4 份数据,每份数据为用户的 ID 和余额。将 4 个数据分别哈希就构成了梅克尔树的树叶,再将两个叶子的哈希值合并起来再进行哈希,如此迭代我们将得到一颗完整的梅克尔树。最上面的节点叫做树根。任何一个数据节点有更改,都会导致树根的哈希值发生变化
- 当我们需要证明某一用户确实在树上,如证明 User1 及其余额,我们只需要提供如图中的蓝色节点的值。User1 只需要知道自己的用户 ID 和余额,以及 Hash2 和 Hash34(这两个 hash 由交易所提供),就可以验证自己是否在树根上。显然,只给出这几个节点就足够一路哈希算到树根,只需要验证树根的值是否吻合即可。
- 梅克尔储备金证明实现的形式可有多种,我们先以http://Gate.io 的方案看看。 其实现思路是:
- 公开梅克尔树根。
- 有能力向任何用户证明其余额和 UID 在树上。
- 第三方审计公司来审核树上所有用户的余额加总。
- 第三方审计公司来审核交易所所有钱包地址的余额加总。
- 1 和 2 是一种来自数学和社会的动态威慑:不论是对用户还是对审计公司,他们都无法确定这个梅克尔树根是否能对应 Gate 的所有用户。但由于每个人都可以验证自己是否在树上(显然出于隐私问题普通用户不可能去验证其他用户),一旦有一个人提供了我不在树上的证据,那 Gate 造假无疑。
- 在没人声称 Gate 有诈时,我们都默认树根是正确的,审计公司也可以基于此去审计树里的每个节点并加总出用户的余额。
- 3 和 4 是基于第三方的信任。这里可能会遭到诟病,但对于 CEX 来说,找到免信任的方法几乎不太可能,我们只需要注意这里可能出现的问题即可。
- 潜在的问题有:
- 树根的更新频率问题。CEX 每秒有大量的交易,每一笔交易就去更新树根这个不现实。大概率你看到的树根不会是最新的,也即了解的情况不是最新的。更新频率是保障这套系统有效性的一个关键参数。
- 前端欺诈问题。用户基本是打开交易所的前端页面对自己在不在树上进行验证,这个页面可以返回假的结果,可能需要一些第三方的开源软件解决这个信任问题。
- 第三方审计的信用问题。传统金融中暴雷的很多公司也是经过层层审计的,有审计并不意味着万无一失。
- 吹哨人可用性问题。即使某个用户发现树根有假,他是否能意识到自己应该做什么,是否能有效地证明自己说的是对的,并传播这一事实?
2022 年 11 月 9 日
- Nginx 中文文档
Nginx
- 淘宝团队翻译的
2022 年 11 月 7 日
2022 年 11 月 3 日
- 知乎 v3 版反爬策略解析
反爬虫策略
- jsvmp 是用匡开圆-2018 年提出的前端保护方案. 基本思路是基于 js 实现一个虚拟机, 运行加密代码, 进行签名计算. 利用虚拟机本身难以破解的特点, 配合加密代码内进行环境校验, 保护签名计算逻辑
- 原始论文: 基于 WebAssembly 的 JavaScript 代码虚拟化保护方法研究与实现
- 论文本身对截止至 18 年 js 的混淆/反混淆有很好的总结
- 作者后来入职了深信服, 作为技术骨干出现在了深信服股权授予名单中
- 知乎的签名计算逻辑中用到了随机数, 保证每次计算出的签名不一致
- 事实上 jsvmp 的破解也只有两种策略
- 环境模拟
- 如果没有平台专属代码, 可在拿到加密模块后, 通过 node.js 直接执行 js 代码获取运行结果
- 如果只是简单添加了环境监测, 可以手工补全检测到的环境变量, hack 掉检测过程
- 一般用到 jsvmp 肯定都做了环境监测, 运行的又是字节码, 很难确认具体执行了哪些检测
- 如果确实想知道的话, 可以对常见全局变量配置 Proxy 代理, 通过拦截对属性的访问请求跟踪环境检测过程
- 如果添加了反跟踪机制, 例如通过随机数方法保证每次生成的加密结果都不一样, 可以尝试 mock 掉系统自带的常见随机函数
Math.random = ()=> 0.5
&Date.now = () => 0
移除随机因子- 防御方法为
- 通过
Math.random.toString()
, 看返回结果是否为function random() { [native code] }
检测随机函数是否发生过修改- 风险点: 需要考虑各平台返回值不一样的情况
- 手工编写随机函数. 例如在虚拟机字节码中内置一个长度为 1000 位的随机数表
- 通过
- 防御方法为
- 通过 js-rpc, 在浏览器中实际执行代码获取结果
- 基本思路: 利用 Electron 提供的进程间通信-模式 3:主进程到渲染器进程方法进行破解. Electron 本身是标准 Chrome 运行环境, 因此可以通过新起一个 webview 的方式, 提供 js 运行环境
- 防御方法
- 添加 Electron 环境校验方法, 检测 Electron 中常见的特征: 例如 process 变量, ua 字段, canvas 特征
- 反防御方法
- 移除 Electron 特征, 或直接用 CDP 协议驱动本机 Chrome 提供环境模拟
- 反混淆
- 插桩法, 通过暴力打断点, 跟踪虚拟机字节码执行流程, 推测出实际执行的算法
- 由于每次发起请求都要进行签名, 字节码又通过虚拟机执行, 对性能损耗很大. 因此要求签名算法不能过于复杂, 所以有机会通过人工进行反混淆
- 环境模拟
- 相关博文
- 【JS 逆向系列】某乎 x96 参数 3.0 版本与 jsvmp 进阶 - 漁滒
- 这篇文章的作者对知乎 jsvmp 内执行的代码进行了反解, 逆向出了 python 版的签名计算函数
- 我自己的话考虑用 Electron 起一个 webview, 利用 rpc 通信从 webview 直接运行 js 得了…
- 作者在看雪论坛上也发了一份
- 知乎新版 x96 逆向分析
- 界面交互很好
- moumouhu x-zse-96 加密逆向 V3.0 算法还原
- 【JS 逆向系列】某乎 x96 参数 3.0 版本与 jsvmp 进阶 - 漁滒
- 专利文本:一种基于前端字节码技术的 JavaScript 虚拟化保护方法
2022 年 11 月 2 日
- 如何编写工作日志
工作习惯
- Lucene 查询语法
Grafana面板编写
- 编写 Grafana 面板时会用到, 对应于使用 ES 作为数据源时,在 query 字段中的语法
- 如果变量为文本且携带特殊符号(例如
-
), 可以使用双引号包裹的方式"$变量名"
, 避免筛选参数失效
- Grafana 面板从 ES 中查询变量
Grafana面板编写
- 使用该语法从 ES 数据源中查询变量可选值列表, 提供给用户进行筛选
{"find":"terms", "field":"serviceName.keyword"}
2022 年 11 月 1 日
- Nginx log_format 中可用变量列表
nginx
- Nginx 官方说明: http://nginx.org/en/docs/varindex.html
- stackoverflow 上也有一个列表&变量说明, 按字母序排列, 更方便查找 https://stackoverflow.com/questions/37437153/dictionary-variable-in-log-format-nginx
- Nginx 变量规则
nginx
- 顺风详解 Nginx 系列—Ngx 中的变量
2022 年 10 月 28 日
- 网络延迟
基础知识
- aws 提供了中文版网络延迟的定义/原因/解决方案
- @todo 待整理
2022 年 10 月 19 日
- 状态机编辑器
状态机构建工具
- https://stately.ai/registry/new
- Stately Studio 是一款有限状态机的可视化建模工具。你可以编辑好各种状态,再导出为 XState 的配置项,直接在项目中使用。理论上来说,如果习惯了这种模式,前端写需求的步骤可以优化为:
- 根据需求文档在 Stately Studio 中建模状态(由于是可视化编辑,PM 也能看懂,可以帮着再检查一遍逻辑是否和文档一致)
- 导出为 XState 配置项,直接在项目中使用
- tiny-async-pool
异步任务控制器
- 利用 25 行代码, 实现异步 async 函数控制/任务池, 保证同时执行的最大任务数不超过配置值
2022 年 10 月 8 日
- 慢雾科技-区块链黑暗森林自救手册
安全
- 网络安全攻防方面, 做的最好&黑产最猖獗&安全意识最强的可能都是加密货币圈, 因此可以通过币圈的安全手册学习个人网络安全知识
- 慢雾科技-安全团队知识库
安全
/团队建设
- 慢雾科技是余弦所在的团队, 可以通过围观他们的知识库, 了解报告编写思路/安全领域最新研究进展/区块链安全事件以及复盘总结
2022 年 10 月 3 日
- 前端界有哪些值得一读的中大型轮子?
脚手架编写
- 推荐了 react-dev-utils, 可以围观下
- https://github.com/facebook/create-react-app/tree/main/packages/react-dev-utils
2022 年 9 月 30 日
- 如何更容易上手 Typescript 类型计算
TypeScript类型体操
- 从编程角度理解 TS 类型运算
- @todo 待看待整理
- TypeScript 类型体操姿势合集
TypeScript类型体操
- 给出了习题集, 可以用于检验类型体操学习效果
- @todo 待完成, 目标是完成简单和中等难度的习题
2022 年 9 月 25 日
- 当你 git push 时,极狐 GitLab 上发生了什么?
仓鼠向
- @todo 待细看整理
2022 年 9 月 18 日
- 百度前端技术学园-零基础入门班
前端学习
- 提供了 html/css/js 入门步骤, 知识点也比较新, 至少更新到 2020
- 也提供了练手用的项目
2022 年 9 月 15 日
- 联机游戏原理入门即入土 – 入门篇
游戏服务器历史脉络
- 游戏服务器架构
- 单机
- 单服务器
- 多服务器(不同服间数据不同步)
- 世界服务器(数据存储于同一集群, 数据归一, 从而实现跨服沟通)
- 但是由于不同服务器存储不同地图, 所以切换地图要 loading/切换服务器
- 世界服务器:无缝地图架构(v2)
- 使用 NodeMaster 管理后端服务器, 自动根据人物位置调配对应的后端服务器, 从而实现无缝切换
- 同步策略
- 帧同步
- 只承担了操作转发的操作, 你给我了什么, 我就通知其他人你怎么了, 具体的执行是各个客户端拿到操作后自己执行
- 状态同步
- 状态同步是客户端将操作告诉服务端, 然后服务端拿着操作进行计算, 最后把结果返给各个客户端, 然后客户端根据新数据进行渲染即可
- 状态延时问题
- 网络延时无法避免, 但我们可以通过一些方法让玩家感受不到延时
- 预测/和解
客户端
不再等待服务端
的返回, 先自行计算操作展示给玩家, 等服务端
状态返回后再次渲染- 缺点: 当服务端的
现实
和客户端的预测
不一致时, 会有状态回退发生
- 插值
- 状态是量子化独立的状态, 因此需要在两个独立状态间进行插值使状态平滑
- 思路可以应用在类似滴滴打车的应用中(司机/乘客位置和司机前进路线, 和游戏机制比较类似)
- 帧同步
- 反作弊
- 核心思路: 客户端只根据状态进行渲染, 在服务端进行逻辑运算
2022 年 9 月 13 日
- 探秘 Web 水印技术
前端水印入门
- 水印分为
可见水印
和不可见水印, 分别叙述 - 可见水印
- 静态图片水印
- 关键 css 属性:
background-repeat:repeat;
- 针对页面的水印一般会使用一个层级比较高且覆盖整个页面的元素来承载, 为避免遮挡其他元素, 需要添加一条 css
pointer-events: none;
, 从而使该元素“可穿透”,“看得见、摸不着”,不再影响页面操作
- 关键 css 属性:
- 动态水印
- canvas 或者 svg 根据页面数据动态生成
- 水印安全
- 使用
Shadow DOM
, 将水印内容封装在 dom 元素内, 从而使水印不可修改 - 如果恶意攻击, 则可利用
Mutation Observer
, 监听 dom 变动.- 现代浏览器支持多种监听器, 包括不限于
IntersectionObserver
、PerformanceObserver
、ResizeObserver
、ReportingObserver
、MutationObserver
- 其中,
MutationObserver
可以用来监听 DOM 变动,DOM 的任何变动,比如节点的增减、属性的变动、文本内容的变动,通过该 API 都可以得到通知
- 现代浏览器支持多种监听器, 包括不限于
- 使用
- 不可见水印(盲水印)
- 优势
- 观感+
- 隐蔽性+, 用户基本感知不到水印的存在。
- 抗攻击性+。,其自身往往还具备比较强的抗攻击能力(可以自定义编码方法)
- 信息隐匿技术/隐写术
- LSB 水印
- 灰度可用一个字节,即 8 比特二进制数表示,其中最高位对图像的贡献最大,最低位对图像的贡献最小,称为最低比特位(Least Significant Bit,LSB)。
- 如果将一个图像所有像素的比特位抽出来,就构成了 8 个不同的位平面,从 LSB(最低有效位 0)到 MSB(最高有效位 7)。位平面从低位到高位,图像的特征逐渐变得复杂,细节不断增加,相邻比特的相关性也越强。而比特位越低包含的图像信息就越少,最低位平面类似于随机噪声。因此,改变低位对图像的成像质量影响不大。
- LSB 水印就是利用了这一点,用水印信息替换载体图像的最低比特位,这样原图像的 7 个高位平面就与表示水印信息的最低位平面组成了新的图像。
- ![实质是简单替换(https://mirror-4-web.bookflaneur.cn/https://tva1.sinaimg.cn/large/007Yq4pTgy1h656yg0rd2j30sk07vq4d.jpg)
- 频域水印
- 进阶:将数字图像用一个矩阵来表示,是图像的空间域表示方法,LSB 就是在图像的空间域隐藏信息,鲁棒性较差。而在图像信号的频域(变换域)中隐藏信息要比在空间域中隐藏信息具有更好的鲁棒性
傅里叶变换
可将图像信号从空间域转换到频域- 原理不清楚, 需要高数知识, 待后续学习
- 变换后可以增强对抗能力, 目标是能够对图片的旋转/压缩/裁剪都有足够好的对抗能力
- LSB 水印
- 优势
- 静态图片水印
2022 年 9 月 12 日
- 在命令行里使用 vue 写 ui
vue渲染引擎
- 渲染代码位于这里
2022 年 9 月 8 日
- ts 字符串模版类型
ts类型体操
- ts 4.1 起支持字符串模板类型, 可以通过
a.b.${string}
的方式, 限制变量只能传入a.b.xxx
格式的值 - 坏消息: 21 年 9 月就推出了, 现在才知道
- MySQL 字符串函数
SQL
- MySQL 内置支持一些字符串函数, 方便查询时使用, 例如FIND_IN_SET,
SELECT FIND_IN_SET('b','a,b,c,d');
, 返回值为 2, 意为从逗号分隔的字符串中找到指定单词首次出现的位置, 没有找到则返回 0 - 这里有一份 TiDB 提供的 MySQL 字符串函数功能的中文版翻译
- 缺点
- FIND_IN_SET 是 mysql 内置函数, 使用后意味着项目与 mysql 引擎深度绑定, 会失去迁移数据引擎的机会
- 一般不推荐将计算操作放数据库(数据库计算能力更宝贵)
- 然而
- 我们并不需要考虑迁移数据库问题
- 数据库性能优化是数据量巨大之后的事情, 当总数据量小于 10mb 时, 用
string.include
实现数据库功能都可以很快 - 所以前端正好是使用该功能的地方
- adminer 面板
mysql管理工具
- 基于 docker 写一个数据库管理配置
- ZIP 压缩算法详细分析及解压实例解释
zip
- 网上对于 zip 算法的介绍基本都来自于这篇文章, 全文 3 万字, 一个博士生 14 年写的
- 提到的
重复现象往往具有局部性
这个假设很有启发性 - 重复现象是具有局部性的,它的基本假设是,如果一个字符串要重复,那么也是在附近重复,远的地方就不用找了,因此设置了一个滑动窗口,ZIP 中设置的滑动窗口是 32KB,那么就是往前面 32KB 的数据中去找,这个 32KB 随着编码不断进行而往前滑动。当然,理论上讲,把滑动窗口设置得很大,那样就有更大的概率找到重复的字符串,压缩率不就更高了?初看起来如此,找的范围越大,重复概率越大,不过仔细想想,可能会有问题,一方面,找的范围越大,计算量会增大,不顾一切地增大滑动窗口,甚至不设置滑动窗口,那样的软件可能不可用,你想想,现在这种方式,我们在压缩一个大文件的时候,速度都已经很慢了,如果增大滑动窗口,速度就更慢,从工程实现角度来说,设置滑动窗口是必须的;另一方面,找的范围越大,距离越远,出现的距离很多,也不利于对距离进行进一步压缩吧
- 目前对 zip 是这样理解的
- 先用行程码方式压缩, 按 32kb 的区间进行滑动压缩
- 将一段字符串表示成 literal(原字符)、distance(距离)+length(字符串长度) 这两种形式了
- 对压缩结果进行霍夫曼编码
- 通过行程码压缩后, 文本只剩下了 literal,distance,length 三种类型, 其中 distance,length 必然携带大量重复信息
- 对于 32kb 的区间而言, distance 最大是 32767, 但 distance 必然不是均匀分布在 0~32767 之间, 因此可以先划分为 30 个代码, 分离出不同区间, 如果单个代码表示的区间中有多个值, 则在代码后补加后缀, 进行区分即可
- literal 由于是 ASCII, 所以有 256 种可能, 也是划分区间进行压缩
- length 限定也是只有 256 个值(范围为 3~258), 留 28 个空位(257~285), 将 literal&length 合到一起压缩
- 然后对构建结果在进行一次霍夫曼编码, 得到最终结果
- 先用行程码方式压缩, 按 32kb 的区间进行滑动压缩
- 但不理解的地方在于
- 为什么不直接用霍夫曼编码
- 先通过行程码, 构建出足够多的重复序列
- 为什么不直接用霍夫曼编码
2022 年 9 月 1 日
仓鼠向
- 图解设计模式
2022 年 8 月 29 日
- https 的实现原理
https实现
- 还没细看, 但对 https 加密部分的讲解比 28 号找到的那篇文章细致
- @todo 需要仔细整理
- rfc5246-中英对照翻译
https实现
- 找到了 rfc 的翻译版, 好人一生平安
- TLS1.2 已废弃, 目前是 TLS1.3
- 各种加密算法在移动设备上的执行效率
https效率
- 各种加密算法在移动设备上的执行效率
- 用于对加密速度产生感性概念, 提供数据支持
- HTTP 相关的 RFCs 中英文对照
http协议
- 系统性学习 http
- @todo 需要仔细整理
- 如何阅读 RFC 文档?
学习方法
- 英文原版: How to Read an RFC
- @todo 需要仔细整理
2022 年 8 月 28 日
- 如何构建一个在线绘图工具:Feakin 是如何设计与构建的?
图描述语言
- @todo 需要仔细整理.
- 首先对业内通过代码生成图形的语言做了综述, 然后开始讲解如何设计一个图形生成引擎
2022 年 8 月 24 日
- 彻底搞懂 HTTP 和 HTTPS 协议
http协议详解
- http
- 需要解决的问题
- 设计目标: 无状态, 基于请求与响应, 提供一种发布和接收 HTML 页面的方法
- 应用层协议 => 无需关心 TCP 底层实现
- 历史
- 0.9/1991 年, 不涉及数据包传输,规定客户端和服务器之间通信格式,只能 GET 请求
- 只接受 GET 一种请求方法,且不支持请求头。
- 协议规定,服务器只能回应 HTML 格式的字符串,不能回应别的格式。
- 由于该版本不支持 POST 方法,所以客户端无法向服务器传递太多信息。
- 示例
-
客户端请求格式 GET /index.html 服务器响应格式 <html> <body>Hello World</body> </html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22- 1.0/1996 年, 传输内容格式不限制,增加 POST、 PUT、PATCH、HEAD、 OPTIONS、DELETE 命令
- 首先, 任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础
- 其次, 除了 GET 命令,还引入了 POST 命令和 HEAD 命令,丰富了浏览器与服务器的互动手段。
- 再次, HTTP 请求和回应的格式也变了。除了数据部分,每次通信都必须包括头信息(HTTP header),用来描述一些元数据
- 其他的新增功能还包括状态码(status code)、多字符集支持、多部分发送(multi-part type)、权限(authorization)、缓存(cache)、内容编码(content encoding)等
- 回应的格式是”头信息 + 一个空行(\r\n) + 数据”。其中,第一行是”协议版本 + 状态码(status code) + 状态描述”。
- 示例
- ```txt
客户端请求格式
GET /index.html HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
服务器响应格式
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
-
- 字段解析
- Content-Type 字段
- 关于字符的编码,1.0 版规定,头信息必须是 ASCII 码,后面的数据可以是任何格式。因此,服务器回应的时候,必须告诉客户端,数据是什么格式,这就是 Content-Type 字段的作用。
- 常见 Content-Type 字段值, 这些数据类型总称为 MIME type,每个值包括一级类型和二级类型,之间用斜杠分隔。
-
text/plain text/html text/css image/jpeg image/png image/svg+xml audio/mp4 video/mp4 application/javascript application/pdf application/zip application/atom+xml
1
2
3
4
5
6
7
8- 客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式。
- `Accept: */*` , 示例中, 客户端声明自己可以接受任何格式的数据。
- Content-Encoding 字段
- 由于发送的数据可以是任何格式,因此可以把数据压缩后再发送。Content-Encoding 字段说明数据的压缩方法
- ```txt
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate - 客户端在请求时,用 Accept-Encoding 字段说明自己可以接受哪些压缩方法。
- Accept-Encoding: gzip, deflate
- 注:
- DEFLATE 是同时使用了 LZ77 算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法, 被 RFC 1951 标准化
- LZ77 算法其实是 Lempel 与 Ziv 在 1977 年发表的论文中提到的算法, 所以叫 LZ77, 实际上后边还有 LZ78, 和 LZW, LZW 是因为美国学者泰瑞·卫曲(Welch)也加进来了
- 实质是基于字典的压缩法, 先通过分析构建出构建字典, 然后再将文本中匹配到的字段进行替换
- 构建方法: hash 表, 滑动窗口, 惰性匹配, via Gzip 格式和 DEFLATE 压缩算法
- 转换后输出的格式为: (distance,length)或 literal, 只会是一个
- Huffman 编码是将出现次数多的编码尽可能的短来进行压缩,而 LZ77 则是另外一种思路:替换重复的内容。
- 对于具有均匀概率分布的一组符号,以及作为 2 的幂之成员,霍夫曼编码等同于简单的二进位制编码,例如 ASCII 编码。这反映了如此的事实:无论压缩方法是什么,这种输入都不可能进行压缩,或只是说对数据无所作为,比起压缩才是最佳选择。
- 在任何情况下,霍夫曼编码在所有方法中是最佳的方式,其中每个输入符号是具有二元概率的已知独立且相同分布的随机变量。前缀码,特别是霍夫曼编码,往往在小字母表上产生较差的效率,其中概率通常落在这些最佳(二元)点之间。当最可能符号的概率远超过 0.5 时,可能发生霍夫曼编码的最坏情况,使低效率的上限无限制。
- 在使用霍夫曼编码的同时,有两种相关的方法可以解决这种特定的低效问题。将固定数量的符号组合在一起(阻塞)通常会增加(并且永不减少)压缩。随着块的大小接近无穷大,霍夫曼编码理论上接近熵限制,即最佳压缩。然而,阻塞任意大的符号组是不切实际的,因为霍夫曼代码的复杂性在要编码的可能性的数量上是线性的,这是在块的大小中呈指数的数字。这限制了在实践中完成的阻塞量。
- 广泛使用的实际替代方案是行程编码。该技术在熵编码之前增加一步,特别是对重复符号进行执行次数的计数,然后对其进行编码。对于伯努力(Bernoulli)过程的简单情况,哥伦(Golomb)编码在编码游程长度的前缀码中是最佳的,这是通过霍夫曼编码技术证明的事实。使用改进的霍夫曼编码的传真机采用类似的方法。但是,游程编码并不像其他压缩技术那样适应许多输入类型。
- via 维基百科:霍夫曼编码-优化
- 在一个文件中,如果有内容是相同的话,就可以在后一块内容中做一个标记,标示和前一块的距离和相同的长度(distance,length)。(distance,length)绝大多数情况下小于重复的内容,因此文件的体积就变小了。
- zip 算法
- ZIP 中,首先使用 LZ77 编码进行压缩,然后之后再对 LZ77 编码之后的结果继续进行压缩(Huffman 编码),这个算法也叫做 Deflate 算法。
- 其实这个算法也支持静态的 Huffman 编码,无需记录码表,但是压缩率不高,所以大多数都采用动态的 Huffman 编码。
- 采用动态的 Huffman 编码其流程如下:
- 参考资料: 从 Huffman 编码谈文件压缩
- DEFLATE 是同时使用了 LZ77 算法与哈夫曼编码(Huffman Coding)的一个无损数据压缩算法, 被 RFC 1951 标准化
-
- Content-Type 字段
- 0.9/1991 年, 不涉及数据包传输,规定客户端和服务器之间通信格式,只能 GET 请求
- 需要解决的问题
2022 年 8 月 23 日
- Nginx 知识图谱
仓鼠向
- 作者提供了很多知识图谱, 参见首页: https://github.com/tsejx
- JavaScript Guidebook:JavaScript 知识图谱 - ECMAScript | DOM | BOM | HTML5 | 计算机网络 | 设计模式
- React Guidebook::React 知识图谱- 基本概念 | 进阶用法 | 框架生态 | 前沿技术 | 源码核心
- Webpack Guidebook::Webpack 知识图谱 - 模块化 | 基础概念 | 工作原理 | 实战应用
- DevOps Guidebook::DevOps 知识图谱 - Linux | Nginx | 数据库 | 部署 | DevOps
- Vue Guidebook:Vue 知识图谱 - 基本概念 | 响应式原理 | 编译原理 | 框架生态
- CSS Guidebook:CSS 知识图谱 - 特性 | 属性 | 布局 | 响应式 | 动画
- Node Guidebook:Node.js 知识图谱 - 模块 | 异步编程 | 进程 | I/O | 服务端应用
- TypeScript Guidebook:TypeScript 知识图谱 - 静态类型检查 | 语法基础 | 配置使用 | 编译原理
- Cross Platform Guidebook:跨平台开发知识图谱 - HybridApp、ReactNative、小程序、Flutter、Electron
- Data Structure and Algorithms Guidebook:数据结构与算法知识图谱 - 数据结构 | 算法 | 编程实现
- Visualizaition Guidebook:前端图像学知识图谱 - Canvas | SVG | WebGL
- Angular Guidebook
- Database Guidebook:MySQL、MongoDB
2022 年 8 月 22 日
- 多个 Nginx 节点, 对同一静态资源文件返回的 etag 不一样
冷知识
- 答案是 Ng 在计算 Etag 时,使用了响应头的 Last-Modified 与 Content-Length 表示为十六进制组合而成。中间因为用了最后修改时间作为参数, 而两个文件最后修改时间不一样, 导致 Etag 值也不一样
- Nginx 源码
- 相关博文:解决 Nginx 多节点上相同静态文件的 etag 不同的问题
- 相关博文: 为什么大厂很少用 etag?
- 解决方法是利用 touch 手工同步两个文件的修改时间.
- 但另一点, 我记得从网上下载文件的话, 可以注意到原文件的创建/修改时间都是可以保留下来的. 线上没有保留下来, 可能是写文件时是直接写的二进制数据流, 导致创建/修改时间被刷新了, 从而引发不同节点之间文件不一致.
- 美团网的秋招总结
面试经验
2022 年 8 月 19 日
- 常见空格一览
冷知识
- 普通空格(U+0020)
- 不间断空格(U+00A0, )No-Break SPace.
- 当 HTML 有多个连续的普通空格时,浏览器在渲染时只会渲染一个空格,而使用这个不间断空格,可以禁止浏览器合并空格。常用于富文本编辑器之中.
- 零宽空格(U+0200B,)
- 零宽空格广泛使用于第三方的富文本编辑器里面,常用于格式隔断,例如当你在一个富文本编辑器里面选中一段文字加粗后,如果啥也不干,接着在这选中的文字后面键入的文字便会自动加粗,为了把格式隔断,可以在加粗后的文字后面手动插入一个零宽空格,这样用户在接着往后输时便不会自动延续格式了。
- HTML 的
标签的作用也相当于一个零宽空格,可用于隔断英文单词进行换行 - 这个标签和上面使用 HTML 实体的区别在于,这个标签是无法被拷到纯文本里面的,而 HTML 实例或者使用 JS 字符串的方式是可以的,因为它本身就是纯文本的一部分(Unicode),标签则不是。
- 全宽空格(U+3000, )
- 普通的 U+0020 是半角空格,与此相对还有一个全角空格,也叫全宽空格,即一个 em 大小,在 fontforge 里面可以看到当前字体的 em 大小:
- 半宽空格(U+2002, )
- 全宽用 em 表示,半宽则用 en 表示,为 em 的一半。半宽空格可用于一些对齐的目的,如三个汉字和四个汉字的两边对齐
- 除了半宽,还有三分之一宽(U+2004)、四分之一宽(U+2005)和六分之一宽(U+2006)
- 发宽空格(U+200A, )
- 零宽空格的前一个便为发宽空格(hair space),网上关于这个空格的介绍几乎没有,只是说它是一个最窄宽度的空格(像头发一样窄,所以叫发宽)。这个也是开篇提到的空格类型,是从 Mac 的文件夹里的文件信息窗口里拷的:
- 除了以上提到的空格外,还有专门用于数学的空格、在德语和法语里用来隔开连词的空格,等等,更多类型空格可见维基百科: 空格
- https 连接的前几毫秒发生了什么
科普
- 对 https 加密过程有比较细致的讲解, 但暂时看不太懂, 等下了班细看
- 从 Chrome 源码看 HTTPS
科普
- 除了对 RSA 加密的解释, 还提供了对 ECC 椭圆曲线加密的解释, 且配了图
- 统计代码行数
冷知识
- npx cloc .
- 需要用自己的项目做统计
- VScode Counter 插件也可以
2022 年 8 月 16 日
- node 限制正则表达式回溯深度
编译器
- V8 支持非回溯 RegExp 引擎
- 在回溯模式下, 正则表达式会有很多分支情况,一个简单的正则都会形成几乎无限的分支情况, 导致系统崩溃
- 例如
\s*$
, 曾经在 2019 年让 Cloudflare 全球服务挂了半小时- 回溯引发 CPU 无限运算的原因可以在文章中搜索
附录:关于正则表达式回溯
看到 - 唯一真正的解决方案(除非完全重写模式以使其更具体)是使用这种回溯机制摆脱正则表达式引擎
- 自 1968 年 Ken Thompson 写了一篇名为“编程技术:正则表达式搜索算法”(Programming Techniques:Regular expression search algorithm) 的论文以来,这一问题的解决方案早就广为人知。这篇论文介绍了一种机制,它可以将正则表达式转换为非确定性有限状态自动机 (NFA),然后使用一种按匹配字符串大小的时间线性执行的算法,跟踪 NFA 中的状态转换。
- 回溯引发 CPU 无限运算的原因可以在文章中搜索
- 例如
- 你可以通过下面的方式配置新的 RegExp 引擎:
--enable-experimental-regexp_engine-on-excessive-backtracks
:在过多的回溯上启用对非回溯引擎的回退。--regexp-backtracks-before-fallback N
:(默认 N=50000)指定了多少回溯被视为过多,即何时进行回退。--enable-experimental-regexp-engine
直接启用非回溯 RegExp 引擎。- 在 v8 引擎 v8.8 版本/chrome 88 版本/Node.js 16.0.0 之后有效(nodejs&v8 对应关系)
- v8 团队对此的介绍
- 测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 测试代码
let startAt = Date.now();
console.log("start => ", startAt);
let c = /(a*)*b/.exec("a".repeat(100));
let endAt = Date.now();
console.log("end => ", endAt);
console.log("during => ", endAt - startAt);
// 对于node index.js而言, 会无限执行下去
// 实际输出=>
// start => 1660631614480
// ------------------------
// 对 node --enable-experimental-regexp_engine-on-excessive-backtracks --regexp-backtracks-before-fallback=1000 dist/index.js 而言, 只需要6ms
// 实际输出 =>
// start => 1660631608399
// end => 1660631608405
// during => 6
- 深入理解 Promise 五部曲
科普
- 基本思路和你不知道的 JavaScript 中一致, 可以视为简版, 分为如下 5 篇
- 查了一下, 文章作者是 Getify, 最后提的 Promise 解决方案叫 asynquence
- 这个人后来搞了个 Github 15.8w star 的仓库存文章, 仓库名叫You-Dont-Know-JS
2022 年 8 月 12 日
- 身份证号的末位校验码算法最后一步模 11 是基于什么考虑?
密码学
&实际应用
- 利用 1~11 的最后一位做校验位(对应于 0~9+X), 可以直接检验出以下错误
- 有一个数填错了。
- 相邻两位填反了。
- 如果有 2 个以上的位填写错误,而填写错误不是刻意而为之,而是随机填错了的话,则身份证校验算法能够检测出错误的概率为 90%
- 关联回答: 身份证号包含「X」而不是纯数字,是不是一个失败设计?
- 评价是否失败需要看该设计是否满足了当时的设计需求.
- 第二代身份证 2003 年开始实施使用,其设计应该还要更早几年,那个年代个人电脑还远未普及,更遑论网络和智能手机。大部分需要填写身份证号的业务都是纸笔填写,人工收集后整理存放或者统一录入系统
- 这一算法可以检测出身份证号中所有有一个数填错了 和 相邻两位填反了 的常见错误情形,对于两位以上的随机填写错误也有 90% 的检出概率,使用任何小于 11 的除数都会削弱其有效性。上述结论的推导可以参考上边的链接
- 这种校验算法的应用非常简便,很容易开发出一种自带身份证号校验功能的计算器,方便基层业务员快速判断身份证号是否填写有误,从而避免使用第一代身份证时大量出现的身份证号错号问题
- 但可惜的是,第二代身份证推出后,又经过了数年的换发工作才逐步取代一代证,此时个人电脑已经开始普及,读卡器淘汰掉了许多纸笔填写身份证号的场景;在一代身份证彻底退出历史舞台的 2013 年,移动互联网时代已然拉开帷幕,联网身份信息查询乃至人脸识别技术让校验码毫无用武之地,多出的一个字母 X 反而给各种信息化系统的设计与使用带来了麻烦。
- 总而言之,身份证号的设计不能算是失败,其编码规则实际上可以说相当巧妙,结合了数论、统计方面的知识和对我国国情及基层工作模式的理解。只不过它的设计者没能预料到未来十年内我国信息产业的爆发式增长,各种良莠不齐的软件雨后春笋般占领了民众的日常生活,而这些软件的开发者并不都能编写“正确”处理身份证号的逻辑。这不能完全算是设计者的过失,毕竟即使是行业内的大佬,也很少有人能预言十年二十年后的世界会是怎样。
2022 年 8 月 11 日
- 前端代码体积的日常
欢乐向
- 前端工程师的深度或者核心竞争力体现在哪里?-欲三更的回答
前端的难点
- 需要保持自己拥有硬编码的能力, 是无论什么需求都能不头疼不发愁,敢拍胸脯说“我给你做”的竞争力
- 前端开发跟后端开发有一个非常不同的点,就是前端开发应用层的代码逻辑很容易就变得极其复杂,而后端的复杂逻辑主要集中在和业务正交的领域
- 示例 1: 流程图编辑器
-
基本共识:
你懂 react,懂 vue,懂 redux,或者你做过多少个几百页面的“大项目”,对你实现上面这个东西有多大帮助?
坦白讲,没有多大帮助。 - 想实现这么个东西,应该怎么做呢?
- 正常的思路是这样——首先按照业务逻辑,设计一个 model 描述整个图,这个 model 一般是树形结构,每一层包含若干节点,每个节点上包含若干连接点,另外还需要一个结构描述连线。
- 大致是:graph - node - pin - connection 这样的层次关系。
- 另外还有很多细节,比如四个泳道如何描述,不同的节点类型如何抽象;不同颜色的连线表示不同关系;以及如何处理注释框,如何处理联动,如何序列化/反序列化……一时半会儿说不全。如果加上界面逻辑,就更复杂了,位置,样式,拖动,事件,刷新,局部刷新(也许需要),context menu,undo,redo,等等。
- 面对这样的需求,谈什么“前端数据流”,好像没多大意义。为什么?因为前端数据流是开发范式,实际上并不会帮你建立业务模型,不管依赖什么工具,模型总要你自己建立。那么如何建立模型,又如何使用代码合理的实现模型?没有什么黑科技,就是一点一点的写,抽丝剥茧,功力足够,你就能写出简洁有序抽象可复用的实现,功力不够,写个一千行就乱套了。
- 示例 2: 复杂框图加实时数据展示加鼠标操作,简称组态
- 示例 3 : 网页渲染 BIM
- 示例 4: 复杂联动表单
- 你在一个平台上能写出那种打眼一看一时反应不过来该怎么写的程序,那你在任何平台上都有能力做到这一点,别让自己做的项目只有填充简历的功能,还要让它们给你背书。
- 前端开发的难点到底在什么地方?-欲三更的回答
前端的难点
- 视频监控行业的客户端软件, 和微软 Office 比没什么难点, 但可以就此往下细问
- 监控点位一多,对性能就有点要求。比如左边那个树形列表,item 超过十万的时候,如何保证不卡顿?如何在客户端做拼音检索保证性能?如何支持多音字?
- 硬件对接。当你要对接超过 200 种监控设备,如何设计对接层?不同厂家的 sdk 底层依赖的都是海思的库,版本却不一致,怎么处理?某些厂家的 sdk 质量不受控如何处理?以及行业主流的平台和设备接入规范是什么样的?
- 应用层协议栈。rtp,rtsp,sip,onvif,等等,都是什么?干什么用的?ps 流和 ts 流分别是什么?以及简单的视频编解码知识,霍夫曼编码和矢量预测简单聊聊?
- 播放性能优化。16 路 1080p 或者 4 路 4k 预览导致掉帧,如何优化?sdl,opengl,directx 各自有什么优化技巧?
- socket client 编写技术。断线重连怎么做?沾包是怎么回事儿?如何设计一个基于线程池和异步 io 的 socket client?
- 交互逻辑实现。比如我把左边的监控点位拖进右边的视频窗口,这时候客户端会尝试连接,发请求获取数据并播放,这个过程肯定不能卡顿,要异步处理。以及,在这个过程中我又拖了另一个点位进去,如何 quit 掉前一个前一个任务,开启新的任务?任务队列了解一下?
- 你看,一个这么 low 的东西,随便列列还有不少技术点可以聊呢。恐怕有一半的后端项目没这个复杂吧?这东西我做过三套,在 windows 上用 c++做过一套,在 linux 上用 qt 做过一套,用 libcef 和前端技术栈做过一套。三个功能几乎一模一样的项目,难度自然也是差不多的。你用 libcef 做也不会简单,只是开发效率高一点。
- 可想而知,你要是想在网页上做个功能更复杂的应用(比如 @于江水 说的那套东西),那难度肯定比这个大的多。所以问题不在于前端不前端,而在于如果你只做 listview,那肯定前端简单。
- 前端开发的难点到底在什么地方?-于江水在银河系的回答
前端的难点
- 前端逻辑复杂度主要在于数据 + UI + 交互的实现
- 垂直领域解决方案很难
- 切页面很简单, 但几十万个页面, 就不是前端/堆外包所能直接解决的了.
- 所以我们有 TMS 等各种运营系统,前端切模块,运营自己设置图片、文案、组装成运营页面,想改自己在后台改不用麻烦前端。这一套系统是个比较庞大的工程,从模块规范、模块开发工具链、模块发布和版本管理、在线管理、在线可视化搭建、数据填写和数据源导入、页面生成和 CDN 同步等等,都需要前端架构师设计然后开发。设计这个系统是很难的。
- 不同业务场景、特点,需要完全不同的前端解决方案,在开发这些垂直解决方案的时候,业务分析、技术选型、架构设计、开发落地是非常难的。
- 总结
- 前端本身业务逻辑、实现方式比较多样、复杂,技术选型、方案设计很难,这要求你对多种技术框架、工具都有一定的了解
- 面对不同业务需求进行抽象、设计、研发以及关联系统的自主研发(跨技术栈)比较难
- 将业务需求、交互设计、数据等糅合在一起开发出来展现给用户,跟多方沟通打交道比较难,良好的沟通需要多种领域的知识
2022 年 8 月 2 日
- vscode 中的数据库客户端
- MySQL
- 皮皮仔-vscode 中的数据库浏览插件
- Github 源码
- 作者是个人开发者, 可以轻量使用以处理不重要的数据. 重要数据库还是要用官方工具. 对于个人开发者的产品要小心意外风险
- 但确实非常轻(vscode 插件, 可以随时查看), 也足够使用
- MongoDB
- MongoDB for VS Code
- MongoDB 官方出品
- MySQL
- catchen 谈大厂中重要的事
工作认知
- 原文: 我对大厂 senior+ 的程序员的期望是:你能够说清楚我们在解决什么用户问题、我们如何通过解决用户问题创造价值、我们如何把价值转化为利润。说不清楚这三件事情,技术品味没有意义,按照技术品味进行的取舍有可能不符合产品和业务应该进行的取舍,最后不能有效解决用户问题、不能盈利。对于熟练的大厂 senior+ 来说,其实哪有那么多东西需要在 code 里面 review 的。除去 CI 直接能定位的问题,我只关心几件事:你是否在解决正确的问题?你是否意识到问题所有的约束?约束冲突时你对它们的优先级排序是否跟业务利益一致?这三件事能说清楚的,没有写不好 code 的,写不好就转 PM 吧。
- 我们是如何记录图片的
图片格式科普
- PBM(Portable BitMap)
- 最早的图片格式, 纯文本, 只支持黑白两色, 通过 01 进行记录
- 缺点是明文存储, 一个像素一个字节(0/1), 体积浪费很大
- GIF(Graphics Interchange Format), 图像交换格式
- 将支持的图片颜色限制为 256 种, 256 种颜色可以从整个 RGB 颜色空间中任选,它们构成一个调色板。GIF 的每个像素便是这个调色板(即颜色表)的索引
- 具体每个像素的颜色可以从调色板中选, 但只有 256 种颜色可用
- 记录每一个像素的颜色, 然后使用 LZW 算法压缩, 以节约体积
- 缺点: 专利收费(现已过期)
- PNG(Portable Network Graphics), 便携式网络图片, 又称 PNG is Not GIF
- 前向兼容
- 标准制定式规定数据分为
关键数据块
和辅助数据块
两类 - PNG 解析器必须支持关键数据块的解析,而对于辅助数据块则是能识别就识别,不能识别可以忽略
- 升级只针对辅助数据块
- 因此, PNG 可以实现渐进增强和前向兼容
- 标准制定式规定数据分为
- 算法和 GIF 类似, 使用颜色表存储颜色
- PNG 8 => 颜色表体积为 2^8 => 256 种颜色, 和 GIF 一样
- PNG 24 => 颜色表体积为 2^24 => 256® _ 256(G) _ 256(B) => 16777216 种颜色, 俗称真彩色
- PNG 32 => PNG 24 + 8bits 透明色通道, 加了一种 A(alpha, 透明色), 效果更佳, 体积更大
- 缺点
- 霍夫曼编码 & LZW 算法特点 => 重复数据越高,压缩效率就越高
- 但是, 如果图片复杂程度增加, 颜色本身就非常复杂且无规律 => 压缩效率大幅降低
- 考虑到 PNG24 已经可以表示所有颜色, 可以将 PNG 视为图像无损压缩技术
- 前向兼容
- JPEG(Joint Photographic Experts Group), 联合图像专家组
- 实用主义策略: 面向人眼识别的有损压缩
- 不使用 RGB 空间, 改为使用 YUV(Y => 亮度, Luma/Luminance, UV => 彩度/色调/饱和度, Chrominance 或 Chroma), 和 HSL(色相、饱和度、亮度/Hue, Saturation, Lightness)很接近
- HSL 更接近于人眼对色彩的感受方式,因此更适合做渐变处理, 不会出现 RGB 颜色中, 某种成分简单变化, 导致视觉颜色出现大幅度变化的问题(每种成分对亮度贡献不同, 导致发生突变)
- 人眼特点:
- 人眼对于亮度的感受要高于色调和饱和度
- 人眼对于在一定范围内的亮度差异较为敏感
- 亮度为 10% & 20% 与 20% & 25% 可以区分
- 亮度为 10% & 90% 与 20% & 80% 难以区分(哪个亮度差距更大)
- 通过矩阵变换的技巧, 可以舍弃频域上的一些细节,这个过程被称为「量化」。这是 JPEG 有损压缩的最主要来源
- 对于通常看到的图片, JPEG 都能在合理地保证质量的前提下大幅压缩图像的尺寸,这尤其体现在一些「绘画作品」中,因为这些作品通常都有相对均匀的亮度。
- 戴珍珠耳环的少女, 参考观摩: 小约翰可汗-骗一下纳粹二把手是怎样的体验?【硬核狠人 35】
- 由于
范米格伦
的伪作对维米尔
作品鉴定师惨无人道的迫害, 导致这幅真迹也被判定为了伪作, 性质极为恶劣
- 不使用 RGB 空间, 改为使用 YUV(Y => 亮度, Luma/Luminance, UV => 彩度/色调/饱和度, Chrominance 或 Chroma), 和 HSL(色相、饱和度、亮度/Hue, Saturation, Lightness)很接近
- 实用主义策略: 面向人眼识别的有损压缩
- WebP
- 金声玉振
- 压缩数据的原理: 数据「本身存在冗余信息」
- 数据压缩的极限: 信息熵, 信息本身存在最小体积, 不能在 1bit 中传递 2bit 的信息
- 从二进制编码->压缩算法->针对人眼模型部分舍弃, 还能更好一点吗…
- 来自 mp4 的启发 => 将图片信息中更多的部分「变成冗余」
- MP4/H.264 的特点
- 只记录帧与帧之间的变化, 将视频大幅压缩 => 「运动补偿」
- 「根据某个单元相邻的单元预测该单元的值,从而使视频文件只需要记录实际值和预测值的差值就足够了」 =>「帧内预测」
- WebP
- WebP 使用每个块上方的三个块和左侧的三个块进行预测,并且包含了 H.264 的四种帧内预测模式
- 通过帧内预测实现了更多原始信息的冗余化
- 同样使用了 PNG 中使用了的字典编码等等无损压缩技术,从而使图片的尺寸降到了尽可能低的程度
- 金声玉振
- 展望
- BPG
- Web 就是旅行的终点了吗? 并不
- 2013 年出现了 H.265 编码, 「High Efficiency Video Coding」,高效视频编码, HEVC 在 H.264 之上做了诸多改进,例如帧内预测就从 4 种模式上升到了 33 种!
- BPG 使用了基于 HEVC 帧内预测算法的有损压缩,这意味着它的性能要显著领先于 JPEG 甚至 WebP。然而,由于 HEVC 与 H.264 一样保留版权,这也成为了 BPG 并没有大规模流行的主要原因。
- FLIF
- 2015 年发布, 完全开源
- 采用和 H.264 类似的一种动态学习的压缩算法, 在无损压缩方面将压缩性能优化到了新高度
- 作为纯社区项目,FLIF 在发布后不久就逐渐式微,但其核心思路被 JPEG 的新标准 JPEG XL 继承,并且 JPEG XL 最终也在 2020 年作为免版税标准发布;BPG 和 FLIF 也最终启发了 MPEG,发布了基于 HEVC 的图片格式 HEIF
- 2021 年起 Google 开始开发下一代 WebP,被称为 WebP 2, 基于 AV1 视频编码
- AV1 是用以代替 H.265 的最新免版税标准
- 时代还在进步中
- 进阶: 为什么故事的主角都是外国的企业
- 有效需求召唤实际供给, 销售市场决定产品命运
- 放眼寰宇, 谁在视频推荐算法方面有实际需求
- 回看自身, 谁在为 CDN 费用天天夜不能寐
- 基于 AVS2 的图片容器——TPG:现状与改进之路
- OceanBase-海量记录,笔笔算数
- 此处省略爱国主义教育 3000 字…
- 进阶: 为什么故事的主角都是外国的企业
- BPG
- PBM(Portable BitMap)
2022 年 8 月 1 日
- WSL 导入系统后, 更改默认进入的 uid
神奇技巧
- 目前 WSL 官方没有提供直接配置入口, 想在输入 wsl 后直接以某身份进入(而非默认的 root), 需要修改注册表实现
wsl -d <DistroName> -u <UserName> -e id -u
可以拿到 导入 wsl 的系统中目标账户的 uid, 为十进制值(一般为 1000)- 进入注册表, 修改
Registry::HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss\{系统uuid}
下,DefaultUid
项对应的值即可
2022 年 7 月 29 日
- sharp 作者提供的提问前待确认 todo
工作模板
- sharp 需要在安装时进行 c++构建, 因此经常会有各种神奇问题出现, 作者也是不胜其扰(使用 sharp 的开发者表示开发者看着报错也是非常痛苦), 因此提供了这套 issue 前提问.
- 可以作为客服类项目的开发 demo
- 体验度量专题|易用度在企业级中后台产品的探索和实践
产品设计
- 出处: 阿里antd 主页-资源-文章-2020-设计部分
- 思路: 通过
易用度
考核技术类产品的效果 - 易用度:使用产品完成工作的容易程度。
- 易用度-满意度-尖叫度-推荐度衡量维度对比
- 谷歌出品: 前端性能监控指标介绍
仓鼠向
- 对常见前端页面性能指标的介绍. 做性能又花钱可以用一下
- Time to First Byte (TTFB)
- First Contentful Paint 首次内容绘制 (FCP)
- Largest Contentful Paint 最大内容绘制 (LCP)
- First Input Delay 首次输入延迟 (FID)
- Time to Interactive 可交互时间 (TTI)
- Total Blocking Time 总阻塞时间 (TBT)
- Cumulative Layout Shift 累积布局偏移 (CLS)
- Interaction to Next Paint (INP)
2022 年 7 月 28 日
- 消息搜索技术调研
端内消息搜索
- 基本思路为: 如何在本地消息数据库中, 尽快找到和关键词匹配的前 n 条消息
- 那么, 数据库方案有 sqlite(FTS, Full Text Search, v3/v4/v5)/CLucene(和 ES 是一个底层)/Lucy 多种方案可选
- 此外, 还需要执行
- 分词器优化
- 引擎层优化
- 对应: Telegram 搜索似乎是在服务端进行
- 参考资料
- js 事件循环机制示例图
仓鼠向
- 调度算法评价指标
仓鼠向
- 调度算法评价指标本身是操作系统里的基础知识, 业内也有非常完善的研究. 但调度系统模型可以和很多实际业务匹配起来, 例如: 当任务量过大时, im-sdk 如何执行任务舍弃逻辑, 以追求更好的体验
- 进一步, 如何定义更好的体验, 在这时, 调度算法指标里的周转时间, 或者 P90 周转时间显然就是很好的指标
2022 年 7 月 22 日
-
-
神奇bug
-
TreeShaking 需要注意意外优化的情况
-
对于以下代码
1
2
3const obj = {};
obj.name = "obj";
export const answer = 42; -
rollup 编译结果
const answer = 42;export {answer};
-
esbuild 编译结果
const obj = {};obj.name = "obj";const answer = 42;export {answer};
-
看起来 rollup 正确的清除了冗余代码, 实际上在特殊情况下, rollup 的优化会导致出错
1
2
3
4
5
6
7
8
9
10// 本来代码的意思是每次设置一个变量属性的时候,都要触发一次render,结果由于obj.name代码被删除,导致render没被触发,这明显改变了语义。
function render(val) {
console.log("render", val);
}
Object.defineProperty(Object.prototype, "name", {
set(val) {
render(val);
},
});
-
-
2022 年 7 月 20 日
- effective-debugging-gitbook
仓鼠向
- 可以学习一下别人的调试方法, 待读
2022 年 7 月 17 日
- 为什么平均值很烂,百分位数很棒
统计学
监控
- 为什么 TP 指标优于平均数.
- TP 可以表示系统整体的响应情况, 也不会受到尖峰值干扰
- tp90 和 tp99 是指什么性能指标,求大神解释下?-刘江的回答
统计学
监控
- TP=Top Percentile,Top 百分数,是一个统计学里的术语,与平均数、中位数都是一类。
- TP50、TP90 和 TP99 等指标常用于系统性能监控场景,指高于 50%、90%、99%等百分线的情况。
2022 年 7 月 16 日
- 总结了 14 种数据异常值检验的方法
统计学
- 14 中检测异常值的方法, 如果将来写监控系统, 制定错误指标监控依据时可以使用
- 大概看了下, 基本看不懂, 有空可以专门看看统计学教科书
- 学习本身也是一种享受/娱乐
- 基于分布
- 3sigma
- z-score
- boxplot
- Grubbs 假设检验
- 基于距离
- KNN
- 基于密度
- LOF
- COF
- SOS
- 基于聚类
- DBCAN
- 基于树
- iForest
- 基于降维
- PCA
- AutoEncoder
- 基于分类
- One-Class SVM
- 基于预测
- Moving Agerage(移动平均)
- ARIMA
- 基于分布
2022 年 7 月 15 日
- 函数式组件与类组件有何不同?
优秀博文&争议问题终结者
- 面试时被问到了这个问题, 正好看到了这篇博文. 博文本身只是简单说, 函数组件相较于类组件, 最大的优势是默认避免了
this
指向不确定的问题, 并举了相关例子. 这个回答一般, 但有一点是面试官所不能反驳的: 文章作者是Dan Abramov
, redux 作者, 另一个身份是React Conf 2018
上 hooks 功能的介绍人(没猜错的话应该也是实际开发者) 欢迎反驳, 若意见不一, 以我为准
- 另一个发现是作者的博客欢迎大家为博文提供各语言的翻译版本. 我用谷歌翻译试翻译了下, 感觉没什么问题, 后续可以集中提 PR
2022 年 7 月 12 日
- 带你入门前端工程
仓鼠
- 对前端工程的概要性介绍, 仅作收藏, 并没有实际查看
- 深入理解 TypeScript
仓鼠
- 对 TS 的深入理解. 等找到工作后认真看下
- 为什么 2021 年浏览器依然不能很好地复制动图?–紫云飞的回答
冷知识
- 解释常见现象的同时, 提供了一种查看剪切板内容的思路
- 代码地址: (使用了永久保存技术, 点击查看源代码)
2022 年 7 月 11 日
- 为什么最难不过二叉树的算法出现在面试题中都会被应聘者抱怨?- Cat Chen 的回答
面试
- 面试不是用来考察你懂不懂什么的,而是用来考察你有没有解决问题的能力的,以及将来和你一起解决问题是否容易
- 正确的面试方式是这样子的:现在你来我这里面试,我就告诉你我们在做一辆车子的原型,现在少了一个轮子问你怎么办。没错,我就是要让你重新发明轮子。谁不知道楼下 7-11 有轮子卖,但我就想知道你会如何解决没有轮子的问题。
- 我不指望你一开始能够给我一个轮子,我也知道外面卖的轮子很便宜,但我需要验证你有没有遇到问题后解决问题的能力,这包括思维和动手两方面。在这个比喻的基础上,我们可以来探讨一下面试过程中遇到的各种面试者。
- 最后从面试官的角度来说,面试 ACM/ICPC 竞赛选手往往都很无聊。他们能够给出一个完美的轮子,但我不觉得我能从他们身上学到新东西。(面试过足够多的人后,要见到一个比已知完美轮子更完美的轮子其实非常难。)
- 更有趣的面试者会说,「你知道吗,其实中国古代独轮手推车的轮子设计得比古罗马战车的轮子要合理」。其实我不知道你在说什么,但如果你能够把整套理论说得自圆其说的话我觉得你至少有点思维能力,同时你还真的对轮子感兴趣。事后我可能会去搜索一下看看你说的理论是否正确,但至少我会学到点新东西。
2022 年 7 月 10 日
- 越老越吃香岗位的共同点
工作认知
- 所谓越老越吃香的岗位,都有几个共同点
- 面对的问题比较固定,变化缓慢
- 面对的问题是永远无法根治,只能缓解的问题
- 解决问题的过程中,经验占比超过知识
2022 年 7 月 9 日
- leetcode 分类总结
刷题
- 按照解题思路对 leetcode 进行归类, 用于 hack 面试时的最后一道算法题
- 谈谈工作中的犯错
业务
- 介绍业务中影响比较大的错误.
信息泄漏
/退款接口(重复调用)
/并发问题
/配置错误
/错误是个人和团队最好的学习、提高的机会,而且我们已经交了学费。
- 对于业务, 需要考虑
防御式编程
, 同时, 也要注意开发成本的控制 - 经验总结
- 安全是第一位的,我们在工作中对敏感信息、公司资产要有一定的安全意识。完全按照公司的安全准则来工作,否则提桶跑路可能是小事,被追究法律责任就麻烦了。
- 任何线上操作都是危险的,如非必要不要进行手动的线上操作。操作的时候尽量慢,然后想清楚如果错了如何恢复。比如删东西尽量软删除,把要删的东西移动目录或者设置状态。
- 如果一个动作是有危险的,应该思考如何把这动作自动化,如果是必须有人给输入,那需要一定的流程来进行 Review 和批准。
- 微软还有个好实践就是所有的线上命令,如果是写入型的命令默认不能运行,需要手动地运行命令提升权限。
- 运维方面,如果有条件和时间尽量往 Infrastructure as Code 方向上靠,减少人工进行操作。
2022 年 7 月 4 日
- 编程语言:类型系统的本质
编程语言
- 通过类型系统, 实现编程正确性证明
- 可以作为兴趣进行了解, 工作中用处不大, 但很有意思.
- web 前端面试 - 面试官系列
前端面试-题库
- 类似八股, 但好处是属于明牌, 用来对自己查缺补漏也可以
- 当然更希望的是实际理解这些题目的含义, 而非简单背题.
2022 年 6 月 28 日
- Taro3 跨端跨框架原理初探, https://mp.weixin.qq.com/s/CO92HJjhsP97cXwEBMPGUA
小程序原理
- 对 react-reconciler 应用原理, web-component 组件库选择方案, 以及对 react 的适配
- 书摘
人工智能
- 只有在莱特兄弟停止模仿鸟并开始使用风洞且开始了解空气动力学后后,对『人工飞行』的追求才获得成功。航空工程的教材不会把其领域目标定义为制造『能完全像鸽子一样飞行的机器,以致他们可以骗过其他真鸽子』
人工智能:一种现代的方法
解释为什么人工智能领域研究者全力研究智能的基本原理,而非致力于通过图灵测试
- 面试
- 前端早早聊, C8-9 额台-如何考察候选人的能力与潜力
- 三面时会问:
- 产品的业务模式是什么
- 背后技术的整体架构是什么,你在这里边扮演了什么角色
- 你的位置,你做了什么事情
- 然后会结合他的回答,往里面挖
- 你在 XX 这里遇到了什么问题,解决了什么问题,沉淀了什么东西
- 如果碰到了候选人没考虑到的事,那么会问
- 假设我给你提了这么一个要求,你会怎么考虑这个问题,怎么制定技术的解决方案
- 借此观察候选人怎么思考这个问题,怎么分解,怎么找到问题中的关键点
- 结合关键点怎么设计技术架构,怎么推动落地,在推动落地的过程中,考虑到质量,效率,团队协作这些问题
- 三面面试官会仔细看前两面的面试记录,对于已问过的问题不再问,改为以候选人层级+1 的难度提问,以确认候选人的潜力,考察他思考未知问题的思维方式,来判断他未来往下一层级成长的潜力
- 我在这个职位未来一年/三年的责任是什么
- 你对我有什么期望
2022 年 6 月 26 日
- https://www.zhihu.com/question/61131777/answer/2545197189, 为什么在中国只有一个时区,但是却有很多的时区代码?
编程冷知识
- 在 java6 中, 对上海时区(Asia/Shanghai)而言,
1927-12-31 23:54:07
和1927-12-31 23:54:08
不是相差 1, 而是相差 353- 源代码
1
2
3
4
5
6
7
8
9
10
11
12// via https://stackoverflow.com/questions/6841333/why-is-subtracting-these-two-times-in-1927-giving-a-strange-result
public static void main(String[] args) throws ParseException {
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String str3 = "1927-12-31 23:54:07";
String str4 = "1927-12-31 23:54:08";
Date sDt3 = sf.parse(str3);
Date sDt4 = sf.parse(str4);
long ld3 = sDt3.getTime() /1000;
long ld4 = sDt4.getTime() /1000;
// output => 353
System.out.println(ld4-ld3);
} - 原因是 1928 年民国对上海时区进行了调整, 上海时区往前调整了 5:52,所以时钟上相邻的 1 秒实际间隔 353 秒.
- js 中该值正常, 估计是时区数据库没有那么详细.
- 但仍然可以找到反直觉行为, 相关测试代码为
1
2
3
4let time_1 = new Date("1986-05-04 02:00:00");
let time_2 = new Date("1986-05-04 03:00:00");
// output => 0
console.log(time_1.valueOf() - time_2.valueOf());- 原因在这里
- 源代码
- 解决方法是尽量选择正确的时区来处理时间数据, 剩下的交给专业时区数据库进行处理
- https://zhuanlan.zhihu.com/p/533850515 利用 shields.io 构造带数字的 Github 图片
开发小工具
- 构造出的图片地址 https://img.shields.io/badge/dynamic/json?label=citationCount&query=citationCount&url=https%3A%2F%2Fapi.semanticscholar.org%2Fgraph%2Fv1%2Fpaper%2Fabd1c342495432171beb7ca8fd9551ef13cbd0ff%3Ffields%3DcitationCount
- 实际请求内容 => label=citationCount&query=citationCount&url=https://api.semanticscholar.org/graph/v1/paper/abd1c342495432171beb7ca8fd9551ef13cbd0ff?fields=citationCount
- 效果示例:
2022 年 6 月 24 日
- https://www.zhihu.com/question/25539382/answer/539557939
密码学
- 介绍了一些密码学可以实现的神奇效果以及对应的关键字:
- A 可以向 B 证明自己拥有一个密码,但是如果 B 是假冒的验证者,A 不会透露关于密码的任何信息给 B。——
零知识证明
- A 可以和 B 比较自己持有的一个值的大小关系,而不泄露这个值给对方。——
百万富翁问题
- A 可以给 B 发来的一段信息进行电子签名,而不知道信息的内容。——
盲签名
- A 和 B 可以,在没有公正第三人的情况下,进行等概率胜负的博弈。——
电子博弈
(又称公平掷币协议
) - 邮件服务,如果不考虑法律风险的话,是可以做到让服务器看不到你的邮件内容的。——PGP
- 不可能破解
- 破解 4096 位 RSA 是困难的。——即使用超算也如此。
- 破解 256 位 AES 是困难的。——即使用量子计算也如此。
- 破解 OTP 系统是困难(划掉)不可能的。——即使天顶星人来了也如此。
- 公开的安全算法才是可信的算法
- 一个好的加密算法真的应该是公开的——它可以接受更多人的检验。
- 一个好的密码系统不一定是公开的——但是它应该按照可以公开除了密码之外的一切而依旧安全来设计。
- 可以实现这样的算法,使得班干部中的任何一个均可以以班委会的名义下达通知,且其他人,除了班长之外,都不知道具体下达者。
- 我理解可以这样设计
- 班委本身有对外的公钥私钥体系, 公钥公开, 因此所有人都可以验证消息来自班委
- 班委本身私钥不公开, 部署在服务器上, 只有班长可以登录
- 班委成员向班委服务器提交公钥, 服务器只允许认证过的班委成员调用私钥发送消息(期间私钥不对外展示)
- 对外表现为: 每一个班委成员都可以以班委的身份发送消息, 除了班长在中间可以看到该消息提供方的公钥签名外, 他人只能看到班委在发送消息, 而不知道具体的发送者
- 我理解可以这样设计
- 密码系统的安全性取决于最弱的一环……当年是谁说的
只用 https 保护登录界面就够了
的来着…你的 token 也会被盗- 参考著名漫画: 绝对安全的加密方法……
- 大多数密码系统都不是被正面攻破的…而是实现过程中出了差错…
- 以上内容,真的,真的,在大多数的密码学教材上都能找到——甚至还有用到的一些算法安全性的数学证明…
- A 可以向 B 证明自己拥有一个密码,但是如果 B 是假冒的验证者,A 不会透露关于密码的任何信息给 B。——
- 在这个回答下的评论(来自@invalid s)
- 提问: 请问前端如何实现两次发的密码 hash 值不同的?是要怎么加盐么?或者推荐个简明教材也好,多谢楼主
- 作者回复:w2014就是客户端向服务器申请登录时,服务器给客户端提供一个随机的 salt,而客户端把密码加 salt 做 hash 之后提交给服务器…因为不同次登录拿不到同样的 salt,所以 hash 结果就不一样了……
- invalid s回复
- 简单说,这叫
挑战-应答
模式。 - 服务器知道 MD5(用户密码+盐),它就可以向用户发出
挑战
——你说你是 alice,那么,你的密码、拼上我发过去的盐,算出 MD5 后,再拼上服务器的当前时间 xx 年 xx 月 xx 日 x 时 x 分 x 秒,然后再算一次 MD5:现在,告诉我这个 MD5! - 现在,随便谁,哪怕你全程监控着双方的通信,也不可能知道这个服务器和用户都知道的 MD5(用户密码+盐) 是多少。因为它从来就不曾在线路上出现过,只有真正的服务器和真正的用户才知道、才能计算出这个最终的 MD5、才能确认这个最终 MD5 是否正确。
- 这就是所谓的挑战-应答模式。
- 事实上,oauth2 认证、你登录网络游戏用的电子令牌,它们都是这个原理。
- 简单说,这叫
- 作者推荐了 结城浩的图解密码技术作为入门读物
2022年汇总-今日阅读-工作相关内容
https://www.yaozeyuan.online/2022/06/25/what-read-today/2022-工作相关/