Forwarded from 有记忆的人 Stand with Ukraine
真的很替华为惋惜,虽然程序设计语言领域的冰封哥支持华为并且称有多为 CE 的朋友在开始工作了
可我觉得原型是很重要的,如果一个东西很久连个基本的框架都没有,我们是不是可以认为,它的可维护性很差?模块化程度太低???
可我觉得原型是很重要的,如果一个东西很久连个基本的框架都没有,我们是不是可以认为,它的可维护性很差?模块化程度太低???
duangsuse Throws
真的很替华为惋惜,虽然程序设计语言领域的冰封哥支持华为并且称有多为 CE 的朋友在开始工作了 可我觉得原型是很重要的,如果一个东西很久连个基本的框架都没有,我们是不是可以认为,它的可维护性很差?模块化程度太低???
#China #Huawei #PL #ce 打住,据说冰封哥和蛤为方舟编译系统没半毛钱关系,不过我是在 Q 群里看到他说有研发方舟的朋友的。
顺道给各位没听说过的科普一下,常见的编译优化(这里不局限于 JVM 平台,而且我和 JVM 的实现也没太大关系,尽管我会偶尔思考一下线性指令序列的控制流和高级控制结构的关系)
constant-propagation & constant-folding, dead-code-elimation, inlining, instcombine(当然也包括 jmp 指令的), loop-unrolling, loop-reversal, loop-inversing, loop-invariant-code-motion(LICM), tail-call-optimization(TCO), , global-value-numbering(GVN), common-subexpression-elimation
有些过于直白的优化就不用看了,当然也不必看。(你自己应该会写)
+ cp/cf 系可怜的 Javac 都有的优化,不信你试试:
+ dce 我学过基于 BFS(breath-first search) 对 LLVM 的 Value ADCE 的,不过再高级一点的输入 ADCE(激进 DCE) 也就是走一遍到集合 {used} 然后取补、删。(苏格拉底都问过学生同类问题:苹果林里你不走一遍是不知道哪颗苹果树绝世而孤立的…… emmm怎么感觉有点不对?)
+ inline 就是 inline function 呗,很多优化的效果都依赖这个优化(外部到局部)
+ instcombine 不是标准的名字(LLVM的),比如合并赋值+一串jmp,就是 Lua 跳转链表
+ unroll 就是展开。reversal 和 inversing 的区别是,reversal 就是你从 N 数到零可以用类似 decrease-jumpIfZero(DJNZ) 这种指令(反之;<n;i++这种不行)、inversing 的意思是
知道循环为什么叫循环吗?因为
知道我们在生成
+ LICM 包含说的 loop-expression-hoisting.
高级一点的,比如 LLVM(low-level-virtual-machine) 的 Alias-analyzing (特指 C/C++ 这种
编译策略上(基本是JVM/CLR里有的),比如 JIT(just-in-time), AOT(ahead-of-time), on-stack replacement, hot-spot dection
JVM 上常见的,比如 de-reflexing, unboxing, range-check-elimation, null-check-elimation, branch-frequencey-prediction (从《深入理解Java虚拟机》书上精选的)
程序员自己要做 profile-guided optimization(PGO) 和算法选择上面的研究(这样学术一点的就得用到函数增长率,普通一点的比如我就会选择口碑好的emmm)。
不知道算了,可以自己到 wiki 上查,不过如果你能够默写 The Little Schemer (不要问我为什么总拿这本书说话,这里是刚好合适,一些优化不一定需要很厉害的算法) 的列表处理例子,基本上就可认为是有足够技术水平去实现了
—
既然我都说了这么多了,那再顺便提及一下『汇编』吧,虽然我一个弄软件的也不知道太多。
一般来说汇编还是要分 instruction structure architecture(ISA) 的,可以按地址归类为 0, 1, 2, 3 地址
举个例子,比如加法运算吧。
你可以设想一下,即便
如果你要设计一个温度计,同时支持摄氏度华氏度显式,所以你的
3 地址一般就是 dst, src1, src2
我们常说的汇编一般认为是当年个人机所用 x86 架构处理器,是3地址。
『汇编』很多时候都会有类似这样的指令:
ldc — 存储常量
ld, st — 读取/写入待操作的对象
mov — 读取和存储的 combine,也就是 copy
别和 "clone" 搞混了,clone 一般是对聚合量(product value)
jmp — 直接指定下一条指令的位置,一般用于循环
br — 分支,如果存储里是「真(truthy)」值
br.not — 分支,如果存储里「非真(falsy)」值
op — 以待操作的对象,实际执行操作
操作有可能有值,一般会被送到存储中(比如 JVM 里就是栈顶)
call — 调用,移交控制权给目标子程序并且待其完成。
alloc — 分配一定大小的栈帧本地存储
ret — (被调用者 callee)从自己的栈帧返回到 caller,本帧分配(alloca)的存储作废。
在有「调用栈层次」的机器里,一般 ld/st/mov 都会有一个所谓的「存储层次」。目的是,某个子程序可以访问调用者给自己的参数。
对应地,call 也会有一个所谓的层次参数指定新调用的层次。
这个过程需要依赖对调用栈
某些机器有「寄存器窗口」,它意味着每个 call 都能够得到自己的一组寄存器。
可以看看 Wiki 的 PL/0 和 p-code,之前我在 USTC 的 CE share 里看到了 PL/0 实践教程的文档,好像是被撤下了?
顺道给各位没听说过的科普一下,常见的编译优化(这里不局限于 JVM 平台,而且我和 JVM 的实现也没太大关系,尽管我会偶尔思考一下线性指令序列的控制流和高级控制结构的关系)
constant-propagation & constant-folding, dead-code-elimation, inlining, instcombine(当然也包括 jmp 指令的), loop-unrolling, loop-reversal, loop-inversing, loop-invariant-code-motion(LICM), tail-call-optimization(TCO), , global-value-numbering(GVN), common-subexpression-elimation
有些过于直白的优化就不用看了,当然也不必看。(你自己应该会写)
+ cp/cf 系可怜的 Javac 都有的优化,不信你试试:
id=`uuidgen`辣鸡 Javac 不接受非 Java 扩展名的输入!
echo 'class CostFold { String ing() { if (true) return "+"; else return "-"; } }'>/tmp/${id}.java
javac /tmp/${id}.java -d /tmp
javap -cp /tmp -c CostFold
+ dce 我学过基于 BFS(breath-first search) 对 LLVM 的 Value ADCE 的,不过再高级一点的输入 ADCE(激进 DCE) 也就是走一遍到集合 {used} 然后取补、删。(苏格拉底都问过学生同类问题:苹果林里你不走一遍是不知道哪颗苹果树绝世而孤立的…… emmm怎么感觉有点不对?)
+ inline 就是 inline function 呗,很多优化的效果都依赖这个优化(外部到局部)
+ instcombine 不是标准的名字(LLVM的),比如合并赋值+一串jmp,就是 Lua 跳转链表
+ unroll 就是展开。reversal 和 inversing 的区别是,reversal 就是你从 N 数到零可以用类似 decrease-jumpIfZero(DJNZ) 这种指令(反之;<n;i++这种不行)、inversing 的意思是
while-p: ...; br.not :while-broke<=>(可代换)
(your code)
jmp :while-p
while-broke: ...
br.not :while-broke就是
do-while-cont:
(your-code)
...; br :do-while-cont
while-broke: ...
while () {} 翻译成 if () do {} while (); 的意思了,根本区别在于 br 指令不必 jmp 后执行,据说在流水线上有好处。知道循环为什么叫循环吗?因为
jmp, br 指令可以随意重置指令指针,使得下条指令可能是jmp的前驱(或者说它可达这条jmp),扭转程序往下执行的趋势。知道我们在生成
br.not :broke 代码的时候为什么能够知道 while-broke 的位置/偏移吗?可以用回填啊,Lua 的跳转链表也解决了回填问题+ LICM 包含说的 loop-expression-hoisting.
高级一点的,比如 LLVM(low-level-virtual-machine) 的 Alias-analyzing (特指 C/C++ 这种
union 弄不清指针到底是什么的语言, 当然 C++ 默认策略也不能直接做到 exact memory management), Vectorization: SLP(superword-level-parallelism) 和 loop vectorization编译策略上(基本是JVM/CLR里有的),比如 JIT(just-in-time), AOT(ahead-of-time), on-stack replacement, hot-spot dection
JVM 上常见的,比如 de-reflexing, unboxing, range-check-elimation, null-check-elimation, branch-frequencey-prediction (从《深入理解Java虚拟机》书上精选的)
程序员自己要做 profile-guided optimization(PGO) 和算法选择上面的研究(这样学术一点的就得用到函数增长率,普通一点的比如我就会选择口碑好的emmm)。
不知道算了,可以自己到 wiki 上查,不过如果你能够默写 The Little Schemer (不要问我为什么总拿这本书说话,这里是刚好合适,一些优化不一定需要很厉害的算法) 的列表处理例子,基本上就可认为是有足够技术水平去实现了
—
既然我都说了这么多了,那再顺便提及一下『汇编』吧,虽然我一个弄软件的也不知道太多。
一般来说汇编还是要分 instruction structure architecture(ISA) 的,可以按地址归类为 0, 1, 2, 3 地址
举个例子,比如加法运算吧。
(1+2) * 3 (=9)
ldc 3零地址一般就是说 JVM, Ruby YARV, CLR 这种以 last-in-first-out(LIFO)「栈」 传递参数的架构
ldc 2; ldc 1; isum // 当然这里用的是逆记法,因为弹(pop)出来的是最后压(push)上去的,尽管我们希望 (1) 先被求值。
imul
(accumlator) plus 1; (accumlator) plus 2; (accumlator) times 9
1地址现在很不常见,早期可能在还没 programmable-logical-device(PLD) 的时候繁荣过一时你可以设想一下,即便
(1+2)*3 还是 1+(2*3) 都没问题(因为只是计算结合顺序变了),如果我们是要 a = a + f(a) 照这种法子要怎么办?如果你要设计一个温度计,同时支持摄氏度华氏度显式,所以你的
f(x) 是算偏差量的函数,这时程序你又该怎么写?效率又怎么样?add A, 1; add A, 2; mul A, 9
2 地址现在很常见了,就是 reduced-instruction-set-computers(RISC) 的芯片们,比方说你 armv7/v8 的手机,当然 hard-float(hf) 与否无关。3 地址一般就是 dst, src1, src2
add A, A, 1; add A, A, 2; mul A, A, 9
当然我举的例子在 Java 里貌似都是常量表达式?我们常说的汇编一般认为是当年个人机所用 x86 架构处理器,是3地址。
『汇编』很多时候都会有类似这样的指令:
ldc — 存储常量
ld, st — 读取/写入待操作的对象
mov — 读取和存储的 combine,也就是 copy
别和 "clone" 搞混了,clone 一般是对聚合量(product value)
jmp — 直接指定下一条指令的位置,一般用于循环
br — 分支,如果存储里是「真(truthy)」值
br.not — 分支,如果存储里「非真(falsy)」值
op — 以待操作的对象,实际执行操作
操作有可能有值,一般会被送到存储中(比如 JVM 里就是栈顶)
call — 调用,移交控制权给目标子程序并且待其完成。
alloc — 分配一定大小的栈帧本地存储
ret — (被调用者 callee)从自己的栈帧返回到 caller,本帧分配(alloca)的存储作废。
在有「调用栈层次」的机器里,一般 ld/st/mov 都会有一个所谓的「存储层次」。目的是,某个子程序可以访问调用者给自己的参数。
对应地,call 也会有一个所谓的层次参数指定新调用的层次。
这个过程需要依赖对调用栈
(底,顶) 或言 (b, t) 的维护。某些机器有「寄存器窗口」,它意味着每个 call 都能够得到自己的一组寄存器。
可以看看 Wiki 的 PL/0 和 p-code,之前我在 USTC 的 CE share 里看到了 PL/0 实践教程的文档,好像是被撤下了?
Wikipedia
Propagation constant
complex measure of the attenuation (real part) and phase angle (imaginary part) along the path travelled by a plane wave
duangsuse Throws
#China #Huawei #PL #ce 打住,据说冰封哥和蛤为方舟编译系统没半毛钱关系,不过我是在 Q 群里看到他说有研发方舟的朋友的。 顺道给各位没听说过的科普一下,常见的编译优化(这里不局限于 JVM 平台,而且我和 JVM 的实现也没太大关系,尽管我会偶尔思考一下线性指令序列的控制流和高级控制结构的关系) constant-propagation & constant-folding, dead-code-elimation, inlining, instcombine(当然也包括 jmp 指令的)…
—
既然我都谈到 JVM 了,那我就再科普一些 GC 的基本理念,顺路推隔壁 USTC 的公开资料(虽然我没时间看了)
(好像没有公开资料了?)
garbage-collector(GC) 呢…… 就是自动内存管理,有条件的可以了解一下 boehm gc 什么的,比较知名
GC 就是让人把存储视作对象的东西,有时候我们需要这么做:
经典的计算机是面向存储、面向处理过程的,可是编程是面向对象(你也可以说是面向函数组合或者 continuation-passing-style, CPS)的,人的开发效率和机的执行速度,天生水火不容。
有个笑话说,冯·诺伊曼怒骂过程序员,“你怎么能用 assembler 呢?你知道它浪费了多少 CPU cycle 吗???”
鱼和熊掌不可得兼,所以要有权衡和取舍。曾经(比如 62 年前 1957, Fortran刚刚发明的时候)的时候,CPU们的速度还很慢,于是程序员就成了冤大头,不得不和一堆与机器过分相关的细节死肝,来描述自己的逻辑和计算。
因为那时候计算机的应用也就是那个『超算』『集群(cluster)』的程度,程序员也没有享受计算机周到服务的那个底气,机器的时间金贵啊!
21 世纪就不一样了,程序员不仅仅是『喜新厌旧』连 assembler 都看不上了,而且还用上了 compiler,甚至 virtual machine,这一个一个跑一秒钟都「浪费」 cycle 到能让老冯跪在地上哭啊!😭
可是程序员依然用得不亦乐乎,甚至还弄了 type checker, linter, inline docgen, sanitizer, code generator, build system, package manager,还IDE、自动补全、智能感知、浏览定位、代码分析,还测试全覆盖、DevOps、云计算。当然所有人也都是一样,因为计算机的算力上去了,不怕浪费一点宝贵的,应该拿去做科学计算的 CPU cycle 了。
如果能够避免悬垂指针或者说野指针(dangling pointer)、内存泄漏(memory leak),能够检测出指针溢出(pointer overflow)索引越界,其实由计算机处理更多工作也没什么,它闲嘛。
当然我这里不是说因为算力上去了你就可以不并行处理,编程时你就可以不做算法分析,不好好考虑怎么节省资源提高内存效率和执行速度。胡乱弄个纸张算法,这不是程序员该有的行为。
如果啥时候我们不需要记忆某些对象了,是不是就可以
之前我们说了
比如说,我们知道在 Java 里你只能访问静态、实例、局部变量(可能不准确,凑合着吧):
回收辣鸡就是对每个『对象』问一个问题:你有用么?
细化一点,就是在『某个时候』去问『我Boss的代码能够访问到你么?』,如果不能,『回收』这个对象。
当然对象也不一定得是所有的对象,比如,可以只是某个特定「区域」的对象。
这是要看时机的,比如
然后 execute 返回,我们就拿不到
如果啥都不做,『蔡徐鲲』就这么『泄漏(leak)』了,因为我们无法再见到它,它却偷偷躲在『片场』(内存池) 的某个角落里大跳《只因你太美》!
所以调用后的任何时候,我们问这三个对象(藏在
对象
(当然其实也是没有用的 (
对象
(所以这种会被放在 HotSpot JVM 的永久代或常量区,当然也有人叫方法区)
对象
我们刚才做的简单算法一般叫『标记-清除(mark-sweep)』算法,它也是 1958 年 Lisp 实现的第一个自动内存管理算法。
它是通过追踪调用栈(就是所有的『动态』变量)上的所有帧本地变量,BFS(广度优先搜索) 标记它们所依赖的对象做到的,换句话说,是为了保留根对象而搜索必须留下的对象、回收不必留的对象
为什么不直接搜索不必留的对象?看看上面的『苏格拉底的问题』…… 数学逻辑上的证明找数学家吧。
实现的细节有 bitmap marking (为 Unix-like 进程 CoW, copy-on-write 优化的).
不过这样不是不能优化,想想一个对象的依赖关系图 — 一个 Node 指向很多其他 Node,有些东西 — 我们称为 primitive,比如 int, float, double 这些 — 是图里最后的顶点
我们的问题是,假设有一个过程引用了
首先我们想,
然后某个依赖处消失,a 还是(递归解除引用关系) x, y, z 的依赖数目都减1,为0时就可以回收,这就是 Rc(引用计数) 算法。
Rc 相对于 tracing 是一种『概括性』的算法,因为它不从GC roots追踪实际引用,只是(有损失地)概括为某对象的被引次数。
Python和PHP 好像默认都是 Rc,不过他们是不会泄漏循环引用的,即便他们没有
欸我还有事的,怎么讲起这些不懂的领域了…… 😫
算了,这里我提及一些名词,请大家自己发动手指找资料……
Common-Language-Runtime(CLR), Mono project
弱代假说(weak-generation hypothesis)、分代垃圾回收
Exact memory management, pointer-type
Semi-space algorithm, Eden Heap, coping-GC, compat-GC
stop-the-world, incremental-GC, tri-color GC, GC write barrier
harmony_gc_source.pdf
停,这个 Harmony 不是华为的『鸿蒙操作系统』,是 Apache Haromny,一个曾经确实是不负众望过但是又因为 Oracle 的打压弄得 Java 世界都支离破碎的项目,当然这不怪它,全赖那个不思进取心胸狭隘的 Oracle。
既然我都谈到 JVM 了,那我就再科普一些 GC 的基本理念,顺路推隔壁 USTC 的公开资料(虽然我没时间看了)
(好像没有公开资料了?)
garbage-collector(GC) 呢…… 就是自动内存管理,有条件的可以了解一下 boehm gc 什么的,比较知名
GC 就是让人把存储视作对象的东西,有时候我们需要这么做:
Object[] memorizedThings = new Object[] {john, monkey, apple, grape, banana};
当然,以上例子按照面向对象封装建模可以建模成 class,按函数式闭包建模可以建模成 memorizedThings::get (这个闭包引用了 (Array<Object>)this, this 包括了对所有元素的引用)。经典的计算机是面向存储、面向处理过程的,可是编程是面向对象(你也可以说是面向函数组合或者 continuation-passing-style, CPS)的,人的开发效率和机的执行速度,天生水火不容。
有个笑话说,冯·诺伊曼怒骂过程序员,“你怎么能用 assembler 呢?你知道它浪费了多少 CPU cycle 吗???”
鱼和熊掌不可得兼,所以要有权衡和取舍。曾经(比如 62 年前 1957, Fortran刚刚发明的时候)的时候,CPU们的速度还很慢,于是程序员就成了冤大头,不得不和一堆与机器过分相关的细节死肝,来描述自己的逻辑和计算。
因为那时候计算机的应用也就是那个『超算』『集群(cluster)』的程度,程序员也没有享受计算机周到服务的那个底气,机器的时间金贵啊!
21 世纪就不一样了,程序员不仅仅是『喜新厌旧』连 assembler 都看不上了,而且还用上了 compiler,甚至 virtual machine,这一个一个跑一秒钟都「浪费」 cycle 到能让老冯跪在地上哭啊!😭
可是程序员依然用得不亦乐乎,甚至还弄了 type checker, linter, inline docgen, sanitizer, code generator, build system, package manager,还IDE、自动补全、智能感知、浏览定位、代码分析,还测试全覆盖、DevOps、云计算。当然所有人也都是一样,因为计算机的算力上去了,不怕浪费一点宝贵的,应该拿去做科学计算的 CPU cycle 了。
如果能够避免悬垂指针或者说野指针(dangling pointer)、内存泄漏(memory leak),能够检测出指针溢出(pointer overflow)索引越界,其实由计算机处理更多工作也没什么,它闲嘛。
当然我这里不是说因为算力上去了你就可以不并行处理,编程时你就可以不做算法分析,不好好考虑怎么节省资源提高内存效率和执行速度。胡乱弄个纸张算法,这不是程序员该有的行为。
如果啥时候我们不需要记忆某些对象了,是不是就可以
free 掉他们对应的存储?之前我们说了
call...alloc...ret 的「栈帧本地变量」,虽然这是一种分配方式,可也是清除了不需要的东西(虽然初衷不大相似)。比如说,我们知道在 Java 里你只能访问静态、实例、局部变量(可能不准确,凑合着吧):
import static java.lang.System.out;
public class GcRoots { public GcRoots(){}
public void execute() {
Object cxk = new Object() {String toString() {return "蔡徐鲲";}};
out.println(cxk);
}
String rootChicken = "🐔太美。";
static String ROOT_emmm = "emmm...";
}
回收辣鸡就是对每个『对象』问一个问题:你有用么?
细化一点,就是在『某个时候』去问『我Boss的代码能够访问到你么?』,如果不能,『回收』这个对象。
当然对象也不一定得是所有的对象,比如,可以只是某个特定「区域」的对象。
这是要看时机的,比如
GcRoots#execute 执行完成之前,cxk指向的那个东西,它就是有用的然后 execute 返回,我们就拿不到
new Object(){...} 的『蔡徐鲲』了,但它的分配还在,没消失!如果啥都不做,『蔡徐鲲』就这么『泄漏(leak)』了,因为我们无法再见到它,它却偷偷躲在『片场』(内存池) 的某个角落里
所以调用后的任何时候,我们问这三个对象(藏在
Object 引用后的):对象
rootChicken有用么?有用,因为我们为了调用 execute() 初始化了一个 GcRoots() 实例GcRoots play = new GcRoots();一个
play.execute();
cook(play.rootChicken);
this 存在时它的所有 field 都是有用的,因为它们可能通过这个 this 被访问。(当然其实也是没有用的 (
new GcRoots().execute()),有句话说得好,CLR 里一个对象可能在 constructor 被调用的时候,就已经 Finalize 了,这里为了保证准确性我刻意弄了个 cook 不是死代码)对象
ROOT_emmm有用么?它当然是有用的。实际上,类 GcRoots 被加载后的任何时候它都可能被访问,因为它是 GcRoots.ROOT_emmm。(所以这种会被放在 HotSpot JVM 的永久代或常量区,当然也有人叫方法区)
对象
cxk有用么?它已经没用了,所以它的分配可以被『回收』,接着用了。我们刚才做的简单算法一般叫『标记-清除(mark-sweep)』算法,它也是 1958 年 Lisp 实现的第一个自动内存管理算法。
它是通过追踪调用栈(就是所有的『动态』变量)上的所有帧本地变量,BFS(广度优先搜索) 标记它们所依赖的对象做到的,换句话说,是为了保留根对象而搜索必须留下的对象、回收不必留的对象
为什么不直接搜索不必留的对象?看看上面的『苏格拉底的问题』…… 数学逻辑上的证明找数学家吧。
实现的细节有 bitmap marking (为 Unix-like 进程 CoW, copy-on-write 优化的).
不过这样不是不能优化,想想一个对象的依赖关系图 — 一个 Node 指向很多其他 Node,有些东西 — 我们称为 primitive,比如 int, float, double 这些 — 是图里最后的顶点
Object x = 1, y = 2, z = 3; // 你需要在 Java 1.5 以上编译,autoboxing。
Object a = new Object[] { x, y, z };
Object b = new Object[] { x, y }; 我们的问题是,假设有一个过程引用了
a,在结束时我们怎么能知道 a 该不该被回收?首先我们想,
a作为「过程本身的局部变量」是一个「需求处」,但a依赖的对象不是它的「需求处」a 创建的时候就是作为某种需求处被依赖的,所以它有 1 个依赖然后某个依赖处消失,a 还是(递归解除引用关系) x, y, z 的依赖数目都减1,为0时就可以回收,这就是 Rc(引用计数) 算法。
Rc 相对于 tracing 是一种『概括性』的算法,因为它不从GC roots追踪实际引用,只是(有损失地)概括为某对象的被引次数。
Python和PHP 好像默认都是 Rc,不过他们是不会泄漏循环引用的,即便他们没有
java.lang.ref.WeakReference<T>. 也没 template<class T> class weak_ptr;, 据说这是因为他们有特殊的 GC module 处理。欸我还有事的,怎么讲起这些不懂的领域了…… 😫
算了,这里我提及一些名词,请大家自己发动手指找资料……
Common-Language-Runtime(CLR), Mono project
弱代假说(weak-generation hypothesis)、分代垃圾回收
Exact memory management, pointer-type
Semi-space algorithm, Eden Heap, coping-GC, compat-GC
stop-the-world, incremental-GC, tri-color GC, GC write barrier
harmony_gc_source.pdf
停,这个 Harmony 不是华为的『鸿蒙操作系统』,是 Apache Haromny,一个曾经确实是不负众望过但是又因为 Oracle 的打压弄得 Java 世界都支离破碎的项目,当然这不怪它,全赖那个不思进取心胸狭隘的 Oracle。
duangsuse Throws
— 既然我都谈到 JVM 了,那我就再科普一些 GC 的基本理念,顺路推隔壁 USTC 的公开资料(虽然我没时间看了) (好像没有公开资料了?) garbage-collector(GC) 呢…… 就是自动内存管理,有条件的可以了解一下 boehm gc 什么的,比较知名 GC 就是让人把存储视作对象的东西,有时候我们需要这么做: Object[] memorizedThings = new Object[] {john, monkey, apple, grape, banana}; 当然,以上例子按照面向对象封装建模可以建模成…
不少知识和信息,除了从书上看到我还从其他爱好者的资料里看到。
USTC ce 系学生的一些分享不知道为什么不见了,我很遗憾,因为那些资料也都很方便。
不过我给大家一个建议:比起直接从理解『解决方式』来理解问题,更应该从理解问题本身来理解问题的解决方式。
对任何复用库的开发者而言,设计时要以使用者的角度思考;对任何使用者而言,想理解问题要先自己设计一个问题的解决方案,然后从编写者的视角再看别人的解决方案。
或许用户的思维是幼稚的,可你不必总当用户。当你实践理论的时候,它们才真正到了你的脑子里。
我也相信,先理解问题还是先理解解法,是创造与重复之间最根本上的鸿沟。
USTC ce 系学生的一些分享不知道为什么不见了,我很遗憾,因为那些资料也都很方便。
不过我给大家一个建议:比起直接从理解『解决方式』来理解问题,更应该从理解问题本身来理解问题的解决方式。
对任何复用库的开发者而言,设计时要以使用者的角度思考;对任何使用者而言,想理解问题要先自己设计一个问题的解决方案,然后从编写者的视角再看别人的解决方案。
或许用户的思维是幼稚的,可你不必总当用户。当你实践理论的时候,它们才真正到了你的脑子里。
如果你对知识进行了彻底的分析和思考,且你脑海中生成的概念已经与生硬的文本之间没有很强的相似性,我们就认为这个知识是被理解的。(大意)据说这是冰封哥的一个朋友说的。emmm……
彻底的分析和非平凡的变换,是获得真知的标志性特征。
我也相信,先理解问题还是先理解解法,是创造与重复之间最根本上的鸿沟。
GitHub
USTC-Resource/USTC-Course
:heart:中国科学技术大学课程资源. Contribute to USTC-Resource/USTC-Course development by creating an account on GitHub.
Forwarded from 永久封存 | Yuuta 台 | 😷 #Pray4Wuhan (Yuuta ⠀)
Twitter
轨道kidou
(图片来自网络)呕
现在 #Telegram 也越来越萧条了, @LetITFlyW 好像都不播消息了,很多事情也在变, @Trumeet 感觉也很久没有写什么新东西了……
只是感觉…… 🤦🏻♂️
还好我不常上也没事,常上现在也不如以前有趣了
只是感觉…… 🤦🏻♂️
还好我不常上也没事,常上现在也不如以前有趣了
《告研发员工书》
此文写得何等好啊!希望研发及海外代表处的员工学习一下。你们都是成人了,要学会自立、自理。我们是以客户为中心,怎么行政系统出来一个莫名其妙的员工满意度,谁发明的。员工他要不满意,你怎么办呢?现在满意,过两年标准又提高了,又不满意了,你又怎么办?满意的钱从什么地方来,他的信用卡交给你了吗。正确的做法是,我们多辛苦一些,让客户满意,有了以后的合同,就有了钱,我们就能活下去。员工应多贡献,以提高收入,改善生活。我们的一些干部处于幼稚状态,没有工作能力,习惯将矛盾转给公司,这些干部不成熟,应调整他们的岗位。海外伙食委员会不是民意机构,而是责任机构,要自己负起责任来的,而不是负起指责来。国内后勤部门要依照市场规律管理,放开价格,管制质量。全体员工不要把后勤服务作为宣泄的地方,确实不舒服要找心理咨询机构,或者天涯网。
「任总批示」
—
『华为一个新员工,北大毕业,刚到华为时,就公司的经营战略问题,洋洋洒洒写了一封"万言书"给任正非,原本以为自己独到的见地能够打动领导,结果任正非批复:"此人如果有精神病,建议送医院治疗,如果没病,建议辞退"。』
此文写得何等好啊!希望研发及海外代表处的员工学习一下。你们都是成人了,要学会自立、自理。我们是以客户为中心,怎么行政系统出来一个莫名其妙的员工满意度,谁发明的。员工他要不满意,你怎么办呢?现在满意,过两年标准又提高了,又不满意了,你又怎么办?满意的钱从什么地方来,他的信用卡交给你了吗。正确的做法是,我们多辛苦一些,让客户满意,有了以后的合同,就有了钱,我们就能活下去。员工应多贡献,以提高收入,改善生活。我们的一些干部处于幼稚状态,没有工作能力,习惯将矛盾转给公司,这些干部不成熟,应调整他们的岗位。海外伙食委员会不是民意机构,而是责任机构,要自己负起责任来的,而不是负起指责来。国内后勤部门要依照市场规律管理,放开价格,管制质量。全体员工不要把后勤服务作为宣泄的地方,确实不舒服要找心理咨询机构,或者天涯网。
「任总批示」
—
『华为一个新员工,北大毕业,刚到华为时,就公司的经营战略问题,洋洋洒洒写了一封"万言书"给任正非,原本以为自己独到的见地能够打动领导,结果任正非批复:"此人如果有精神病,建议送医院治疗,如果没病,建议辞退"。』
GitHub
evil-huawei/events/华为四大名著 at master · evil-huawei/evil-huawei
Evil Huawei - 华为作过的恶. Contribute to evil-huawei/evil-huawei development by creating an account on GitHub.
刚看到之前收集的那些蛤为 OpenArkCompiler(方舟) 的描述,我到觉得没什么了
只是我真的讨厌这种事不做先吹得天花乱坠的,虽然我以前也是这样的,但华为不该这样,更不该老搞政治迫害不干实事。 #Huawei
一个事情做完之前,说得再怎么样又如何?到底还是不能用的
只是我真的讨厌这种事不做先吹得天花乱坠的,虽然我以前也是这样的,但华为不该这样,更不该老搞政治迫害不干实事。 #Huawei
一个事情做完之前,说得再怎么样又如何?到底还是不能用的
Forwarded from duangsuse::Echo (LetITFly 让技术飞)
https://t.me/dsuset/6708
LetITFly 在这里说一句:我的频道没有弃坑停更的计划。😏
LetITFly 在这里说一句:我的频道没有弃坑停更的计划。😏
Telegram
duangsuse Throws
现在 #Telegram 也越来越萧条了, @LetITFlyW 好像都不播消息了,很多事情也在变, @Trumeet 感觉也很久没有写什么新东西了……
只是感觉…… 🤦🏻♂️
还好我不常上也没事,常上现在也不如以前有趣了
只是感觉…… 🤦🏻♂️
还好我不常上也没事,常上现在也不如以前有趣了