Skip to main content

coding

· 2 min read

我很蠢,什么都不会,代码也不会写

我只是喜欢一个我不存在的东西

我觉得写工作的代码很恶心

但是我喜欢修bug

最近最开心的是给php-src提了两个pr并且通过了 ,但是我还是不会写php,我也不会c,我也背不过php的array系列的函数.

说到底,我还是太弱了

我其实不会写代码,但是会修bug.

因为修bug是体力活,写代码是脑力活

我果然很笨,什么都不会 只会写一堆bug

准备看看能不能修mysql的代码

没有银弹 No Silver Bullet

我真的会写代码吗? 我其实什么都不懂吧

我真的什么都不懂,有点怀疑自己这几年是不是只会copy and plaste 了

golang compile

· 3 min read

golang 的 lex和parse 在src\cmd\compile\internal\gc\main.go开始

核心步骤

  • parseFiles lex and parse
  • typecheck 语法树的遍历做类型检查
  • ssa

之后会经过link 连接和加载器ld

func Main(archInit func(*Arch)) {
lines := parseFiles(flag.Args()) // lex and parse
...
typecheckok = true

// Process top-level declarations in phases.

// Phase 1: const, type, and names and types of funcs.
// This will gather all the information about types
// and methods but doesn't depend on any of it.
//
// We also defer type alias declarations until phase 2
// to avoid cycles like #18640.
// TODO(gri) Remove this again once we have a fix for #25838.

// Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "top1")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op != ODCL && op != OAS && op != OAS2 && (op != ODCLTYPE || !n.Left.Name.Param.Alias) {
xtop[i] = typecheck(n, ctxStmt)
}
}

// Phase 2: Variable assignments.
// To check interface assignments, depends on phase 1.

// Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "top2")
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op == ODCL || op == OAS || op == OAS2 || op == ODCLTYPE && n.Left.Name.Param.Alias {
xtop[i] = typecheck(n, ctxStmt)
}
}

// Phase 3: Type check function bodies.
// Don't use range--typecheck can add closures to xtop.
timings.Start("fe", "typecheck", "func")
var fcount int64
for i := 0; i < len(xtop); i++ {
n := xtop[i]
if op := n.Op; op == ODCLFUNC || op == OCLOSURE {
Curfn = n
decldepth = 1
saveerrors()
typecheckslice(Curfn.Nbody.Slice(), ctxStmt)
checkreturn(Curfn)
if nerrors != 0 {
Curfn.Nbody.Set(nil) // type errors; do not compile
}
// Now that we've checked whether n terminates,
// we can eliminate some obviously dead code.
deadcode(Curfn)
fcount++
}
}
// With all types checked, it's now safe to verify map keys. One single
// check past phase 9 isn't sufficient, as we may exit with other errors
// before then, thus skipping map key errors.
}
(gdb) bt
#0 cmd/go/internal/load.LoadImport (path=..., srcDir=..., parent=0xc000147200, stk=0xc0001db698, importPos=..., mode=1, ~r6=<optimized out>) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:530
#1 0x000000000079fa1b in cmd/go/internal/load.(*Package).load (p=0xc000147200, stk=0xc0001db698, bp=0xc0001b8a80, err=...) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:1707
#2 0x0000000000799827 in cmd/go/internal/load.loadImport (pre=0x0, path=..., srcDir=..., parent=0xc000146d80, stk=0xc0001db698, importPos=..., mode=1, ~r7=<optimized out>)
at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:578
#3 0x000000000079890a in cmd/go/internal/load.LoadImport (path=..., srcDir=..., parent=0xc000146d80, stk=0xc0001db698, importPos=..., mode=1, ~r6=<optimized out>) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:531
#4 0x000000000079fa1b in cmd/go/internal/load.(*Package).load (p=0xc000146d80, stk=0xc0001db698, bp=0xc0001b8700, err=...) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:1707
#5 0x0000000000799827 in cmd/go/internal/load.loadImport (pre=0x0, path=..., srcDir=..., parent=0xc000146900, stk=0xc0001db698, importPos=..., mode=1, ~r7=<optimized out>)
at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:578
#6 0x000000000079890a in cmd/go/internal/load.LoadImport (path=..., srcDir=..., parent=0xc000146900, stk=0xc0001cf698, importPos=..., mode=1, ~r6=<optimized out>) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:531
#7 0x000000000079fa1b in cmd/go/internal/load.(*Package).load (p=0xc000146900, stk=0xc0001db698, bp=0xc0001b8380, err=...) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:1707
#8 0x00000000007a4c66 in cmd/go/internal/load.GoFilesPackage (gofiles=..., ~r1=<optimized out>) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:2230
#9 0x00000000007a3c54 in cmd/go/internal/load.PackagesAndErrors (patterns=..., ~r1=...) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:2056
#10 0x00000000007a417d in cmd/go/internal/load.PackagesForBuild (args=..., ~r1=...) at /home/dinosaur/newgo/go/src/cmd/go/internal/load/pkg.go:2123
#11 0x0000000000842528 in cmd/go/internal/work.runBuild (cmd=<optimized out>, args=...) at /home/dinosaur/newgo/go/src/cmd/go/internal/work/build.go:348
#12 0x0000000000932219 in main.main () at /home/dinosaur/newgo/go/src/cmd/go/main.go:189

a language to machine code

· One min read

计算机语言是什么?

我感觉是一个数学系统

编译成机器码是什么?

是绑定了动作

// lex parse 类型系统 ssa asm elf abi

keyword   :
int bool
for while if

ssa optimistic

· 2 min read

优化的本质是什么呢?

比如ssa,是减少死代码,通过常量传播和常量折叠减少运行时的计算

比如sql的逻辑优化: 就是一个逻辑下推 通过变换减少读io

编译的一般步骤:

lex : 词法分析 parse: 语法分析构造语法树 cfg优化
codegen

在golang 和php都有ssa 优化,ssa 优化是通过控制流图来做常量传递 常量折叠 和 死代码去除

php的ssa 优化在opcache中,而golang的也在类似的包里面

structure induction

CFG

construct cfg

ssa

what is ssa

A program is defined to be in SSA form if each variable is a target of exactly one assignment statement in the program text.

如果程序里面每个变量只被赋值一次那么这个程序就具有ssa 形式

def-use chain and use-def chain

Under SSA form, each variable is defined once. Def-use chains?are data structures that provide, for the single definition of a variable, the set of all its uses. In turn, a use-def chain?, which under SSA consists of a single name, uniquely specifies the definition that reaches the use.

def-use chain 就是输入是 定义(赋值) , 输出是使用被使用的变量的集合

use-def chain 刚好相反 输入是使用的变量 而 输出是他的定义(赋值)的集合, 对于ssa 的程序来说, 每个变量只被赋值(定义)一次,所以这个use-def这个数据结构在ssa形式下这个集合只有一个元素 ssa 形式下

ssa properties

ssa 有什么性质 ?

DG

JG

insert φ-function

construct ssa

destruct ssa

相关阅读

规则系统

· One min read

我一直对所谓的可扩展性什么的很有疑惑,或者说我们要怎么设计一个规则系统,怎么知道这个规则的集合的边界在哪里

第一个例子: 流水线

流水线上每个节点都是一个回调,我们可以随意添加或者删除

有向无环图 等价于原始递归函数

这个规则系统的路径则需要输入来确定,所以和语言是等价的

所以一个规则系统等价于一个语言,所以我们可以使用一些内容来等价和变换

math

· 2 min read

其中一种是基于锁 我之前一直对acid理解有问题,锁和事务的关系,其实是这样的:

1 read(x) 和write(x)是不可以交换顺序的 2 write(x) write(x) 是不可以交换顺序的 3 write(x) 和read(x) 也是不可以交换顺序的

我们的事务 t1和t2 如果完全按照先执行t1再执行t2 就一点问题都没有,就是有点慢,并发低。

那么我们就用一些等价的方法,尽量减少阻塞。我们不锁住整个事务,只对冲突的部分进行锁定,其他就因为等价所以顺序没有关系,因为其他部分没有顺序关系,所以不用上锁,所以并发会上去


类型是什么? 类型描述了一个特别的集合

结构体是什么?

结构图本质是类型的组合,也就是关系

举个例子

struct{
int a,
int b
}

这个本质是 RXR 的关系 ,那一个结构体的变量又是什么? 是这个关系的一个元素

递归是什么? 递归是差分方程,递归是不动点,但是递归的内容还得看

什么是可扩展性?

BNF 或者类似的规则系统为什么是正确的? 靠什么保证?是依赖范畴学或者其他数学的什么定理或者和数学的什么模型一致? 我一直很好奇规则系统的约束怎么做到的?因为规则系统真的很神奇

induction

· One min read

前言

归纳法是一个很特别的推理方式。使用自然数的映射。(我的理解可能不太对)

Mathematical induction

数学归纳法

  • P(0) is true
  • If P(m) is true then so is P(m + 1) for any natural number m. (P(O) & (Vm E w. P(m) =} P(m + 1)) =} Vn E w. P(n).

well define

Q 的非空子集有最小值

induction 举例

BNF 是一个典型的递归定义集合(induction define set) 。 归纳法有个很特别的东西,就是用一个很短的表达式描述一个有限集合

Recursive definitions of sets

举例: 自然数集合:
P(0) = 0 ; P(N+1) = P(N)+1

相关阅读

编译原理

· 2 min read

什么是编译?

一个从一种状态集转换为另外一个状态集的过程

什么是优化?

什么是类型,类型就是集合的约束

一个类型就是一个集合

什么是隐式转换

就是一个集合被编译器材自动从一个集合映射到另外一个集合

因为不同类型的运算是未定义的(也可能是不闭合的,但是更多是未定义的 )

举个例子sql的谓词有些是二值的有些是三值的,导致语义会很难每个人都清楚

同构

什么是同构? 这是我最想弄明白的东西,真的很奇妙

语法和语义(syntax and semantic)

自然语言的语法

如果学过英语,那么i eat apple就是一个主谓宾结构,我对自然语言的语法的理解就是满足某些结构的结构(好吧可能是错误的结论)

数理逻辑的语法

数理逻辑也有相类似的语法

编程语言的语法

编程语言也是特定的token组合就是一个语法结构; 举个例子:

a = 1 ;   // 由三个token组成  token<a> token<=> token <1> , 由parse规约而成

语义

操作语义(operate semantic)

描述这个语法对应的操作

表达式(Expressions)

如果是c++的表达式,就是一个序列,这个序列有返回值 举个例子:

The result of the expression always has type void [1]

返回值或者求值结果是void

相关阅读

php 反射

· One min read

反射是一个很特别的api,php的反射是一个很特别的回调

(gdb) bt
#0 zim_reflection_class_hasProperty (execute_data=0x7ffff3a14220, return_value=0x7ffff3a14180) at /home/ubuntu/php-src-php-7.4.1/ext/reflection/php_reflection.c:4186
#1 0x0000555555af49b2 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at /home/ubuntu/php-src-php-7.4.1/Zend/zend_vm_execute.h:1729
#2 0x0000555555b58295 in execute_ex (ex=0x7ffff3a14020) at /home/ubuntu/php-src-php-7.4.1/Zend/zend_vm_execute.h:53588
#3 0x0000555555b5c32d in zend_execute (op_array=0x7ffff3a61c00, return_value=0x0) at /home/ubuntu/php-src-php-7.4.1/Zend/zend_vm_execute.h:57664
#4 0x0000555555a80b27 in zend_execute_scripts (type=8, retval=0x0, file_count=3) at /home/ubuntu/php-src-php-7.4.1/Zend/zend.c:1663
#5 0x00005555559e2bad in php_execute_script (primary_file=0x7fffffffd0e0) at /home/ubuntu/php-src-php-7.4.1/main/main.c:2619
#6 0x0000555555b5ee34 in do_cli (argc=2, argv=0x55555678ab30) at /home/ubuntu/php-src-php-7.4.1/sapi/cli/php_cli.c:961
#7 0x0000555555b5ff9e in main (argc=2, argv=0x55555678ab30) at /home/ubuntu/php-src-php-7.4.1/sapi/cli/php_cli.c:1352

mysql_error_sqlstate

· One min read

当我们使用jdbc 或者pdo或者其他mysql的驱动的时候,经常看到错误会有两个错误码 举个例子

Error number: 1005; Symbol: ER_CANT_CREATE_TABLE; SQLSTATE: HY000

1005HY000 或者是

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '34' for key 'PRIMARY',

230001062

那么两者的关系是怎么样的呢?

Error code: This value is numeric. It is MySQL-specific and is not portable to other database systems.

SQLSTATE value: This value is a five-character string (for example, '42S02'). SQLSTATE values are taken from ANSI SQL and ODBC and are more standardized than the numeric error codes.

不管怎么样,你会看到两个错误一个是SQLSTATE,一个是 errorcode,两者区别就是SQLSTATE更加标准或者通用一些,而errorcode则是mysql自己的

相关阅读