0%

思路

参考资料中说的很详细了,利用的是 Markdown Preview Enhanced: Extend Parser功能,在预览时将hexo特有的语法转换为markdown语法,参考资料给的代码片段如下:

1
2
3
4
5
6
7
8
9
onWillParseMarkdown: function(markdown) {
return new Promise((resolve, reject)=> {
markdown = markdown.replace(
/\{%\s*asset_img\s*(.*)\s*%\}/g,
(whole, content) => (`![](${content})`)
)
return resolve(markdown)
})
},

在实际测试时发现存在如下两个问题:

  1. 正则表达式不准确,不能适配完整的asset_img语法
  2. 图片位于和文档同名目录下面,生成的新的markdown语法没有包含前缀路径

本人对vscode和js均不熟悉,经过一番搜索,修改后的代码片段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
onWillParseMarkdown: function(markdown) {
return new Promise((resolve, reject)=> {
markdown = markdown.replace(
/\{%\s*asset_img\s*(\S+)\s*\S*\s*%\}/g,
(whole, content) => {
//(`![](${content})`)
//console.log("test--" + content);
abs_filename = vscode.window.activeTextEditor.document.fileName
filename = path.basename(abs_filename);
filename = filename.substring(0,filename.indexOf('.'))
//console.log("test--" + filename);

return `![](${filename + "/"+ content})`;
}
)
return resolve(markdown)
})
},

参考资料

概述

随着业务的发展,源码组织的方式、仓库分支模型、版本发布流程也需要不停的演进以便适应当前业务需要。本文档是搜集相关的资料并加以总结。
不要寄希望于万能的模型实践,每个模型都有各自的优缺点,要根据自己的实际情况选择。

仓库组织

单仓库

将所有项目代码存放在一个代码仓库当中,这个好处在于项目的所有开发者可以共享看到项目中的所有代码; 在项目规模较小的时候,一个库可以更好地管理和维护,发版本只要统一发布即可;对于持续集成,也只需要针对一个库维护若干条流水线。但再好的实践以及工具都有它适用的范围。Git 已经是非常流行的代码托管工具,但 Git 会把所有历史记录以及代码同步到各个用户的本地机器,所以对于大型项目而言,如果使用单仓库,就意味着某个模块开发者的本地可能有大量冗余代码和提交记录的信息,这个时候拆分成更小的库显得更加合适。

谷歌与 Facebook 就是业界典型的单仓库派代表。作为代码行数已经超过数十亿行、commit 数量累计达到千万次的团队(2015 年的统计数据),如果没有强悍的基础设施,也很难运转顺利。Google 曾发表论文介绍其强大的代码管理系统 Piper 以及客户端工具 CitC,但对于大部分企业来说是否有必要投入如此之大的研发成本去自研一个代码管理系统值得商榷,所以谷歌的实践对于大部分企业来说不一定具备参考性。

项目规模小时一般都是单仓库,但项目规模庞大时,如果再使用单仓库则要有完善的工具链支持。

多仓库

将项目代码进行一定的拆分放在多个库当中,好处就是 将代码进行一定的解耦,对于体型较为庞大的项目来说管理上会更加清晰和富有弹性。将代码按照一定逻辑分库之后,仓库与模块有了自描述的特征,让一起协作的开发者可以一目了然。发布源码版本、持续集成构建时,负责各仓库的研发组织可以按照自己的节奏来发布,同时将一些“坏代码”的影响控制在某个仓库中,而不会影响项目全部代码。分库也有要注意的地方,在同一个项目里的代码多多少少都有业务上或者是技术上的联系,比如编译依赖:以一个Java 项目为例,客户端接口的调用代码究竟是直接依赖服务端接口代码的定义,还是间接依赖?如果是间接依赖,那么分库管理是非常方便的,但同时客户端就无法快速感知到服务端接口定义的变化。所以在进行多仓库划分时,要注意划分的一些常用原则。

多仓库情况下,要仔细处理项目多组件之间的依赖关系并能及时检测到依赖变更和不兼容升级,可以通过语义化版本号和依赖管理工具来维护

分支模型

只讨论基于git的分支模型,常见的有如下几种,详细介绍见参考资料

  • GitFlow模型
  • GitHub Flow 模型
  • Trunk Based development 模型 (配合Branch By Abstraction使用)
  • GitLab Flow 模型
  • Atlassian Simple Git Flow 模型

在上面的模型介绍中,TBD模型支持多个不兼容版本维护,其余的模型未看到如何支持多个不兼容版本的并行维护。

版本发布

选用了仓库模型和分支模型,基本就确定了版本发布模型。

组件化

在源码管理上可以参考安卓、IOS的源码管理变迁,因为安卓、IOS需求多变,承载的业务复杂,其演进的轨迹具有借鉴意义。

参考资料

生活终究是复杂的,具体的。罕有完美无缺的英雄,也难有十恶不赦的坏蛋。更普遍的情况是,英雄可能在某些场合私欲膨胀,而坏蛋也可能在某些时候良心发现。
窥见英雄的阴暗面,由此剧烈转向,相信“人间不值得”是一种选择,但未必是必然的选择,因为由此理解人性的复杂,明白要始终做个好人并不容易,也是一种选择。
–源自网络

概念

SMP,NUMA,MPP

SMP(Symmetric Multi-Processor)

SMP(对称多处理系统), 所谓对称多处理器结构,是指服务器中多个 CPU 对称工作,无主次或从属关系。各 CPU 共享相同的物理内存,每个 CPU 访问内存中的任何地址所需时间是相同的,因此 SMP 也被称为一致存储器访问结构 (UMA : Uniform Memory Access) 。对 SMP 服务器进行扩展的方式包括增加内存、使用更快的 CPU 、增加 CPU 、扩充 I/O( 槽口数与总线数 ) 以及添加更多的外部设备 ( 通常是磁盘存储 ) 。

SMP 服务器的主要特征是共享,系统中所有资源 (CPU 、内存、 I/O 等 ) 都是共享的。也正是由于这种特征,导致了 SMP 服务器的主要问题,那就是它的扩展能力非常有限。对于 SMP 服务器而言,每一个共享的环节都可能造成 SMP 服务器扩展时的瓶颈,而最受限制的则是内存。由于每个 CPU 必须通过相同的内存总线访问相同的内存资源,因此随着 CPU 数量的增加,内存访问冲突将迅速增加,最终会造成 CPU 资源的浪费,使 CPU 性能的有效性大大降低。实验证明, SMP 服务器 CPU 利用率最好的情况是 2 至 4 个 CPU 。

阅读全文 »

年少轻狂的时候,以自我为中心,总是认为可以改变一切。
等接受几年社会的毒打,会逐渐回归现实,见过形形色色的人和事之后,也会感慨,自己一辈子努力的终点也许都赶不上别人的起点。
会怨天尤人,怼天怼地怼空气,也会幻想突然获得主角光环,从此一路开挂,但也会再挣扎下,努力前行。
如果说人生1/3过去了有什么收获,那就是学会了接受自己,接受自己就是普通人,一个路人甲的设定,各方面都是中规中矩的。
我们登上并非我们所选择的舞台,演绎并非我们所选择的剧本,偶尔埋怨为什么舞台不够大,剧本不够好,但更多的时候还是去思考如何去演好。

以前更多的是想我想要什么,为什么不给我,转变为我如何做,我向别人提供什么才能匹配到更好的资源。

在目前的网络中,为了获得流量,充斥着虚假的信息,为了做出有效的决策,我们必须对获取的信息质量进行评估。

  • 尽可能看原始来源
    信息传递过程中会失真(未必是故意的),所以要寻找信息的原始来源做确认。
  • 尽可能从不同的视角了解同一个消息
    屁股决定脑袋,不同的人/信息源/媒介有不同立场,不同的价值观,在传递信息的过程中有可能只保留了一个视角的信息(再次强调,未必是故意的)。
  • 区分事实和观点
    事实是一种客观存在,你可以可验证其真实存在与否;观点是个人看法,你可以同意或者不同意一个观点,但是你不能证明或者证伪一个观点的存在。要基于事实做出自己的观点,评估他人的观点,而不是忽视事实,直接采用他人的观点
  • 理解概率
    当前的信息未必能得出明确的结论,但可以依据概率获取一个可能的结论,并随着信息的增加修改完善/推翻这个结论。概率不能保证处理的一定对,但放到一个大的时间尺度下,能保证你大部分时候是对的。
  • 严谨的思路
    不要被带节奏,要能独立自主的思考做决策
  • 对信息源建立自己的分级体系
    不是所有的信息源都是同等有价值的,有的信息源更可信,要建立自己的分级体系并动态调整

还有一点,即使是权威的信息源,也会有自己的立场,当评估时,一定要考虑到信息源本身的立场和信息的价值是否冲突。

原始来源

逼近真相:在虚假和半真半假中的生存指南
斯坦索姆的故事
疫情之下,提高一点个人信息素养

学习的过程

回顾这几年的求索之路,除了一开始的迷糊之外,后续基本遵循着下面一个循环

  1. 提出问题
    首先要提出一个明确的问题,可以是因工作需要提出,也可以因个人进修需要拟定的。
  2. 搜集资料
    根据提出的问题检索资料。检索到的资料会先读一遍,如果觉得好就搜集起来。通过阅读资料会建立起来一个知识的轮廓,随着阅读的增多,知识的面貌会越来越清晰,直到感觉自己搞懂了。
    搜集资料这块可以使用中文了解轮廓,但真正深入的技术问题,要真正的搞明白,还是要读英文资料。
  3. 消化吸收
    这个步骤和搜集资料是重叠的、交互进行的。随着对知识理解的加深,需要搜集更多的资料来学习。
  4. 整理输出
    到此阶段,自己觉得自己已经掌握了这块知识,也可能没有真正的掌握,只是感觉掌握了。通过整理资料,组织逻辑关系,能用自己的话表达出来才算是真正的理解。
  5. 资料归档
    针对以前搜集的资料,结合现有的理解,剔除糟粕、重复的,将相关资料归档,以便将来查阅。
阅读全文 »

理解了false share,解决办法就比较简单了,采用cache填充即可。现在的问题是随着代码量、协作人数变多,很难避免合入的代码没有false share问题,有没有什么工具可以有效的检测出false share.

资料归档

avoiding-and-identifying-false-sharing-among-threads
[c2c-blog][https://joemario.github.io/blog/2016/09/01/c2c-blog/]
cache-false-sharing-debug(中文资料,推荐)

cache-false-sharing-debug.pdf

译者注

原文

barriers:屏障, 本文档中指内存屏障
memory barriers: 内存屏障

指令重排序

基础不牢靠的程序员有一个错觉, 指令执行的顺序就是我所理解的代码编写的顺序。
在目前多核、多发射、乱序执行的今天,编译器、CPU都可以根据需要调整指令执行顺序,指令实际的执行顺序和代码的书写顺序不一定一致

可见性

在内存-多级缓存的今天,一定存在一个层次,在这个层次下,数据的变化是同步的,即所有CPU看到的都是相同的状态,任意一个CPU的修改其它CPU都能看到。在这个层次只上,每个CPU有自己独享的缓存,这些缓存对其它CPU是不可见的。内存屏障的目的是通知CPU让其将自己的缓存和共享的缓存/内存做一次同步,以便其它CPU可以感知到这些变化。

:内存屏障控制是本CPU独享缓存和共享缓存/内存的同步工作,而不关心和其它的CPU是否同步。如果其它CPU也想和共享内存同步下,需要自己来触发内存屏障。

阅读全文 »