#每日精进#2020年07月30日

zkbhj 发表了文章 • 0 个评论 • 1391 次浏览 • 2020-07-30 08:34 • 来自相关话题

 
【早读:《深入理解计算机系统》】

第一章 计算机系统漫游

hello程序运行过程:

1、键盘输入"./hello"后,shell程序将字符逐一读入寄存器,再把它们存放到主存中;
2、敲击回车,shell就知道我们已经输入结束了,然后shell会执行一系列指令,将hello程序中的代码和数据从磁盘复制到主存。这其中利用了直接存储器存取(DMA),数据直接通过总线从磁盘进入主存中,不会经过处理器;
3、代码和数据加载完毕之后,处理器就开始执行hello程序的main程序中的机器语言指令,将数据(hello,world\n)字符串中的字符从主存中复制到寄存器文件中,再从寄存器文件中复制到显示器设备,最终显示出结果。


高速缓存的重要性:上面的执行过程,我们就可以发现,系统花费了大量的时间把信息从一个地方移动到另一个地方!这些复制都是巨大的开销,减慢了程序”真正“的工作。因此,系统设计者通过让”存储设备形成层次结构”来提供速度,尽可能让这些复制操作能够尽快完成。






存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。

L1、L2、L3这些更小更快的存储设备,称为高速缓存存储器(cache memory,简称cache或高速缓存)。高速缓存是用一种叫做静态随机访问存储器(SRAM)的硬件技术实现的。

高速缓存之所以能加快访问速度,从而提高系统整体的效率,是利用了高速缓存的局部性原理:即程序具有访问局部区域里的数据和代码的趋势。通过让高速缓存里存放可能经常访问的数据,大部分的内存操作都能在高速缓存中快速完成。

操作系统管理硬件

应用程序并不能直接跟硬件“打交道”,而是要通过“操作系统”这一“中间商”提供的服务来和硬件进行交流。

操作系统有2个基本功能:
防止硬件被失控的应用程序滥用;向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。
 
操作系统通过以下三个抽象概念来实现上述2个功能:
文件:是对I/O设备的抽象表示;虚拟内存:是对主存和磁盘I/O设备的抽象表示;进程:是对处理器、主存和磁盘I/O设备的抽象表示。Posix标准是IEEE组织为了组织Unix越来越混乱,越来越不标准化而制定的标准化Unix开发提出来的一套标准规范。
 
 
【爱英语Show】
 
开电脑,关电脑不能用Open the computer 和 Close the computer!这两个表达方式的意思是 拆开/关上的意思。
正确的表达方式应该是 Turn on the computer 和 Turn off the computer!
另外,打开/关闭电脑中的文件,可以说 Open the file 或者 Close the file。
 

【高次方程】
 
今天中午在读紫金陈的《无证之罪》时,严良给赵铁民分析案情时提到,这个案子不能用常规的方法。普通的案子,可以根据线索通过“推论”算出来“嫌疑人”,就像是方程,可以通过公式计算出结果。但是这个案子,要用对应“高次方程”的求解方法来分析:那就是先确定结果,再代入方程中进行论证。也就是先确定嫌疑人,然后代入案情中推论。
 
严良提到的“高次方程”其实指的是次数大于等于5的方程,这类方程有一个特点: 高于5次(大于等于5)的方程没有精确代数解(这个定理已经被证明)。 这种方程只能通过数值计算的方法,用数值逼近求近似解。
 
埃瓦里斯特·伽罗瓦,用群论系统化地阐述了五次及五次以上方程不能用公式求解。
 
【今日放学别走】

今天的放学别走部门同学一起Review了近期完成的筛选项后台管理系统的项目代码,项目使用了Gin框架,其中有一个配置文件格式是以前没有接触过的,是Toml。之前一直接触过的有yaml、json、ini之类的,这个今天还是第一次听,大概了解了下一个配置文件的相关内容。

GitHub觉得 YAML 不够简洁优雅,因此捣鼓出了一个TOML。TOML的全称是 Tom’s Obvious, Minimal Language,因为它的作者是 GitHub联合创始人Tom Preston-Werner 。

TOML 的目标是成为一个极简的配置文件格式。TOML 被设计成可以无歧义地被映射为哈希表,从而被多种语言解析。

是大小写敏感的。

可能是目前最好的配置文件格式。详细可以点击了解:
https://blog.csdn.net/john_f_lau/article/details/55803069
 
【Go语言核心36讲:第9节 字典的操作和约束】

Go 语言的字典类型(Map)其实是一个哈希表(hash table)的特定实现,在这个实现中,键和元素的最大不同在于,键的类型是受限的,而元素却可以是任意类型的。之所以会受限,是因为哈希表中的一个重要过程:映射。

映射过程的第一步就是:把键值转换为哈希值。

Go 语言规范规定,键类型的值必须要支持判等操作,所以字典的键类型不可以是函数类型、字典类型和切片类型。

应该优先考虑哪些类型作为字典的键类型?求哈希和判等操作的速度越快,对应的类型就越适合作为键类型。优先选用数值类型和指针类型,通常情况下类型的宽度越小越好。如果非要选择字符串类型的话,最好对键值的长度进行额外的约束。

除了添加键 - 元素对,我们在一个值为nil的字典上做任何操作都不会引起错误。当我们试图在一个值为nil的字典中添加键 - 元素对的时候,Go 语言的运行时系统就会立即抛出一个 panic。

永远要注意那些可能引发 panic 的操作,比如像一个值为nil的字典添加键 - 元素对。 查看全部

 
【早读:《深入理解计算机系统》】

第一章 计算机系统漫游

hello程序运行过程:


1、键盘输入"./hello"后,shell程序将字符逐一读入寄存器,再把它们存放到主存中;
2、敲击回车,shell就知道我们已经输入结束了,然后shell会执行一系列指令,将hello程序中的代码和数据从磁盘复制到主存。这其中利用了直接存储器存取(DMA),数据直接通过总线从磁盘进入主存中,不会经过处理器;
3、代码和数据加载完毕之后,处理器就开始执行hello程序的main程序中的机器语言指令,将数据(hello,world\n)字符串中的字符从主存中复制到寄存器文件中,再从寄存器文件中复制到显示器设备,最终显示出结果。



高速缓存的重要性:上面的执行过程,我们就可以发现,系统花费了大量的时间把信息从一个地方移动到另一个地方!这些复制都是巨大的开销,减慢了程序”真正“的工作。因此,系统设计者通过让”存储设备形成层次结构”来提供速度,尽可能让这些复制操作能够尽快完成。

timg.jpeg


存储器层次结构的主要思想是上一层的存储器作为低一层存储器的高速缓存。

L1、L2、L3这些更小更快的存储设备,称为高速缓存存储器(cache memory,简称cache或高速缓存)。高速缓存是用一种叫做静态随机访问存储器(SRAM)的硬件技术实现的。

高速缓存之所以能加快访问速度,从而提高系统整体的效率,是利用了高速缓存的局部性原理:即程序具有访问局部区域里的数据和代码的趋势。通过让高速缓存里存放可能经常访问的数据,大部分的内存操作都能在高速缓存中快速完成。

操作系统管理硬件

应用程序并不能直接跟硬件“打交道”,而是要通过“操作系统”这一“中间商”提供的服务来和硬件进行交流。

操作系统有2个基本功能:
  1. 防止硬件被失控的应用程序滥用;
  2. 向应用程序提供简单一致的机制来控制复杂而又通常大不相同的低级硬件设备。

 
操作系统通过以下三个抽象概念来实现上述2个功能:
  • 文件:是对I/O设备的抽象表示;
  • 虚拟内存:是对主存和磁盘I/O设备的抽象表示;
  • 进程:是对处理器、主存和磁盘I/O设备的抽象表示。Posix标准是IEEE组织为了组织Unix越来越混乱,越来越不标准化而制定的标准化Unix开发提出来的一套标准规范。

 
 
【爱英语Show】
 
开电脑,关电脑不能用Open the computer 和 Close the computer!这两个表达方式的意思是 拆开/关上的意思。
正确的表达方式应该是 Turn on the computer 和 Turn off the computer!
另外,打开/关闭电脑中的文件,可以说 Open the file 或者 Close the file。
 

【高次方程】
 
今天中午在读紫金陈的《无证之罪》时,严良给赵铁民分析案情时提到,这个案子不能用常规的方法。普通的案子,可以根据线索通过“推论”算出来“嫌疑人”,就像是方程,可以通过公式计算出结果。但是这个案子,要用对应“高次方程”的求解方法来分析:那就是先确定结果,再代入方程中进行论证。也就是先确定嫌疑人,然后代入案情中推论。
 
严良提到的“高次方程”其实指的是次数大于等于5的方程,这类方程有一个特点: 高于5次(大于等于5)的方程没有精确代数解(这个定理已经被证明)。 这种方程只能通过数值计算的方法,用数值逼近求近似解
 
埃瓦里斯特·伽罗瓦,用群论系统化地阐述了五次及五次以上方程不能用公式求解
 
【今日放学别走】

今天的放学别走部门同学一起Review了近期完成的筛选项后台管理系统的项目代码,项目使用了Gin框架,其中有一个配置文件格式是以前没有接触过的,是Toml。之前一直接触过的有yaml、json、ini之类的,这个今天还是第一次听,大概了解了下一个配置文件的相关内容。

GitHub觉得 YAML 不够简洁优雅,因此捣鼓出了一个TOML。TOML的全称是 Tom’s Obvious, Minimal Language,因为它的作者是 GitHub联合创始人Tom Preston-Werner 。

TOML 的目标是成为一个极简的配置文件格式。TOML 被设计成可以无歧义地被映射为哈希表,从而被多种语言解析。

是大小写敏感的。

可能是目前最好的配置文件格式。详细可以点击了解:
https://blog.csdn.net/john_f_lau/article/details/55803069
 
【Go语言核心36讲:第9节 字典的操作和约束】

Go 语言的字典类型(Map)其实是一个哈希表(hash table)的特定实现,在这个实现中,键和元素的最大不同在于,键的类型是受限的,而元素却可以是任意类型的。之所以会受限,是因为哈希表中的一个重要过程:映射。

映射过程的第一步就是:把键值转换为哈希值。

Go 语言规范规定,键类型的值必须要支持判等操作,所以字典的键类型不可以是函数类型、字典类型和切片类型。

应该优先考虑哪些类型作为字典的键类型?求哈希和判等操作的速度越快,对应的类型就越适合作为键类型。优先选用数值类型和指针类型,通常情况下类型的宽度越小越好。如果非要选择字符串类型的话,最好对键值的长度进行额外的约束。

除了添加键 - 元素对,我们在一个值为nil的字典上做任何操作都不会引起错误。当我们试图在一个值为nil的字典中添加键 - 元素对的时候,Go 语言的运行时系统就会立即抛出一个 panic。

永远要注意那些可能引发 panic 的操作,比如像一个值为nil的字典添加键 - 元素对。

#每日精进#2020年7月29日

zkbhj 发表了文章 • 0 个评论 • 1328 次浏览 • 2020-07-29 09:29 • 来自相关话题

【早读:《深入理解计算机系统》】

第一章 计算机系统漫游

1、了解编译系统是如何工作的有以下优势: 
优化程序性能:了解编译系统将不同的C代码转化为机器代码的方式,比如一个switch是否总是比if-else更高效?一个函数调用的开销有多大等;理解链接时出现的错误:静态变量和全局变量的区别是什么;避免安全漏洞:缓冲区溢出错误一直都是安全漏洞的主要原因。需要限制从不受信任的源接收数据的数量和格式。


2、shell是一个命令行解释器,它输出一个提示符,然后等待输入一个命令行,然后执行这个命令。首先第一个单词如果是内置的shell命令(如cat、top之类的内置命令),那么shell会假设只是一个可执行文件的名字,进而加载并运行它,将输出信息显示到屏幕上。然后换行输出提示符,等待下一个命令行输入。

系统的硬件组成如下图所示:






总线:贯穿整个系统的一组电子管道,被设计成传递定长的字节块(字word),字长(字中的字节数)是一个基本的系统参数,比如4个字节(32位)或8个字节(64位);

I/O设备:系统与外部世界联系的通道。图示里有4个I/O设备:输入的键盘鼠标,输出的显示器,长期存储数据的磁盘驱动器;I/O设备通过一个控制器或者适配器与I/O总线相连。控制器是设备本身或者主板上的芯片组,而适配器是插在主板插槽上的卡;

主存:一个临时存储设备,执行程序时存放程序和程序处理的数据。物理上是一组动态随机存取存储器(DRAM)。逻辑上是一个线性的字节数组,每个字节有唯一的地址,从0开始;

处理器:中央处理单元(CPU),是解释或执行存储在主存中指令的引擎。处理器的核心是一个大小为一个字的存储设备(寄存器),称为程序计数器(PC)。在通电之后的任何时刻,PC都指向主存中的某条机器语言指令。寄存器文件是一个小的存储设备,由一些单个字长的寄存器组成,都有唯一的名字。CPU可能会执行的操作有: 
加载:从主存复制一个字节或者一个字到寄存器,以覆盖原来的内容;存储:从寄存器复制一个字节或者一个字到主存的某个位置,覆盖原来的内容;操作:把两个寄存器内容复制到ALU,ALU对他们进行算数运算,将结果放到一个寄存器里,覆盖原来的内容跳转:从指令本身中抽取一个字,复制到程序计数器PC中,覆盖PC中原来的值;

实际上现代处理器使用了非常复杂的机制来加速程序执行(多核,寄存器缓存等)

【安全用药清单】 
安全保存药物的方法:药品能不开封就不开封,能买铝箔单片封存的,就别买整瓶包装;治疗方案有多种药物可选时,尽量选那种服用的注意事项比较少、吃起来比较方便的药,这样就能避免因未服用方法不当带来的风险;两种以上药物同时使用时,可能存在风险,可以咨询医院要放的药师进行药物重整;食物和药物混合使用,可能存在风险,尤其需要注意西柚、酒、咖啡、牛油果、黄豆;把父母常吃的药拍个照片,存在手机里,以备不时之需。
 
https://mp.weixin.qq.com/s/atZhbBMFyUOvGXy3YPncnA
 
【数据归一化】
 
今天被同事问到什么是归一化。只是以前听过,没有结构化了解过这个概念,今天查了一下,有了一个初级的认识和了解。
 
在物理学的定义上,归一化的解释是:

归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为标量。 在多种计算中都经常用到这种方法。

看到这个概念,就又牵扯到另外一个概念:量纲!量纲是物理学中的一个重要概念。可以定性地表示出导出量与基本量之间的关系。量纲指数都为0的物理量,称为无量纲量。
 
但是作为我们搜索推荐相关的实际应用场景,这里的归一化指的是:数据的标准化(normalization)和归一化!

数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间。在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。

目前数据标准化方法有多种,归结起来可以分为直线型方法(如极值法、标准差法)、折线型方法(如三折线法)、曲线型方法(如半正态性分布)。不同的标准化方法,对系统的评价结果会产生不同的影响,然而不幸的是,在数据标准化方法的选择上,还没有通用的法则可以遵循。

其中最典型的就是数据的归一化处理,即将数据统一映射到[0,1]区间上。

 
归一化的目标有2个:
把数变为(0,1)之间的小数。主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,更加便捷快速,应该归到数字信号处理范畴之内。把有量纲表达式变为无量纲表达式。
 
归一化后有两个好处,一是提升模型的收敛速度,二是提升模型的精度。
 
https://blog.csdn.net/pipisorry/article/details/52247379
https://www.zhihu.com/question/20467170
 
【今日开发小技巧】
 
今天同事在群里分享了2个提高Go语言代码质量,提前发现代码问题的小技巧:

build的时候,通过参数-race开启竞态检测,然后访问一下应用,就可以看到有哪些可能会出问题的点;
可以用https://staticcheck.io/ 这个在线代码检查工具做一个代码检查;

 【SVGA格式的“图片”】
 
今天在做社区项目写接口文档的时候,品牌图是要支持动画的,移动端开发说品牌图是否支持svga,查了一下才知道这个svga到底是哪路神仙?先看下官方介绍:

SVGA 是一种跨平台的开源动画格式,同时兼容 iOS / Android / Web。SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画交互的沟通成本,提升开发效率。动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 svga player 之后直接使用。动画开发从未如此简单!

SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画交互的沟通成本,提升开发效率。

动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 SVGAPlayer 之后直接使用。 
—— 来自官网svga.io


在开发APP的过程中,需要在APP中实现设计同学的UE效果动画,一般都是通过代码实现的,当对于较复杂的动画时,例如直播中刷礼物时的动画,这时利用代码实现会比较复杂。而且Android和iOS两端不好统一效果,如果用gif图片来实现的话,在图片大小和动画帧数之间很难权衡。而且会导致内存吃紧。为了解决这样的问题,实现复杂动画的开源库和SVGA应运而生,还有一个动画开源库Lottie。

对比和详细使用教程可以参考:
https://www.jianshu.com/p/60d28d7bab48​ 
 
【Go语言核心36讲:第8节 Container包中的那些容器】

Go 语言的链表实现在标准库的container/list代码包中。这个代码包中有两个公开的程序实体——List和Element,List 实现了一个双向链表(以下简称链表),而 Element 则代表了链表中元素的结构。
MoveBefore方法和MoveAfter方法,它们分别用于把给定的元素移动到另一个元素的前面和后面;
MoveToFront方法和MoveToBack方法,分别用于把给定的元素移动到链表的最前端和最后端;Front和Back方法分别用于获取链表中最前端和最后端的元素;InsertBefore和InsertAfter方法分别用于在指定的元素之前和之后插入新元素;PushFront和PushBack方法则分别用于在链表的最前端和最后端插入新元素;

在List包含的方法中,用于插入新元素的那些方法都只接受interface{}类型的值。这些方法在内部会使用Element值,包装接收到的新元素。

为什么链表可以做到开箱即用?

List和Element都是结构体类型。结构体类型有一个特点,那就是它们的零值都会是拥有特定结构,但是没有任何定制化内容的值,相当于一个空壳。值中的字段也都会被分别赋予各自类型的零值。var l list.List
上面声明的变量 l 的值是什么呢?

这个零值将会是一个长度为0的链表。
List这个结构体类型有两个字段,一个是Element类型的字段root,另一个是int类型的字段len。顾名思义,前者代表的就是那个根元素,而后者用于存储链表的长度。注意变量小写,所以是包级私有。len的零值是0,代表该链表未包含任何元素,root的零值是该类型的空格,字面量标识的话就是Element{}。

 关键在于它的“延迟初始化”机制。所谓的延迟初始化,你可以理解为把初始化操作延后,仅在实际需要的时候才进行。指针相等是链表已经初始化的充分必要条件。List的根元素永远不会持有任何实际的元素值,而该元素的存在就是为了连接这个循环链表的首尾两端。List的零值是一个只包含了根元素,但不包含任何实际元素值的空链表。

https://time.geekbang.org/column/intro/100013101  查看全部
QQ截图20200729092412.jpg

【早读:《深入理解计算机系统》】

第一章 计算机系统漫游

1、了解编译系统是如何工作的有以下优势: 
  • 优化程序性能:了解编译系统将不同的C代码转化为机器代码的方式,比如一个switch是否总是比if-else更高效?一个函数调用的开销有多大等;
  • 理解链接时出现的错误:静态变量和全局变量的区别是什么;
  • 避免安全漏洞:缓冲区溢出错误一直都是安全漏洞的主要原因。需要限制从不受信任的源接收数据的数量和格式。



2、shell是一个命令行解释器,它输出一个提示符,然后等待输入一个命令行,然后执行这个命令。首先第一个单词如果是内置的shell命令(如cat、top之类的内置命令),那么shell会假设只是一个可执行文件的名字,进而加载并运行它,将输出信息显示到屏幕上。然后换行输出提示符,等待下一个命令行输入。

系统的硬件组成如下图所示:

QQ截图20200729092547.jpg


总线:贯穿整个系统的一组电子管道,被设计成传递定长的字节块(字word),字长(字中的字节数)是一个基本的系统参数,比如4个字节(32位)或8个字节(64位);

I/O设备:系统与外部世界联系的通道。图示里有4个I/O设备:输入的键盘鼠标,输出的显示器,长期存储数据的磁盘驱动器;I/O设备通过一个控制器或者适配器与I/O总线相连。控制器是设备本身或者主板上的芯片组,而适配器是插在主板插槽上的卡;

主存:一个临时存储设备,执行程序时存放程序和程序处理的数据。物理上是一组动态随机存取存储器(DRAM)。逻辑上是一个线性的字节数组,每个字节有唯一的地址,从0开始;

处理器:中央处理单元(CPU),是解释或执行存储在主存中指令的引擎。处理器的核心是一个大小为一个字的存储设备(寄存器),称为程序计数器(PC)。在通电之后的任何时刻,PC都指向主存中的某条机器语言指令。寄存器文件是一个小的存储设备,由一些单个字长的寄存器组成,都有唯一的名字。CPU可能会执行的操作有: 
  1. 加载:从主存复制一个字节或者一个字到寄存器,以覆盖原来的内容;
  2. 存储:从寄存器复制一个字节或者一个字到主存的某个位置,覆盖原来的内容;
  3. 操作:把两个寄存器内容复制到ALU,ALU对他们进行算数运算,将结果放到一个寄存器里,覆盖原来的内容
  4. 跳转:从指令本身中抽取一个字,复制到程序计数器PC中,覆盖PC中原来的值;


实际上现代处理器使用了非常复杂的机制来加速程序执行(多核,寄存器缓存等)

【安全用药清单】 
  • 安全保存药物的方法:药品能不开封就不开封,能买铝箔单片封存的,就别买整瓶包装;
  • 治疗方案有多种药物可选时,尽量选那种服用的注意事项比较少、吃起来比较方便的药,这样就能避免因未服用方法不当带来的风险;
  • 两种以上药物同时使用时,可能存在风险,可以咨询医院要放的药师进行药物重整;
  • 食物和药物混合使用,可能存在风险,尤其需要注意西柚、酒、咖啡、牛油果、黄豆;
  • 把父母常吃的药拍个照片,存在手机里,以备不时之需。

 
https://mp.weixin.qq.com/s/atZhbBMFyUOvGXy3YPncnA
 
【数据归一化】
 
今天被同事问到什么是归一化。只是以前听过,没有结构化了解过这个概念,今天查了一下,有了一个初级的认识和了解。
 
在物理学的定义上,归一化的解释是:


归一化是一种简化计算的方式,即将有量纲的表达式,经过变换,化为无量纲的表达式,成为标量。 在多种计算中都经常用到这种方法。


看到这个概念,就又牵扯到另外一个概念:量纲!量纲是物理学中的一个重要概念。可以定性地表示出导出量与基本量之间的关系。量纲指数都为0的物理量,称为无量纲量。
 
但是作为我们搜索推荐相关的实际应用场景,这里的归一化指的是:数据的标准化(normalization)和归一化


数据的标准化(normalization)是将数据按比例缩放,使之落入一个小的特定区间。在某些比较和评价的指标处理中经常会用到,去除数据的单位限制,将其转化为无量纲的纯数值,便于不同单位或量级的指标能够进行比较和加权。

目前数据标准化方法有多种,归结起来可以分为直线型方法(如极值法、标准差法)、折线型方法(如三折线法)、曲线型方法(如半正态性分布)。不同的标准化方法,对系统的评价结果会产生不同的影响,然而不幸的是,在数据标准化方法的选择上,还没有通用的法则可以遵循。

其中最典型的就是数据的归一化处理,即将数据统一映射到[0,1]区间上


 
归一化的目标有2个:
  1. 把数变为(0,1)之间的小数。主要是为了数据处理方便提出来的,把数据映射到0~1范围之内处理,更加便捷快速,应该归到数字信号处理范畴之内。
  2. 把有量纲表达式变为无量纲表达式。

 
归一化后有两个好处,一是提升模型的收敛速度,二是提升模型的精度。
 
https://blog.csdn.net/pipisorry/article/details/52247379
https://www.zhihu.com/question/20467170
 
【今日开发小技巧】
 
今天同事在群里分享了2个提高Go语言代码质量,提前发现代码问题的小技巧:


build的时候,通过参数-race开启竞态检测,然后访问一下应用,就可以看到有哪些可能会出问题的点;
可以用https://staticcheck.io/ 这个在线代码检查工具做一个代码检查;


 【SVGA格式的“图片”】
 
今天在做社区项目写接口文档的时候,品牌图是要支持动画的,移动端开发说品牌图是否支持svga,查了一下才知道这个svga到底是哪路神仙?先看下官方介绍:


SVGA 是一种跨平台的开源动画格式同时兼容 iOS / Android / Web。SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画交互的沟通成本,提升开发效率。动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 svga player 之后直接使用。动画开发从未如此简单!

SVGA 除了使用简单,性能卓越,同时让动画开发分工明确,各自专注各自的领域,大大减少动画交互的沟通成本,提升开发效率。

动画设计师专注动画设计,通过工具输出 svga 动画文件,提供给开发工程师在集成 SVGAPlayer 之后直接使用。 
—— 来自官网svga.io



在开发APP的过程中,需要在APP中实现设计同学的UE效果动画,一般都是通过代码实现的,当对于较复杂的动画时,例如直播中刷礼物时的动画,这时利用代码实现会比较复杂。而且Android和iOS两端不好统一效果,如果用gif图片来实现的话,在图片大小和动画帧数之间很难权衡。而且会导致内存吃紧。为了解决这样的问题,实现复杂动画的开源库和SVGA应运而生,还有一个动画开源库Lottie。

对比和详细使用教程可以参考:
https://www.jianshu.com/p/60d28d7bab48​ 
 
【Go语言核心36讲:第8节 Container包中的那些容器】

Go 语言的链表实现在标准库的container/list代码包中。这个代码包中有两个公开的程序实体——List和Element,List 实现了一个双向链表(以下简称链表),而 Element 则代表了链表中元素的结构。
MoveBefore方法和MoveAfter方法,它们分别用于把给定的元素移动到另一个元素的前面和后面;
  • MoveToFront方法和MoveToBack方法,分别用于把给定的元素移动到链表的最前端和最后端;
  • Front和Back方法分别用于获取链表中最前端和最后端的元素;
  • InsertBefore和InsertAfter方法分别用于在指定的元素之前和之后插入新元素;
  • PushFront和PushBack方法则分别用于在链表的最前端和最后端插入新元素;


在List包含的方法中,用于插入新元素的那些方法都只接受interface{}类型的值。这些方法在内部会使用Element值,包装接收到的新元素。

为什么链表可以做到开箱即用?

List和Element都是结构体类型。结构体类型有一个特点,那就是它们的零值都会是拥有特定结构,但是没有任何定制化内容的值,相当于一个空壳。值中的字段也都会被分别赋予各自类型的零值。
var l list.List

上面声明的变量 l 的值是什么呢?


这个零值将会是一个长度为0的链表。
List这个结构体类型有两个字段,一个是Element类型的字段root,另一个是int类型的字段len。顾名思义,前者代表的就是那个根元素,而后者用于存储链表的长度。注意变量小写,所以是包级私有。len的零值是0,代表该链表未包含任何元素,root的零值是该类型的空格,字面量标识的话就是Element{}。


 关键在于它的“延迟初始化”机制。所谓的延迟初始化,你可以理解为把初始化操作延后,仅在实际需要的时候才进行。指针相等是链表已经初始化的充分必要条件。List的根元素永远不会持有任何实际的元素值,而该元素的存在就是为了连接这个循环链表的首尾两端。List的零值是一个只包含了根元素,但不包含任何实际元素值的空链表。

https://time.geekbang.org/column/intro/100013101 

#每日精进#2020年7月28日

zkbhj 发表了文章 • 0 个评论 • 1527 次浏览 • 2020-07-28 08:30 • 来自相关话题

开通微信公众号了,同学们可以关注:kiss-note。





 
【早读:《深入理解计算机系统》】
第一章 计算机系统漫游
计算机系统由硬件和系统软件组成;本书的目的是帮助你了解程序在系统上执行时,发生了什么以及为什么会这样;c的hello.c源程序开始,源程序实际上就是一个由值0和1组成的位序列,8个位为1组,称为字节,每个字节表示某些文本字符;像hello.c这样只由ASCII字符构成的文件称为文本文件,所有其他文件称为二进制文件;同样的字节序列可能表示不同的对象,唯一区分他们的办法是通过读取到这些数据对象时的上下文信息;C语言的起源:

贝尔实验室的Dennis Ritchie与1969年~1973年之间创建的,之后经历了ANSI C标准到现在的IOS标准。标准定义了C语言和一系列库函数(C标准库)。作者说C语言是“古怪的,有缺陷的,但同时也是一个巨大的成功”。
C语言与Unix操作系统关系密切。C从一开始就是作为一种用于Unix系统的程序语言开发出来的。Unix几乎全部使用C语言编写的;C语言 小而简单;C语言是为实践目的设计的。最初设计用来实现Unix操作系统,但是后来发现开发其他程序也很容易。
缺点:指针会造成困惑和麻烦。缺乏对抽象的显示支持,比如类、对象和异常。C++和Java解决了这些问题。

程序需要经过下面的命令,编译成低级机器语言指令才能被最终运行:
linux> gcc -o hello hello.c
编译系统由4个阶段的程序组成:预处理器(cpp)、编译器(ccl)、汇编器(as)、链接器(ld);

预处理阶段:根据#开头的命令,把包含进来的.h或者.c文件直接插入到相应位置,生成一个hello.i文件;
编译阶段:编译器将hello.i翻译成汇编语言程序,生成hello.s文件;
汇编阶段:汇编器将hello.s翻译成机器语言指令,把它们打包成一种可重定位目标程序,生成hello.o文件;
链接阶段:链接器将标准C库中的已经预编译好的.o文件(比如printf.o)以某种方式合并到我们的hello.o中,最终形成可执行文件hello。

汇编语言将不同的高级语言提供了通用的输出语言。相当于一个连接高级语言和机器语言的桥梁。
 
【成为一个优秀的人,可以从这些方面重点切入】
1、拥有强烈的好奇心:
你所能拥有的一切,都源自于探索;而探索的动力,都源自于好奇。正是因为这种好奇,驱动他们离开舒适区,获得更多新知识,不断拓展自己的边界。拥有好奇心的人,就像一块海绵。不断吸收新的知识,获得更大的成长。也因此,他们总是乐意接受更大的挑战。如果已经丢失了孩童时的好奇心,我们还能再捡起来吗?当然可以,当你对一件事情失去兴趣时,“我好奇如果我这么做了,会怎么样?”这么问自己!
 
2、面对不确定性,选择拥抱而不是怀疑:
人们厌恶不确定性,是因为厌恶不确定性背后巨大的风险。但是,不确定性背后,除了巨大的风险,也可能是巨大的收益。因为拥抱比怀疑,永远多一次机会。能成大事儿的人,在面对不确定性时,更容易选择拥抱,而不是怀疑。

3、相比赚钱,他们有更大的目标和想象力:
房子车子都只是附带品。最关键的是,我要不断成长,积累自己的价值,让自己变得稀缺,有能力去解决别人解决不了的问题。所以想要成大事儿,就要有更大的目标和想象力,专注于创造价值,而不是创造财富。
 
4、延迟满足,极度自律:
在这个世界上,要把一件事情做到极致,其实大部分时候都是很平淡,很枯燥的。延迟满足,能够让你在日复一日的枯燥中,不至于选择放弃。
 
5、不怕犯错,善于自省:
很多人不愿尝试做能力范围之外的事情,有一个原因是:害怕犯错。但其实只要不是什么致命错误,犯一些小错,反而是值得高兴的事。不怕犯错,善于自省,不断改进。这样的人,没有天花板。
 
希望我们都能不断成长为心目中那个,最好的自己。
https://mp.weixin.qq.com/s/9vGy6dc1vhBl58GA6F-ARw
 
【怎么理解美国关闭中国休斯顿使馆时间?本质是什么?】
说白了美方就是在故意找事。对美国好处很大,尤其对特朗普而言好处非常大。下面的视频很好的说明了这件政治事件。
https://player.youku.com/embed/XMTg5MDc5MzI3Ng==
对于这些在野党而言,今天的美国经济搞的再稀烂,那也是特朗普的锅。疫情越猛,经济越差,在野党越开心,当然要千方百计的破坏美国抗疫大局。
手段是合法的,用心是险恶的。所以不是特朗普不想消灭病毒,他是真的做不到。当然,特朗普也不是啥好货,他所有政治行为的唯一目的,也是为了选票和连任。其他一切东西,都没有这个重要,包括美国的未来。
这是人性,无关道德。
https://mp.weixin.qq.com/s/9m6Flh3X3wg9Xo-PJJzvuQ 
 
【Go语言核心36讲:第7节 数组与切片】
数组类型的值(以下简称数组)的长度是固定的(是其类型的一部分),而切片类型的值(以下简称切片)是可变长的。
我们其实可以把切片看做是对数组的一层简单的封装,因为在每个切片的底层数据结构中,一定会包含一个数组。数组可以被叫做切片的底层数组,而切片也可以被看作是对数组的某个连续片段的引用(所以Go 语言的切片类型属于引用类型)。
s3 := []int{1, 2, 3, 4, 5, 6, 7, 8}
s4 := s3[3:6]
fmt.Printf("The length of s4: %d\n", len(s4))
fmt.Printf("The capacity of s4: %d\n", cap(s4))
fmt.Printf("The value of s4: %d\n", s4)s3[3:6] 等同于数学表达式:[3, 6)。所以,s4的长度就是6-3=3。容量是从起始索引开始(无法向左扩展,只能从3开始,及0,1,2切片s4“看不到”),一直到“底层数组”最右端,所以,容量是 8-3=5。
 
切片容量如何增长?
它并不会改变原来的切片,而是会生成一个容量更大的切片,然后将把原有的元素和新元素一并拷贝到新切片中。在一般的情况下,你可以简单地认为新切片的容量(以下简称新容量)将会是原切片容量(以下简称原容量)的 2 倍。
但是,当原切片的长度(以下简称原长度)大于或等于1024时,Go 语言将会以原容量的1.25倍作为新容量的基准(以下新容量基准)。新容量基准会被调整(不断地与1.25相乘),直到结果不小于原长度与要追加的元素数量之和(以下简称新长度)。最终,新容量往往会比新长度大一些,当然,相等也是可能的。
另外,如果我们一次追加的元素过多,以至于使新长度比原容量的 2 倍还要大,那么新容量就会以新长度为基准。
 
切片的底层数组什么时候会被替换?
确切地说,一个切片的底层数组永远不会被替换。为什么?虽然在扩容的时候 Go 语言一定会生成新的底层数组,但是它也同时生成了新的切片。它只是把新的切片作为了新底层数组的窗口,而没有对原切片,及其底层数组做任何改动。请记住,
 
在无需扩容时,append函数返回的是指向原底层数组的新切片,而在需要扩容时,append函数返回的是指向新底层数组的新切片。
 
https://time.geekbang.org/column/intro/100013101
  查看全部
开通微信公众号了,同学们可以关注:kiss-note。

WX20200728-075634@2x.png

 
【早读:《深入理解计算机系统》】
第一章 计算机系统漫游
  • 计算机系统由硬件和系统软件组成;
  • 本书的目的是帮助你了解程序在系统上执行时,发生了什么以及为什么会这样;
  • c的hello.c源程序开始,源程序实际上就是一个由值0和1组成的位序列,8个位为1组,称为字节,每个字节表示某些文本字符;
  • 像hello.c这样只由ASCII字符构成的文件称为文本文件,所有其他文件称为二进制文件;
  • 同样的字节序列可能表示不同的对象,唯一区分他们的办法是通过读取到这些数据对象时的上下文信息;
  • C语言的起源:


贝尔实验室的Dennis Ritchie与1969年~1973年之间创建的,之后经历了ANSI C标准到现在的IOS标准。标准定义了C语言和一系列库函数(C标准库)。作者说C语言是“古怪的,有缺陷的,但同时也是一个巨大的成功”。

  1. C语言与Unix操作系统关系密切。C从一开始就是作为一种用于Unix系统的程序语言开发出来的。Unix几乎全部使用C语言编写的;
  2. C语言 小而简单;
  3. C语言是为实践目的设计的。最初设计用来实现Unix操作系统,但是后来发现开发其他程序也很容易。

缺点:指针会造成困惑和麻烦。缺乏对抽象的显示支持,比如类、对象和异常。C++和Java解决了这些问题。


  • 程序需要经过下面的命令,编译成低级机器语言指令才能被最终运行:

linux> gcc -o hello hello.c

  • 编译系统由4个阶段的程序组成:预处理器(cpp)、编译器(ccl)、汇编器(as)、链接器(ld);


预处理阶段:根据#开头的命令,把包含进来的.h或者.c文件直接插入到相应位置,生成一个hello.i文件;
编译阶段:编译器将hello.i翻译成汇编语言程序,生成hello.s文件;
汇编阶段:汇编器将hello.s翻译成机器语言指令,把它们打包成一种可重定位目标程序,生成hello.o文件;
链接阶段:链接器将标准C库中的已经预编译好的.o文件(比如printf.o)以某种方式合并到我们的hello.o中,最终形成可执行文件hello。


  • 汇编语言将不同的高级语言提供了通用的输出语言。相当于一个连接高级语言和机器语言的桥梁。

 
【成为一个优秀的人,可以从这些方面重点切入】
1、拥有强烈的好奇心:
你所能拥有的一切,都源自于探索;而探索的动力,都源自于好奇。正是因为这种好奇,驱动他们离开舒适区,获得更多新知识,不断拓展自己的边界。拥有好奇心的人,就像一块海绵。不断吸收新的知识,获得更大的成长。也因此,他们总是乐意接受更大的挑战。如果已经丢失了孩童时的好奇心,我们还能再捡起来吗?当然可以,当你对一件事情失去兴趣时,“我好奇如果我这么做了,会怎么样?”这么问自己!
 
2、面对不确定性,选择拥抱而不是怀疑:
人们厌恶不确定性,是因为厌恶不确定性背后巨大的风险。但是,不确定性背后,除了巨大的风险,也可能是巨大的收益。因为拥抱比怀疑,永远多一次机会。能成大事儿的人,在面对不确定性时,更容易选择拥抱,而不是怀疑。

3、相比赚钱,他们有更大的目标和想象力:
房子车子都只是附带品。最关键的是,我要不断成长,积累自己的价值,让自己变得稀缺,有能力去解决别人解决不了的问题。所以想要成大事儿,就要有更大的目标和想象力,专注于创造价值,而不是创造财富。
 
4、延迟满足,极度自律:
在这个世界上,要把一件事情做到极致,其实大部分时候都是很平淡,很枯燥的。延迟满足,能够让你在日复一日的枯燥中,不至于选择放弃。
 
5、不怕犯错,善于自省:
很多人不愿尝试做能力范围之外的事情,有一个原因是:害怕犯错。但其实只要不是什么致命错误,犯一些小错,反而是值得高兴的事。不怕犯错,善于自省,不断改进。这样的人,没有天花板。
 
希望我们都能不断成长为心目中那个,最好的自己。
https://mp.weixin.qq.com/s/9vGy6dc1vhBl58GA6F-ARw
 
【怎么理解美国关闭中国休斯顿使馆时间?本质是什么?】
说白了美方就是在故意找事。对美国好处很大,尤其对特朗普而言好处非常大。下面的视频很好的说明了这件政治事件。
https://player.youku.com/embed/XMTg5MDc5MzI3Ng==
对于这些在野党而言,今天的美国经济搞的再稀烂,那也是特朗普的锅。疫情越猛,经济越差,在野党越开心,当然要千方百计的破坏美国抗疫大局。
手段是合法的,用心是险恶的。所以不是特朗普不想消灭病毒,他是真的做不到。当然,特朗普也不是啥好货,他所有政治行为的唯一目的,也是为了选票和连任。其他一切东西,都没有这个重要,包括美国的未来。
这是人性,无关道德。
https://mp.weixin.qq.com/s/9m6Flh3X3wg9Xo-PJJzvuQ 
 
【Go语言核心36讲:第7节 数组与切片】
数组类型的值(以下简称数组)的长度是固定的(是其类型的一部分),而切片类型的值(以下简称切片)是可变长的。
我们其实可以把切片看做是对数组的一层简单的封装,因为在每个切片的底层数据结构中,一定会包含一个数组。数组可以被叫做切片的底层数组,而切片也可以被看作是对数组的某个连续片段的引用(所以Go 语言的切片类型属于引用类型)。
s3 := []int{1, 2, 3, 4, 5, 6, 7, 8}
s4 := s3[3:6]
fmt.Printf("The length of s4: %d\n", len(s4))
fmt.Printf("The capacity of s4: %d\n", cap(s4))
fmt.Printf("The value of s4: %d\n", s4)
s3[3:6] 等同于数学表达式:[3, 6)。所以,s4的长度就是6-3=3。容量是从起始索引开始(无法向左扩展,只能从3开始,及0,1,2切片s4“看不到”),一直到“底层数组”最右端,所以,容量是 8-3=5。
 
切片容量如何增长?
它并不会改变原来的切片,而是会生成一个容量更大的切片,然后将把原有的元素和新元素一并拷贝到新切片中。在一般的情况下,你可以简单地认为新切片的容量(以下简称新容量)将会是原切片容量(以下简称原容量)的 2 倍
但是,当原切片的长度(以下简称原长度)大于或等于1024时,Go 语言将会以原容量的1.25倍作为新容量的基准(以下新容量基准)。新容量基准会被调整(不断地与1.25相乘),直到结果不小于原长度与要追加的元素数量之和(以下简称新长度)。最终,新容量往往会比新长度大一些,当然,相等也是可能的。
另外,如果我们一次追加的元素过多,以至于使新长度比原容量的 2 倍还要大,那么新容量就会以新长度为基准。
 
切片的底层数组什么时候会被替换?
确切地说,一个切片的底层数组永远不会被替换。为什么?虽然在扩容的时候 Go 语言一定会生成新的底层数组,但是它也同时生成了新的切片。它只是把新的切片作为了新底层数组的窗口,而没有对原切片,及其底层数组做任何改动。请记住,
 
  • 在无需扩容时,append函数返回的是指向原底层数组的新切片,
  • 而在需要扩容时,append函数返回的是指向新底层数组的新切片。

 
https://time.geekbang.org/column/intro/100013101
 

#每日精进#2020年7月27日

zkbhj 发表了文章 • 0 个评论 • 1622 次浏览 • 2020-07-27 10:03 • 来自相关话题

【总结《一年顶十年》读后感】
https://ask.zkbhj.com/?/article/346
 
【最新的世界格局理解:世界的蛋糕已经不够分了】
全世界的发达国家,都在不同程度上陷入内噬。最直接冲击是就业。
各种冲突、内卷,全世界的蛋糕已经不够分了。
这背后本质,还是科技红利消失殆尽,而下一个科技革命仍然遥遥无期。
现在就仿佛一个炸药桶,各方情绪在里面酝酿。
所有人都不满意目前的世界格局。
但是现在发动战争的成本太高,且搞不好就变成了核战争。所以,对美国来说,中国就是一个标准的背锅对象。
所以,「逆全球化」其实是欧美的逆中国化,遏制中国的商品出口,不跟中国玩了。
逆中国化只能说很难,主要还是成本问题。中国是所有工业门类最齐全的国家,任何零部件都做得出来,甚至形成「供应链网络」,效率非常高。
既然美国要「逆中国化」,要拆解中国的产业链,遏制中国企业的出海路,那我们要做的,自然是高举全球化大旗,坚持改革开放。
对外是一带一路,是中非命运共同体,是欧亚大陆一体化,是推动中日韩自贸区;对内是新农村建设,是乡村振兴战略,把产业过剩能力转向内陆建设。
这就是对美国的最好反制。
你不开拓市场,别人就会抢占先机。
https://mp.weixin.qq.com/s/x6qDmU0-e6um6QiZH7trfA

【每日一个TED:安德鲁·斯坦顿】
在一个推荐系统解构分享PPT中的一句话发现的这个故事。
里面在解释为什么需要推荐系统时,陈述了一个“信息过载“的事实,里面引用了安德鲁·斯坦顿的一句话:

Don't give them 4, give them 2+2

所以查找了相关的原出处,是安德鲁·斯坦顿的一个TED演讲中讲到的,名字叫《一个伟大故事的线索》
https://www.ted.com/talks/andrew_stanton_the_clues_to_a_great_story/transcript?language=zh-cn
【推荐系统解构(电商篇)】
推荐的目的:帮助用户发现好商品,帮助高质量商品触达精准受众(背后对平台和商家就是促进转化)
数据闭环:
用户:浏览、点击、成交、评价、物流全链路闭环数据商品:潜力、新品、老品、衰落、下架
 
主要召回策略包括:

1) 实时行为召回:在线实时捕捉用户对商品的点击,收藏,加购,购买等反馈行为,并召回相似商品,迅速抓住用户的短期购物需求。
2) 历史行为召回:离线分析用户对商品的历史点击,收藏,加购,购买等反馈行为,并召回相似商品,兼顾用户的长期购物需求。
3) profile召回:从性别,年龄段,设备等多个维度,在线和离线同时对用户进行画像,并召回相对应的热门商品。
4) 热销&趋势召回:分析商品的长期和短期销量变化,召回爆款和近期热点商品。

排序模型建模(电商)相关:

Ctr: Expose -> Click
Cvr: Click -> Order 
GMV-Rate: Click -> GMV
GMV-Pv: Expose -> GMV

排序:一个指标不够—点击和转化:

基础排序公式:score = ctrα * cvrβ * priceγ

假设:
 ctr和cvr估计是准确的, α、β、γ均为1的排序公式才有可能最大化收益 item粒度的估计,而非组合力度的估计 
解决方案: 
通过调整三个因子的大小,如果三者相对稳定可以通过离线统一参数学习 的情况完成,如果不稳定,可通过强化学习来解决这个超参的设定。
复杂排序公式:

score= ctrα * cvrβ * priceγ * mathScoreδ * timeWeightScoreε * mathTypeScoreθ * ···

mathScore:召回分 
typeWeightScore:召回类型分
timeWeight:时间衰减
mathType:召回类型
 
覆盖率:通过类目,品牌,频道,场景等多粒度的打散重排,最大化各个维度的个性化覆盖率。 
疲劳度:通过引入一定的随机因子,针对不同个性化程度,建立合理的轮转机制,保证一定的新颖性。 (这个概念以前没有了解过)

 推荐演进路线:

复杂度:规则 -> 线性 -> 非线性 -> 融合 
时效性:天级 -> 时段级 -> 小时级 -> 实时

人工规则:人工经验提取规则,千人一 面,流量效率低 
线性模型:通过线性模型自动学习人工 提取的特征权重,简单的用 户特征,个性化推荐雏形
非线性模型:树模型及多模型融合,引入更多的上下文特征,加入用 户实时行为反馈,千人千面
深度学习、强化学习与在线学习:对象向量化表达,高维特征 自动提取,特征与模型实时在线更新
 
团队或产品是否应该做推荐功能的决策路径:
• 推荐功能对该产品有无价值(可以) 
• 价值多大(值得) 
• 成本和收益(现在) 
• 优先级(怎样)
比如推荐系统的实时性做到毫秒级是否有必要?
 
分群:根据不同维度对用户进行分群,从而进行针对性推荐
新老用户分群
购买力分群
兴趣分群(群体对类目的强偏好和弱偏好均可以在推荐中使用)
 
Query-Item 文本相关性

文本: 词->短语->语义->主题->句法 
图片: 图->标签&向量

或者把query看成id,与其它id做item2vector
 
PPT下载:
链接:https://pan.baidu.com/s/1YnYkWfpHW3-EokxHmoMrEQ 提取码:li44
 
【如何评估搜索的好坏?看哪些指标】
https://ask.zkbhj.com/?/article/356
 
【Go语言核心36讲:6 程序实体那些事儿】
一对不包裹任何东西的花括号{},除了可以代表空的代码块之外,还可以用于表示不包含任何内容的数据结构(或者说数据类型)。
类型断言表达式的语法形式是x.(T)。其中的x代表要被判断类型的值。
struct{},它就代表了不包含任何字段和方法的、空的结构体类型。interface{}则代表了不包含任何方法定义的、空的接口类型。对于一些集合类的数据类型来说,{}还可以用来表示其值不包含任何元素,比如空的切片值string{},以及空的字典值map[int]string{}。
 
类型字面量:所谓类型字面量,就是用来表示数据类型本身的若干个字符。

string是表示字符串类型的字面量,uint8是表示 8 位无符号整数类型的字面量。再复杂一些的就是我们刚才提到的string,用来表示元素类型为string的切片类型,以及map[int]string,用来表示键类型为int、值类型为string的字典类型。

类型转换表达式:T(x)
x可以是一个变量,也可以是一个代表值的字面量(比如1.23和struct{}{}),还可以是一个表达式。
 
类型转换中的几个陷阱:
对于整数类型值、整数常量之间的类型转换,原则上只要源值在目标类型的可表示范围内就是合法的。虽然直接把一个整数值转换为一个string类型的值是可行的,但值得关注的是,被转换的整数值应该可以代表一个有效的 Unicode 代码点,否则转换的结果将会是"�"(仅由高亮的问号组成的字符串值)string(-1)得到的就是?string类型与各种切片类型之间的互转
 
一个值在从string类型向byte类型转换时代表着以 UTF-8 编码的字符串会被拆分成零散、独立的字节。
一个值在从string类型向rune类型转换时代表着字符串会被拆分成一个个 Unicode 字符。 //别名类型,实际上是同一个类型
type myString = string

//类型再定义,实际上是两个不同的类型
type myString string 
【今日放学别走】

Review推荐系统的新版推荐接口。

排查问题,了解netstat命令显示的tcp和tcp6的区别。# netstat -tlnp | grep :22 tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1444/sshd tcp6 0 0 :::22 :::* LISTEN 1444/sshd可以看到,netstat 显示表示 sshd 既监听在 ipv4 的地址,又监听在 ipv6 的地址。tcp6表示监听的是IPv6的。

netstat 只是很真实的显示监听的端口而已,但是需要注意 ipv6 实际上在 Linux 上也支持 ipv4。

https://blog.csdn.net/weixin_4 ... 16951  查看全部
【总结《一年顶十年》读后感】
https://ask.zkbhj.com/?/article/346
 
【最新的世界格局理解:世界的蛋糕已经不够分了】
全世界的发达国家,都在不同程度上陷入内噬。最直接冲击是就业。
各种冲突、内卷,全世界的蛋糕已经不够分了。
这背后本质,还是科技红利消失殆尽,而下一个科技革命仍然遥遥无期。
现在就仿佛一个炸药桶,各方情绪在里面酝酿。
所有人都不满意目前的世界格局。
但是现在发动战争的成本太高,且搞不好就变成了核战争。所以,对美国来说,中国就是一个标准的背锅对象。
所以,「逆全球化」其实是欧美的逆中国化,遏制中国的商品出口,不跟中国玩了。
逆中国化只能说很难,主要还是成本问题。中国是所有工业门类最齐全的国家,任何零部件都做得出来,甚至形成「供应链网络」,效率非常高。
既然美国要「逆中国化」,要拆解中国的产业链,遏制中国企业的出海路,那我们要做的,自然是高举全球化大旗,坚持改革开放。
对外是一带一路,是中非命运共同体,是欧亚大陆一体化,是推动中日韩自贸区;对内是新农村建设,是乡村振兴战略,把产业过剩能力转向内陆建设。
这就是对美国的最好反制。
你不开拓市场,别人就会抢占先机。
https://mp.weixin.qq.com/s/x6qDmU0-e6um6QiZH7trfA

【每日一个TED:安德鲁·斯坦顿】
在一个推荐系统解构分享PPT中的一句话发现的这个故事。
里面在解释为什么需要推荐系统时,陈述了一个“信息过载“的事实,里面引用了安德鲁·斯坦顿的一句话:


Don't give them 4, give them 2+2


所以查找了相关的原出处,是安德鲁·斯坦顿的一个TED演讲中讲到的,名字叫《一个伟大故事的线索》
https://www.ted.com/talks/andrew_stanton_the_clues_to_a_great_story/transcript?language=zh-cn
【推荐系统解构(电商篇)】
推荐的目的:帮助用户发现好商品,帮助高质量商品触达精准受众(背后对平台和商家就是促进转化)
数据闭环:
  • 用户:浏览、点击、成交、评价、物流全链路闭环数据
  • 商品:潜力、新品、老品、衰落、下架

 
主要召回策略包括:


1) 实时行为召回:在线实时捕捉用户对商品的点击,收藏,加购,购买等反馈行为,并召回相似商品,迅速抓住用户的短期购物需求。
2) 历史行为召回:离线分析用户对商品的历史点击,收藏,加购,购买等反馈行为,并召回相似商品,兼顾用户的长期购物需求。
3) profile召回:从性别,年龄段,设备等多个维度,在线和离线同时对用户进行画像,并召回相对应的热门商品。
4) 热销&趋势召回:分析商品的长期和短期销量变化,召回爆款和近期热点商品。


排序模型建模(电商)相关:


Ctr: Expose -> Click
Cvr: Click -> Order 
GMV-Rate: Click -> GMV
GMV-Pv: Expose -> GMV


排序:一个指标不够—点击和转化:


基础排序公式:score = ctrα * cvrβ * priceγ


假设:
 ctr和cvr估计是准确的, α、β、γ均为1的排序公式才有可能最大化收益 item粒度的估计,而非组合力度的估计 
解决方案: 
通过调整三个因子的大小,如果三者相对稳定可以通过离线统一参数学习 的情况完成,如果不稳定,可通过强化学习来解决这个超参的设定。
复杂排序公式:


score= ctrα * cvrβ * priceγ * mathScoreδ * timeWeightScoreε * mathTypeScoreθ * ···


mathScore:召回分 
typeWeightScore:召回类型分
timeWeight:时间衰减
mathType:召回类型
 
覆盖率:通过类目,品牌,频道,场景等多粒度的打散重排,最大化各个维度的个性化覆盖率。 
疲劳度:通过引入一定的随机因子,针对不同个性化程度,建立合理的轮转机制,保证一定的新颖性。 (这个概念以前没有了解过)

 推荐演进路线:


复杂度:规则 -> 线性 -> 非线性 -> 融合 
时效性:天级 -> 时段级 -> 小时级 -> 实时


人工规则:人工经验提取规则,千人一 面,流量效率低 
线性模型:通过线性模型自动学习人工 提取的特征权重,简单的用 户特征,个性化推荐雏形
非线性模型:树模型及多模型融合,引入更多的上下文特征,加入用 户实时行为反馈,千人千面
深度学习、强化学习与在线学习:对象向量化表达,高维特征 自动提取,特征与模型实时在线更新
 
团队或产品是否应该做推荐功能的决策路径:
• 推荐功能对该产品有无价值(可以) 
• 价值多大(值得) 
• 成本和收益(现在) 
• 优先级(怎样)
比如推荐系统的实时性做到毫秒级是否有必要?
 
分群:根据不同维度对用户进行分群,从而进行针对性推荐
新老用户分群
购买力分群
兴趣分群(群体对类目的强偏好和弱偏好均可以在推荐中使用)
 
Query-Item 文本相关性


文本: 词->短语->语义->主题->句法 
图片: 图->标签&向量


或者把query看成id,与其它id做item2vector
 
PPT下载:
链接:https://pan.baidu.com/s/1YnYkWfpHW3-EokxHmoMrEQ 提取码:li44
 
【如何评估搜索的好坏?看哪些指标】
https://ask.zkbhj.com/?/article/356
 
【Go语言核心36讲:6 程序实体那些事儿】
一对不包裹任何东西的花括号{},除了可以代表空的代码块之外,还可以用于表示不包含任何内容的数据结构(或者说数据类型)。
类型断言表达式的语法形式是x.(T)。其中的x代表要被判断类型的值。
  • struct{},它就代表了不包含任何字段和方法的、空的结构体类型。
  • interface{}则代表了不包含任何方法定义的、空的接口类型。
  • 对于一些集合类的数据类型来说,{}还可以用来表示其值不包含任何元素,比如空的切片值string{},以及空的字典值map[int]string{}。

 
类型字面量:所谓类型字面量,就是用来表示数据类型本身的若干个字符。


string是表示字符串类型的字面量,uint8是表示 8 位无符号整数类型的字面量。再复杂一些的就是我们刚才提到的string,用来表示元素类型为string的切片类型,以及map[int]string,用来表示键类型为int、值类型为string的字典类型。


类型转换表达式:T(x)
x可以是一个变量,也可以是一个代表值的字面量(比如1.23和struct{}{}),还可以是一个表达式。
 
类型转换中的几个陷阱:
  1. 对于整数类型值、整数常量之间的类型转换,原则上只要源值在目标类型的可表示范围内就是合法的。
  2. 虽然直接把一个整数值转换为一个string类型的值是可行的,但值得关注的是,被转换的整数值应该可以代表一个有效的 Unicode 代码点,否则转换的结果将会是"�"(仅由高亮的问号组成的字符串值)string(-1)得到的就是?
  3. string类型与各种切片类型之间的互转

 
一个值在从string类型向byte类型转换时代表着以 UTF-8 编码的字符串会被拆分成零散、独立的字节。
一个值在从string类型向rune类型转换时代表着字符串会被拆分成一个个 Unicode 字符。 
//别名类型,实际上是同一个类型
type myString = string

//类型再定义,实际上是两个不同的类型
type myString string
 
【今日放学别走】

Review推荐系统的新版推荐接口。

排查问题,了解netstat命令显示的tcp和tcp6的区别。# netstat -tlnp | grep :22 tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1444/sshd tcp6 0 0 :::22 :::* LISTEN 1444/sshd可以看到,netstat 显示表示 sshd 既监听在 ipv4 的地址,又监听在 ipv6 的地址。tcp6表示监听的是IPv6的。

netstat 只是很真实的显示监听的端口而已,但是需要注意 ipv6 实际上在 Linux 上也支持 ipv4。

https://blog.csdn.net/weixin_4 ... 16951 

#每日精进#2020年7月24日

zkbhj 发表了文章 • 0 个评论 • 988 次浏览 • 2020-07-24 10:30 • 来自相关话题

【Go函数理解】
https://ask.zkbhj.com/?/article/352

【理解变量的深拷贝和浅拷贝】
https://ask.zkbhj.com/?/article/354
 
【Go HTTPClient包坑】
// An error is returned if there were too many redirects or if there 
// was an HTTP protocol error. A non-2xx response doesn't cause an 
// error. Any returned error will be of type *url.Error. The url.Error 
// value's Timeout method will report true if request timed out or was 
// canceled.
非200状态码并不会抛出Error,需要手动显示处理





  查看全部
【Go函数理解】
https://ask.zkbhj.com/?/article/352

理解变量的深拷贝和浅拷贝】
https://ask.zkbhj.com/?/article/354
 
【Go HTTPClient包坑】
// An error is returned if there were too many redirects or if there 
// was an HTTP protocol error. A non-2xx response doesn't cause an 
// error. Any returned error will be of type *url.Error. The url.Error 
// value's Timeout method will report true if request timed out or was 
// canceled.
非200状态码并不会抛出Error,需要手动显示处理

QQ截图20200724175822.jpg

 

#每日精进#2020年7月23日

zkbhj 发表了文章 • 0 个评论 • 926 次浏览 • 2020-07-23 11:25 • 来自相关话题

【什么是embedding】
目前在自如因为在做搜索和推荐,所以跟其相关的概念都需要进行了解,embedding就是其中一个。
学习并总结了一篇文章:https://ask.zkbhj.com/?/article/348
 
【学习远程过程调用RPC概念】
总结文章:https://ask.zkbhj.com/?/article/349
 
【排查线上问题:Go Map并发安全问题】





 
今天线上服务监控发现,有3分钟的时间,接口相应时间大幅度增加。3分钟恰好是熔断设置的窗口时长,说明当时触发了熔断。
登录应用管理后台,发现有一个实例重启过一次,重启时间和监控时间吻合。进入实例,查看当时的日志信息,发现如下报错:





 
定位到代码上之后,确认是发生了map数据结构并发读写问题。
 https://ask.zkbhj.com/?/article/350
为什么map并发读写会是个致命错误?
https://www.zhihu.com/question/305845656/answer/728440889 
 
【Go语言核心36讲】
第五节:
如果有代码包导入语句import . fmt,那么我们在当前源码文件中引用fmt.Printf函数的时候直接用Printf就可以了。在这个特殊情况下,程序在查找当前源码文件后会先去查用这种方式导入的那些代码包。
 
可重名变量和变量重命名的区别。 查看全部
【什么是embedding】
目前在自如因为在做搜索和推荐,所以跟其相关的概念都需要进行了解,embedding就是其中一个。
学习并总结了一篇文章:https://ask.zkbhj.com/?/article/348
 
【学习远程过程调用RPC概念】
总结文章:https://ask.zkbhj.com/?/article/349
 
【排查线上问题:Go Map并发安全问题】

QQ截图20200723165152.jpg

 
今天线上服务监控发现,有3分钟的时间,接口相应时间大幅度增加。3分钟恰好是熔断设置的窗口时长,说明当时触发了熔断。
登录应用管理后台,发现有一个实例重启过一次,重启时间和监控时间吻合。进入实例,查看当时的日志信息,发现如下报错:

QQ截图20200723165453.jpg

 
定位到代码上之后,确认是发生了map数据结构并发读写问题。
 https://ask.zkbhj.com/?/article/350
为什么map并发读写会是个致命错误?
https://www.zhihu.com/question/305845656/answer/728440889 
 
【Go语言核心36讲】
第五节:
如果有代码包导入语句import . fmt,那么我们在当前源码文件中引用fmt.Printf函数的时候直接用Printf就可以了。在这个特殊情况下,程序在查找当前源码文件后会先去查用这种方式导入的那些代码包。
 
可重名变量和变量重命名的区别。

#每日精进#2020年7月22日

zkbhj 发表了文章 • 0 个评论 • 1070 次浏览 • 2020-07-22 09:45 • 来自相关话题

【中台的发展方向】
中台经过数年的发展,已经进入到“碎片化中台”时代。
第一,业务中台。企业从业务顶层规划、业务建模开始,梳理出各业务领域的边界、服务能力,进而指导系统的服务化,以及企业数字化建设。
第二,“数据-业务”双中台。企业具备了业务领域建模、数据治理方面的能力,逐步建立起基于业务中台和数据中台的“双中台”模式,在这个过程中,沉淀自己的中台方法论和实践。
第三,碎片化中台。在完成业务中台、数据中台的建设之后,企业组织的效率已经有了显著提升,企业成本也随之降低。这个时候,中台建设进入到了碎片化中台阶段,组织内部按业务线或职能进行更细粒度拆分,比如:安全中台、财务中台、移动中台、客服中台、供应商中台、物流中台等等。
不管中台如何演变,大家记住一点:生产力决定生产关系,生产关系影响企业的组织模式,组织模式倒逼着系统架构适应组织架构,所以有了微服务、中台,这就是康威定律。
 
总的说来,中台主要解决两个问题:一是,提升体验;二是,降低成本。体验怎么提升呢?中台只是手段,中台的目的是支撑小前台。成本如何降低?通过合并重组相似组织来降低。
 
数据是中台的灵魂。数据的价值在于流动。
 
前中后台,都有自己的中台。中台的核心就是服务化。
https://mp.weixin.qq.com/s/jQ8sEhMTkZHab4NHqwyYGg
 
【管理学中的法则,也是“棍子管理法”的底层原理:赫勒法则】
“棍子管理法”的底层原理是赫勒法则,它是英国管理学家h.赫勒提出的,内容很简单:

当人们知道自己的工作成绩有人检查的时候,会加倍努力。


赫勒认为,没有有效的督促,就没有工作的动力,也就没有办法进行激励。
赫勒法则从人性的角度出发,认为人都是有惰性的。管理一方面要督促人对抗自身的惰性,另一方面也要真正调动员工的工作热情,提高员工的工作积极性。于是“激励+监督”,就是管理者手中的指挥棒,是让员工“动”起来的一个重要机制。
https://mp.weixin.qq.com/s/GJNuAz1FNIaDYw865oLhcQ
 
【读完了小说《坏小孩》】
看了电视剧再来看这本小说,真的是,会产生巨大的心理反差!
尤其是朱朝阳这个人物,是如此的黑暗和狡猾!不剧透了。总之,他最坏!
https://ask.zkbhj.com/?/article/345
  查看全部
【中台的发展方向】
中台经过数年的发展,已经进入到“碎片化中台”时代。
第一,业务中台。企业从业务顶层规划、业务建模开始,梳理出各业务领域的边界、服务能力,进而指导系统的服务化,以及企业数字化建设。
第二,“数据-业务”双中台。企业具备了业务领域建模、数据治理方面的能力,逐步建立起基于业务中台和数据中台的“双中台”模式,在这个过程中,沉淀自己的中台方法论和实践。
第三,碎片化中台。在完成业务中台、数据中台的建设之后,企业组织的效率已经有了显著提升,企业成本也随之降低。这个时候,中台建设进入到了碎片化中台阶段,组织内部按业务线或职能进行更细粒度拆分,比如:安全中台、财务中台、移动中台、客服中台、供应商中台、物流中台等等。
不管中台如何演变,大家记住一点:生产力决定生产关系,生产关系影响企业的组织模式,组织模式倒逼着系统架构适应组织架构,所以有了微服务、中台,这就是康威定律。
 
总的说来,中台主要解决两个问题:一是,提升体验;二是,降低成本。体验怎么提升呢?中台只是手段,中台的目的是支撑小前台。成本如何降低?通过合并重组相似组织来降低。
 
数据是中台的灵魂。数据的价值在于流动。
 
前中后台,都有自己的中台。中台的核心就是服务化。
https://mp.weixin.qq.com/s/jQ8sEhMTkZHab4NHqwyYGg
 
【管理学中的法则,也是“棍子管理法”的底层原理:赫勒法则】
“棍子管理法”的底层原理是赫勒法则,它是英国管理学家h.赫勒提出的,内容很简单:


当人们知道自己的工作成绩有人检查的时候,会加倍努力。



赫勒认为,没有有效的督促,就没有工作的动力,也就没有办法进行激励。
赫勒法则从人性的角度出发,认为人都是有惰性的。管理一方面要督促人对抗自身的惰性,另一方面也要真正调动员工的工作热情,提高员工的工作积极性。于是“激励+监督”,就是管理者手中的指挥棒,是让员工“动”起来的一个重要机制。
https://mp.weixin.qq.com/s/GJNuAz1FNIaDYw865oLhcQ
 
【读完了小说《坏小孩》】
看了电视剧再来看这本小说,真的是,会产生巨大的心理反差!
尤其是朱朝阳这个人物,是如此的黑暗和狡猾!不剧透了。总之,他最坏!
https://ask.zkbhj.com/?/article/345
 

#每日精进#2020年7月20日

zkbhj 发表了文章 • 0 个评论 • 1053 次浏览 • 2020-07-20 09:40 • 来自相关话题

【关于喝咖啡的几个真相】

1. 咖啡提神效果与基因有关,因人而异。
2. 咖啡可能会让心跳加快,这是正常的。
3. 喝咖啡不会导致心脏病。
4. 喝了咖啡,可能会频繁跑厕所。
5. 经期、孕期也能喝咖啡,但要适量。
6. 喝咖啡,不会导致胃溃疡。
7. 正常喝咖啡,不会导致骨质疏松。
8. 咖啡不致癌,还能降低某些癌症风险。
9. 经常喝咖啡会产生依赖,但不必戒。
10. 咖啡挺健康的,前提是别加糖。

https://mp.weixin.qq.com/s/bjbIbtHvnMTG_T_hAY3t5g
 
【三浦春马自杀事件】
这个世界虽然不完美,但我们仍然可以疗愈自己。
生活不易,请对自己善良一些! 
 

【关于疫情】
此次新冠疫情,国内也是此起彼伏的生发出来。北京刚刚宣布从今天0时起突发公共卫生事件相应级别从二级调整为三级,新疆那边又爆发。
大胆预测下,今年冬天还会有一波国内高峰。
张宏文说现在全球疫情还没有到达高峰,感觉只能等疫苗。
关于新冠后遗症的一些基本事实:
https://mp.weixin.qq.com/s/xuNYnbzeiSRq5k_7br4ZvA
 
【课程再学习:Go语言核心36讲】
1、库源码文件是不能被直接运行的源码文件,它仅用于存放程序实体,这些程序实体可以被其他代码使用(只要遵从 Go 语言规范的话)。
2、理由是,为了不让该代码包的使用者产生困惑,我们总是应该让声明的包名与其父目录的名称一致。
3、Go 语言中的程序实体包括变量、常量、函数、结构体和接口。
4、短变量声明,实际上就是 Go 语言的类型推断再加上一点点语法糖。只能在函数体内部使用短变量声明。
5、重构的概念:

我们通常把不改变某个程序与外界的任何交互方式和规则,而只改变其内部实现”的代码修改方式,叫做对该程序的重构。重构的对象可以是一行代码、一个函数、一个功能模块,甚至一个软件系统。

6、Go 语言的类型推断可以带来哪些好处:对重构友好,提升程序的灵活性。Go 语言的类型推断可以明显提升程序的灵活性,使得代码重构变得更加容易,同时又不会给代码的维护带来额外负担(实际上,它恰恰可以避免散弹式的代码修改),更不会损失程序的运行效率。7、变量重声明其实算是一个语法糖(或者叫便利措施)。它允许我们在使用短变量声明时不用理会被赋值的多个变量中是否包含旧变量。
var err error
n, err := io.WriteString(os.Stdout, "Hello, everyone!\n") 查看全部
【关于喝咖啡的几个真相】


1. 咖啡提神效果与基因有关,因人而异。
2. 咖啡可能会让心跳加快,这是正常的。
3. 喝咖啡不会导致心脏病。
4. 喝了咖啡,可能会频繁跑厕所。
5. 经期、孕期也能喝咖啡,但要适量。
6. 喝咖啡,不会导致胃溃疡。
7. 正常喝咖啡,不会导致骨质疏松。
8. 咖啡不致癌,还能降低某些癌症风险。
9. 经常喝咖啡会产生依赖,但不必戒。
10. 咖啡挺健康的,前提是别加糖。


https://mp.weixin.qq.com/s/bjbIbtHvnMTG_T_hAY3t5g
 
【三浦春马自杀事件】
这个世界虽然不完美,但我们仍然可以疗愈自己。
生活不易,请对自己善良一些! 
 

【关于疫情】
此次新冠疫情,国内也是此起彼伏的生发出来。北京刚刚宣布从今天0时起突发公共卫生事件相应级别从二级调整为三级,新疆那边又爆发。
大胆预测下,今年冬天还会有一波国内高峰。
张宏文说现在全球疫情还没有到达高峰,感觉只能等疫苗。
关于新冠后遗症的一些基本事实:
https://mp.weixin.qq.com/s/xuNYnbzeiSRq5k_7br4ZvA
 
【课程再学习:Go语言核心36讲】
1、库源码文件是不能被直接运行的源码文件,它仅用于存放程序实体,这些程序实体可以被其他代码使用(只要遵从 Go 语言规范的话)。
2、理由是,为了不让该代码包的使用者产生困惑,我们总是应该让声明的包名与其父目录的名称一致。
3、Go 语言中的程序实体包括变量、常量、函数、结构体和接口。
4、短变量声明,实际上就是 Go 语言的类型推断再加上一点点语法糖。只能在函数体内部使用短变量声明。
5、重构的概念:


我们通常把不改变某个程序与外界的任何交互方式和规则,而只改变其内部实现”的代码修改方式,叫做对该程序的重构。重构的对象可以是一行代码、一个函数、一个功能模块,甚至一个软件系统。


6、Go 语言的类型推断可以带来哪些好处:对重构友好,提升程序的灵活性。Go 语言的类型推断可以明显提升程序的灵活性,使得代码重构变得更加容易,同时又不会给代码的维护带来额外负担(实际上,它恰恰可以避免散弹式的代码修改),更不会损失程序的运行效率。7、变量重声明其实算是一个语法糖(或者叫便利措施)。它允许我们在使用短变量声明时不用理会被赋值的多个变量中是否包含旧变量。
var err error
n, err := io.WriteString(os.Stdout, "Hello, everyone!\n")

每日精进#2020年7月18日

zkbhj 发表了文章 • 0 个评论 • 1072 次浏览 • 2020-07-18 11:25 • 来自相关话题

【摩尔定律和安迪-比尔定律定率】
 
摩尔定律
 
摩尔定律是由英特尔(Intel)创始人之一戈登·摩尔(Gordon Moore)提出来的。其内容为:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月(目前验证18个月较为精确)便会增加一倍,性能也将提升一倍。
“摩尔定律”对整个世界意义深远。在回顾40多年来半导体芯片业的进展并展望其未来时,信息技术专家们认为,在以后“摩尔定律”可能还会适用。但随着晶体管电路逐渐接近性能极限,这一定律终将走到尽头。40多年中,半导体芯片的集成化趋势一如摩尔的预测,推动了整个信息技术产业的发展,进而给千家万户的生活带来变化。

https://www.zhihu.com/topic/19577621/intro​ 

安迪-比尔定律
 
其中的“安迪”,字面的意思是指英特尔公司的前CEO安迪·格鲁夫,背后所指代的是所有硬件厂商。而其中的“比尔”,字面的意思是指微软公司的比尔·盖茨,背后所指代的是所有软件厂商。

原文对于定律是这样解释的:Andy gives, Bill takes away.

直白地讲,就是硬件厂商们辛辛苦苦把硬件性能提升,而傻X软件公司们开发出更庞大、更消耗资源的软件,把硬件提升的性能给抵消了。 
从另一个角度来讲,安迪-比尔定律也并不全是坏事,许多新软件有着更高的配置要求,从而带动了硬件的消费市场,让整个IT生态更加活跃。比如某游戏公司推出一款酷炫的游戏,那么显卡公司一定会偷着乐。
 
https://zhuanlan.zhihu.com/p/80371343
 
  查看全部
【摩尔定律和安迪-比尔定律定率】
 
摩尔定律
 
摩尔定律是由英特尔(Intel)创始人之一戈登·摩尔(Gordon Moore)提出来的。其内容为:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月(目前验证18个月较为精确)便会增加一倍,性能也将提升一倍。
“摩尔定律”对整个世界意义深远。在回顾40多年来半导体芯片业的进展并展望其未来时,信息技术专家们认为,在以后“摩尔定律”可能还会适用。但随着晶体管电路逐渐接近性能极限,这一定律终将走到尽头。40多年中,半导体芯片的集成化趋势一如摩尔的预测,推动了整个信息技术产业的发展,进而给千家万户的生活带来变化。

https://www.zhihu.com/topic/19577621/intro​ 

安迪-比尔定律
 
其中的“安迪”,字面的意思是指英特尔公司的前CEO安迪·格鲁夫,背后所指代的是所有硬件厂商。而其中的“比尔”,字面的意思是指微软公司的比尔·盖茨,背后所指代的是所有软件厂商。

原文对于定律是这样解释的:Andy gives, Bill takes away.

直白地讲,就是硬件厂商们辛辛苦苦把硬件性能提升,而傻X软件公司们开发出更庞大、更消耗资源的软件,把硬件提升的性能给抵消了。 
从另一个角度来讲,安迪-比尔定律也并不全是坏事,许多新软件有着更高的配置要求,从而带动了硬件的消费市场,让整个IT生态更加活跃。比如某游戏公司推出一款酷炫的游戏,那么显卡公司一定会偷着乐。
 
https://zhuanlan.zhihu.com/p/80371343
 
 

每日精进#2020年7月17日

zkbhj 发表了文章 • 0 个评论 • 1175 次浏览 • 2020-07-17 10:57 • 来自相关话题

【Golang中goroutine协程的退出和销毁】
 
情况1:
Go语言中,若在子go协程中创建一个新 go协程,子go协程释放(销毁),新创建的go协程不会随着子go协程的销毁而销毁。
原因:go程共享堆,不共享栈,go程由程序员在go的代码里显示调度(释放)。package main
import (
"fmt"
"time"
"runtime"
)
func test() {
for i:=0;i<10;i++{
fmt.Printf("执行第%d次内层go程\n",i)
time.Sleep(time.Second)
}
fmt.Println("内层go程执行完毕!")
}
func main() {
go func() {
go test()
fmt.Println("------zkbhj-------")
time.Sleep(time.Second)
fmt.Println("------外层go程结束--------------")
/*
不管是return 还是 runtime.Goexit(),效果一样
*/
//return
runtime.Goexit()

}()
for{
runtime.GC()
}
}





从以上实例来看,虽然外层go协程已经退出,但是在go协程中新建的内层go协程还在执行!原因:go协程不共享栈,有自己独立的栈空间。外层go协程有自己的栈,在外层go协程中创建的新go协程也有自己的栈。外层go协程的栈被释放(回收),由于栈独立,因此新创建的内层go协程的栈不会被释放。 
情况2:
 
Go语言中,若在主go协程中创建一个新go协程,主go协程释放(销毁),新创建的go协程随着主go程的销毁而销毁。
原因:go程共享堆,不共享栈。package main

import (
"fmt"
"time"
)
func main() {
go func() {
for i:=0;i<10;i++{
fmt.Printf("子go程:执行第%d次操作!\n",i)
time.Sleep(time.Second)
}
}()
for i:=0;i<3;i++{
fmt.Println("--------zkbhj------")
time.Sleep(time.Second)
}
}





从以上实例来看,主go协程退出,子go协程马上退出。
原因:go协程共享堆。主go协程和新创建的子go协程共享一个堆。主go协程退出,执行main对应的{ },堆退出。由于是共享堆,所以对应的子go协程也会被销毁。

【深入理解Golang中的Runtime】
Golang Runtime是go语言运行所需要的基础设施
1、协成调度、内存分配、GC;
2、操作系统及CPU相关的操作的封装(信号处理、系统调用、寄存器操作、原子操作等),CGO;
3、pprof、trace、race检测的支持;
4、map、channel、string等内置类型及反射的实现。
 
与java、Python等的runtime不同,他们是虚拟机,而go的runtime是和用户代码一起编译到一个可执行文件中。用户代码和runtime代码除了代码组织上有界限,运行时没有明显界限。一些常用关键字被编译成runtime包下的一些函数调用,如go会变成 newproc,new会变成 newobject,等
 
Golang调度模型
PMG模型
轻量级携程G,栈初始2KB,调度不涉及系统调用,用户函数调用前会检查栈空间是否足够,不够会进行扩容,代码中的协程同步造成的阻塞,仅仅是切换协程,而不阻塞现成。
 
调用的进化史
Proctor(进程) --> Thread(LWP,lightweight process) --> Goroutine(一种lightweight userspace thread)
我们去看调度的一个进化, 从进程到线程再到协程, 其实是一个不断共享, 不断减少切换成本的过程。
 
对操作系统有过一些了解, 知道 linux 下的线程其实是 task_struct 结构, 线程其实并不是真正运行的实体, 线程只是代表一个执行流和其状态.真正运行驱动流程往前的其实是 CPU. CPU 在时钟的驱动下, 根据 PC 寄存器从程序中取指令和操作数, 从 RAM 中取数据, 进行计算, 处理, 跳转, 驱动执行流往前. CPU 并不关注处理的是线程还是协程, 只需要设置 PC 寄存器, 设置栈指针等(这些称为上下文), 那么 CPU 就可以欢快的运行这个线程或者这个协程了.

线程的运行, 其实是被运行.其阻塞, 其实是切换出调度队列, 不再去调度执行这个执行流. 其他执行流满足其条件, 便会把被移出调度队列的执行流重新放回调度队列.协程同理, 协程其实也是一个数据结构, 记录了要运行什么函数, 运行到哪里了。
 
sysmon协程是在go runtime初始化之后, 执行用户编写的代码之前, 由runtime启动的不与任何P绑定, 直接由一个M执行的协程. 类似于linux中的执行一些系统任务的内核线程。
 
调度综合总结: 
轻量级的协程, 栈初始2KB, 调度不涉及系统调用.调度在计算机中是分配工作所需资源的方法. linux的调度为CPU找到可运行的线程. 而Go的调度是为M(线程)找到P(内存, 执行票据)和可运行的G.用户函数调用前会检查栈空间是否足够, 不够的话, 会进行*2 栈扩容. 最大栈1G, 超出panic.用户代码中的协程同步造成的阻塞, 仅仅是切换(gopark)协程, 而不阻塞线程, m和p仍结合, 去寻找新的可执行的g.每个P均有local runq, 大多数时间仅与local runq无锁交互.  新生成的g, 放入到local runq中.调度时会随机从全局runq取g.  然后local runq, global runq... 均没有g的话, work stealing从其他P中取.sysmon: 对于运行过久的g设置抢占标识; 对于过久syscall的p, 进行m和p的分离. 防止p被占用过久影响调度.封装了epoll, 网络fd会设置成NonBlocking模式, 网络fd的read, write, accept操作, 会以NonBlocking模式操作, 返回EAGAIN则gopark当前协程. 在m调度, sysmon中, gc start the world等阶段均会poll出ready的协程进行运行或者添加到全局runq中目前(1.12), go还不支持非协作的抢占调度, 在密集CPU运算时, 可能会导致调度延迟. 官方已在解决.
 

https://www.acao.cn/course/program/402.html
  查看全部
【Golang中goroutine协程的退出和销毁】
 
情况1:
Go语言中,若在子go协程中创建一个新 go协程,子go协程释放(销毁),新创建的go协程不会随着子go协程的销毁而销毁
原因:go程共享堆,不共享栈,go程由程序员在go的代码里显示调度(释放)
package main
import (
"fmt"
"time"
"runtime"
)
func test() {
for i:=0;i<10;i++{
fmt.Printf("执行第%d次内层go程\n",i)
time.Sleep(time.Second)
}
fmt.Println("内层go程执行完毕!")
}
func main() {
go func() {
go test()
fmt.Println("------zkbhj-------")
time.Sleep(time.Second)
fmt.Println("------外层go程结束--------------")
/*
不管是return 还是 runtime.Goexit(),效果一样
*/
//return
runtime.Goexit()

}()
for{
runtime.GC()
}
}

QQ截图20200717104954.jpg


从以上实例来看,虽然外层go协程已经退出,但是在go协程中新建的内层go协程还在执行!原因:go协程不共享栈,有自己独立的栈空间。外层go协程有自己的栈,在外层go协程中创建的新go协程也有自己的栈。外层go协程的栈被释放(回收),由于栈独立,因此新创建的内层go协程的栈不会被释放。 
情况2:
 
Go语言中,若在主go协程中创建一个新go协程,主go协程释放(销毁),新创建的go协程随着主go程的销毁而销毁。
原因:go程共享堆,不共享栈。
package main

import (
"fmt"
"time"
)
func main() {
go func() {
for i:=0;i<10;i++{
fmt.Printf("子go程:执行第%d次操作!\n",i)
time.Sleep(time.Second)
}
}()
for i:=0;i<3;i++{
fmt.Println("--------zkbhj------")
time.Sleep(time.Second)
}
}

QQ截图20200717105408.jpg


从以上实例来看,主go协程退出,子go协程马上退出。
原因:go协程共享堆。主go协程和新创建的子go协程共享一个堆。主go协程退出,执行main对应的{ },堆退出。由于是共享堆,所以对应的子go协程也会被销毁。

【深入理解Golang中的Runtime】
Golang Runtime是go语言运行所需要的基础设施
1、协成调度、内存分配、GC;
2、操作系统及CPU相关的操作的封装(信号处理、系统调用、寄存器操作、原子操作等),CGO;
3、pprof、trace、race检测的支持;
4、map、channel、string等内置类型及反射的实现。
 
与java、Python等的runtime不同,他们是虚拟机,而go的runtime是和用户代码一起编译到一个可执行文件中。用户代码和runtime代码除了代码组织上有界限,运行时没有明显界限。一些常用关键字被编译成runtime包下的一些函数调用,如go会变成 newproc,new会变成 newobject,等
 
Golang调度模型
PMG模型
轻量级携程G,栈初始2KB,调度不涉及系统调用,用户函数调用前会检查栈空间是否足够,不够会进行扩容,代码中的协程同步造成的阻塞,仅仅是切换协程,而不阻塞现成。
 
调用的进化史
Proctor(进程) --> Thread(LWP,lightweight process) --> Goroutine(一种lightweight userspace thread)
我们去看调度的一个进化, 从进程到线程再到协程, 其实是一个不断共享, 不断减少切换成本的过程。
 
对操作系统有过一些了解, 知道 linux 下的线程其实是 task_struct 结构, 线程其实并不是真正运行的实体, 线程只是代表一个执行流和其状态.真正运行驱动流程往前的其实是 CPU. CPU 在时钟的驱动下, 根据 PC 寄存器从程序中取指令和操作数, 从 RAM 中取数据, 进行计算, 处理, 跳转, 驱动执行流往前. CPU 并不关注处理的是线程还是协程, 只需要设置 PC 寄存器, 设置栈指针等(这些称为上下文), 那么 CPU 就可以欢快的运行这个线程或者这个协程了.

线程的运行, 其实是被运行.其阻塞, 其实是切换出调度队列, 不再去调度执行这个执行流. 其他执行流满足其条件, 便会把被移出调度队列的执行流重新放回调度队列.协程同理, 协程其实也是一个数据结构, 记录了要运行什么函数, 运行到哪里了。
 
sysmon协程是在go runtime初始化之后, 执行用户编写的代码之前, 由runtime启动的不与任何P绑定, 直接由一个M执行的协程. 类似于linux中的执行一些系统任务的内核线程。
 
调度综合总结: 
  • 轻量级的协程, 栈初始2KB, 调度不涉及系统调用.
  • 调度在计算机中是分配工作所需资源的方法. linux的调度为CPU找到可运行的线程. 而Go的调度是为M(线程)找到P(内存, 执行票据)和可运行的G.
  • 用户函数调用前会检查栈空间是否足够, 不够的话, 会进行*2 栈扩容. 最大栈1G, 超出panic.
  • 用户代码中的协程同步造成的阻塞, 仅仅是切换(gopark)协程, 而不阻塞线程, m和p仍结合, 去寻找新的可执行的g.
  • 每个P均有local runq, 大多数时间仅与local runq无锁交互.  新生成的g, 放入到local runq中.
  • 调度时会随机从全局runq取g.  然后local runq, global runq... 均没有g的话, work stealing从其他P中取.
  • sysmon: 对于运行过久的g设置抢占标识; 对于过久syscall的p, 进行m和p的分离. 防止p被占用过久影响调度.
  • 封装了epoll, 网络fd会设置成NonBlocking模式, 网络fd的read, write, accept操作, 会以NonBlocking模式操作, 返回EAGAIN则gopark当前协程. 在m调度, sysmon中, gc start the world等阶段均会poll出ready的协程进行运行或者添加到全局runq中
  • 目前(1.12), go还不支持非协作的抢占调度, 在密集CPU运算时, 可能会导致调度延迟. 官方已在解决.

 

https://www.acao.cn/course/program/402.html