Blog

权益乘数(Equity Multiplier)

什么是权益乘数(Equity Multiplier)?它用来衡量什么? #

又被称为股本乘数,是指资产总额相当于股东权益的倍数。表示企业的负债程度,权益乘数越大,企业负债程度越高。

权益乘数 = 1 / (1 - 资产负债率)

将资产负债率的公式代入:

资产负债率 = 总负债 / 总资产 * 100%

可以得到另一个计算公式:

权益乘数 = 总资产 / 净资产

净资产也称股东权益。

资产负债率(Liability/Asset Ratio)

WATCH机制

Content #

Redis中并发操作在 EXEC 命令前执行,此时,隔离性的保证要使用 WATCH 机制来实现,否则隔离性无法保证。请问WATCH机制是如何保证隔离性的?

WATCH 机制的作用是,在事务执行前,监控一个或多个键的值变化情况,当事务调用 EXEC 命令执行时,WATCH 机制会先检查监控的键是否被其它客户端修改了。如果修改了,就放弃事务执行,避免事务的隔离性被破坏。然后,客户端可以再次执行事务,此时,如果没有并发修改事务数据的操作了,事务就能正常执行,隔离性也得到了保证。

Viewpoint #

From #

Bash初始文件顺序

Content #

Bash以interactive login shell方式启动,在/etc/profile之后,会以何种方式来找用户自定义初始文件?

依次找以下三个位置的文件:

  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile

第一个被找到的文件会被执行。

Viewpoint #

From #

GC死亡螺旋

什么是“GC死亡螺旋”? #

一个糟糕透顶的场景:由于CPU资源减少,请求处理速度变慢,内存使用率上升,导致GC触发次数增多,导致CPU资源的进一步减少。我们将此称之为“GC死亡螺旋”。

Viewpoint #

From #

经验风险(empirical risk)

Content #

统计学习中如果把损失函数(loss function)记为L(Y, f(X)),那么经验风险 (empirical risk)可以怎么表示?

\begin{displaymath}R_{emp}(f)=\frac{1}{N}\sum_{i=1}^{N}L(y_i,f(x_i))\end{displaymath}

Viewpoint #

平均值。

From #

职业的两个维度

一个职业方向好不好,可以从哪两个维度来判断? #

从长期来说,要看它的“高度”和“容量”;从短期来说,要看它的“供需关系”。“高度”指的是这个职业方向上最牛的那批程序员能达到的职场高度,也就是我们常说的“职场天花板”。刚才我们说的算法工程师,只从年收入来说,国内可以达到 200 万人民币,美国可以达到 60 万美元(再往上属于凤毛麟角,不具备统计意义)。对于普通人来说,显然是足够高的天花板了。

“容量”,指的是这个职业方向能够容纳的从业者的数量。上面提到的算法、后端、移动端等方向,它们的从业者容量都是非常大的,这就代表着整个相关行业是繁荣的,跳槽和选择的机会非常多,我们就容易把握住行业中新的发展机会。

一个好的职业方向,一定是高度很高,容量很大且稳定的方向。

Viewpoint #

From #

D锁存器

D锁存器 #

为了让存储电路可以保持记忆的能力,我们可以考虑为这种电路引入保持位,当保持位为 1 时,数据可以被存储进电路,当存储完成以后,保持位变为 0,输入就不能再影响输出了。

如下图所示,通过增加两个与门来实现保持位 C。当保持位为 1 时,RS 锁存器的功能与不加保持位时完全相同,当保持位为 0 时,则 R 端和 S 端不论取什么值,都不再起作用了。

我们再对上图进行更深一步的分析,R 和 S 同时为 0 的情况,可以使用保持位为 0 来代替。R 和 S 同时为 1 的情况是非法情况,所以我们可以使用一个非门,把 R 和 S 合并成一个信号 D,这样的话,电路的输入端就可以进一步化简,如下图所示:

上面电路的保持位为 1 时,输出 Q 可以反应输入 D 的变化,当保持位为 0 时,输出 Q 保持原来的值不变。这种电路被称为电平触发的 D 型锁存器。其中的 D 代表数据 Data。

我们知道信号在传输的过程中容易产生毛刺等不稳定的现象,所以在保持位为 1 的期间,如果输入信号还是不能稳定的话,那么输出将随着输入的改变而发生相应的变化。这种情况下,锁存器的状态就难以稳定。我们把在保持位为 1 期间,锁存器发生多次翻转的情况称为空翻。

在实际应用中,人们还是希望存储电路有良好的稳定性,从这个角度上看,电平触发的锁存器的抗干扰能力相对较差。

Viewpoint #

From #

13 | 存储电路:计算机存储芯片的电路结构是怎样的?

RS锁存器

RS锁存器 #

我们把具有存储信息能力的电路,称为存储器。其中,RS 锁存器 (Latch) 是最简单的一种存储器电路,它可以存储一个比特,如下图所示:

上图中的电路由两个或非门组成,它的特点是,图上方的或非门的输出作为图下方的或非门的输入,反过来,图下方的或非门的输出,也是图上方的或非门的输入。我来分析一下这个电路的特点,你就能理解这个电路是如何完成一个比特的存储的。

一开始,输入端 R 和 S 都是低电压,代表 0,上方的或非门输出为 0,下方的或非门输出为 1,这是一种合法状态。或者下方的或非门的输出为 0,上方的或非门的输出为 1,这也是一种合法状态。也就是说这个电路在 R 和 S 都为 0 的时候,有两种合法的稳定状态。

如果此时,S 变成高电压,也就是 1,那么下方或非门的输出就变成 0,进而导致上方或非门的输出变成 1,也就是 Q 变成 1。这个时候,如果 S 又变成低电压的话,因为上方或非门的输出为 1,所以下方或非门的输出仍然保持为 0。而输入端 R 仍然为 0,这就使得上方或非门的两个输入端都为 0,进而 Q 的高电压可以得到保持。

于是,我们就看到了神奇的一幕:输入端 S 变为 1 以后,可以将输出端 Q 变成 1,但是当 S 变为 0 以后,输出端仍然保持 1。这就说明这个电路可以存储 1。

当 R 和 S 都是 0、Q 为 1 时,如果此时 R 变成 1,由于电路是对称的,可以很容易分析得到 Q 将变成 0,Q 反(表示 Qˉ​,下同)变成了 1。同样地,如果此时 R 再变成 0,Q 为 0,Q 反为 1 的状态仍然可以保持。这就实现了一个可以保持一个比特的存储器。

...

CPU执行时间的公式

CPU执行时间的公式 #

CPU 执行时间的公式: 程序的 CPU 执行时间 =CPU 时钟周期数×时钟周期时间

最简单的提升性能方案,自然缩短时钟周期时间,也就是提升主频。换句话说,就是换一块好一点的 CPU。不过,这个是我们这些软件工程师控制不了的事情,所以我们就把目光挪到了乘法的另一个因子——CPU 时钟周期数上。如果能够减少程序需要的 CPU 时钟周期数量,一样能够提升程序性能。

对于 CPU 时钟周期数,我们可以再做一个分解,把它变成“指令数×每条指令的平均时钟周期数(Cycles Per Instruction,简称 CPI)”。不同的指令需要的 Cycles 是不同的,加法和乘法都对应着一条 CPU 指令,但是乘法需要的 Cycles 就比加法要多,自然也就慢。在这样拆分了之后,我们的程序的 CPU 执行时间就可以变成这样三个部分的乘积。

程序的 CPU 执行时间 = 指令数×CPI×Clock Cycle Time

因此,如果我们想要解决性能问题,其实就是要优化这三者。

  1. 时钟周期时间就是计算机主频,这个取决于计算机硬件。我们所熟知的摩尔定律就一直在不停地提高我们计算机的主频。比如说,我最早使用的 80386 主频只有 33MHz,现在手头的笔记本电脑就有 2.8GHz,在主频层面,就提升了将近 100 倍。
  2. 每条指令的平均时钟周期数 CPI 就是一条指令到底需要多少 CPU Cycle。在后面讲解 CPU 结构的时候,我们会看到,现代的 CPU 通过流水线技术(Pipeline),让一条指令需要的 CPU Cycle 尽可能地少。因此,对于 CPI 的优化,也是计算机组成和体系结构中的重要一环。
  3. 指令数代表执行我们的程序到底需要多少条指令、用哪些指令。这个很多时候就把挑战交给了编译器。同样的代码,编译成计算机指令时候,就有各种不同的表示方式。

我们可以把自己想象成一个 CPU,坐在那里写程序。计算机主频就好像是你的打字速度,打字越快,你自然可以多写一点程序。CPI 相当于你在写程序的时候,熟悉各种快捷键,越是打同样的内容,需要敲击键盘的次数就越少。指令数相当于你的程序设计得够合理,同样的程序要写的代码行数就少。如果三者皆能实现,你自然可以很快地写出一个优秀的程序,你的“性能”从外面来看就是好的。

Viewpoint #

From #

03 | 通过你的CPU主频,我们来谈谈“性能”究竟是什么?

...