202302

算法

为什么 360 面试官说 Trie 树没用?
https://www.zhihu.com/question/27168319

多模式匹配算法-AC算法等
https://blog.csdn.net/xiaof_90/article/details/77447625

问题一:如果有一个关键词,然后让你在一段长文本中找出这些关键词,如何做?
问题二:如果有10K个关键词,然后让你在一段长文本中找出这些关键词,如何做?

如上问题一中,一段长文本中找一个关键词,那么就是单模式匹配。除了朴素算法(暴力算法)之外,还有一些经典的算法,例如KMP算法等。
问题二中,一段长文本中找N个关键词,那么就是多模式匹配,除了朴素算法外,也有一些经典的算法,例如AC算法、BM算法等。

https://pypi.org/project/cyac/

>>> ac = AC.build([u"python", u"ruby"])
>>> for id, start, end in ac.match(u"python ruby"):
>>>     print(id, start, end)

适用于大规模的多关键字匹配的多模匹配算法

  • agrep 对处理大规模的多关键字匹配问题有高效。多模式中最著名的快速匹配算法之一。
  • MultiBDM 基于AC和DAWG两种自动机扫描思想的多模匹配算法。根据匹配过程中使用时可的不同,作者提出了两种改进。

python

获取异常信息

try:
    pass
except Exception as e:
    print getattr(e, 'message', repr(e))

Python性能分析工具Line_profiler
https://blog.csdn.net/weixin_44613728/article/details/120411325

Python代码优化工具——memory_profiler
https://blog.csdn.net/weixin_42245157/article/details/126623370

pip install line-profiler
pip install -U memory_profiler

def cpu_profiler():
    from line_profiler import LineProfiler
    p = LineProfiler()
    p.add_function(match_keywords)
    p_wrap = p(run)
    p_wrap()
    p.print_stats()

def mem_profiler():
    from memory_profiler import profile
    p = profile(precision=4)(run)
    p()

python ahocorasick介绍
https://blog.csdn.net/u010569893/article/details/97136696

ahocorasick 是个 python 模块,Aho-Corasick 算法是多模式匹配中的经典算法,目前在实际应用中较多。

  • Trie是一个字符串索引的词典,检索相关项时时间和字符串长度成正比。
  • AC自动机能够在一次运行中找到给定集合所有字符串。
  • AC自动机其实就是在Trie树上实现KMP,可以完成多模式串的匹配。

linux

Linux 内核 101:NUMA架构
https://zhuanlan.zhihu.com/p/62795773

proxy setting

bash <(curl -s -L https://git.io/v2ray.sh)
stress-ng -c 0 -l 30 -t 8640000000

mysql

带进度导入数据

pv database1.sql.gz | gunzip | mysql -uroot -p database1

字节面试:知道MySQL 的 NULL 值是怎么存放的吗?
https://blog.csdn.net/Javatutouhouduan/article/details/128150631

结果集行号

select @rowNum:=@rowNum + 1 AS '行号',a.username,a.money
from account a, (select @rowNum:=0) b

books

The Subtle Art of Not Giving a F*ck
https://book.douban.com/subject/26895197/

作者:易又饕(来自豆瓣)
来源:https://book.douban.com/review/10006306/

  • 第一,要区分“快乐”(happiness)和"快感"(high)。前者具有可持续性,能真正让生活变得美好。后者往往是短暂的生理刺激,在刺激结束后还可能带来更深的痛苦。
  • 第二,生活中充满了问题,因为问题本来就是生活的常态。不必为连绵不断的问题本身而感到苦恼,如果因为这些苦恼而纠结,我们必然就干不了其他事情,进而会为无所成就而进一步苦恼,陷入恶性循环。
  • 第三,快乐只有在解决问题的过程中才能获得,而从长期来看,逃避问题只能带来更多的压力和挑战。用追求快感的方式来逃避挑战,最后只能像喝海水解渴,越喝越渴。
  • 第四,既然痛苦和挣扎是人生不可避免的一部分,就应该时刻做好直面它们的准备。同时,要选择自己的战场,把精力、能力和毅力用到那些真正值得解决的问题上。
  • 第五,明白自己所在乎的价值,同时明白自己用以衡量这些价值的标尺是否真正合适。好的价值,是往往是自己可以掌控的、真实的并且不会伤害其他人。好的标尺,往往也不依赖于我们无法控制的他人评价。
  • 第六,真正能够持续带来快乐的,只有不断提升自我、不断达到目标、不断解决问题的过程,而任何存量指标,比如金钱的数量等等,一旦被我们达到,就不会再带来快乐了。
  • 第七,没有必要和别人比较。没有必要对自己感觉过于良好或者不好。有时候,我们觉得自己在某些方面表现平常,这本来就是生活的应有之义,接受就好。
  • 第八,与其抱怨自己没有灵感或者动力,不如直接上手去干事情。很多时候,灵感和动力是在劳动的过程中产生的。克服惰性与恐惧,踏踏实实开始行动,很多问题都会迎刃而解。
  • 第九,情感上的支持自有其意义和价值,但每个人的问题都要每个人自己去解决。亲密关系中最好的相处之道,不是施舍与依赖,而是坦诚与理解。
  • 第十,生命短暂,但生活充实的人在死亡面前就会变得坦然。我们所在乎的许多东西,在生命这个宏大的命题面前,可能根本就不值得为之纠结。我们要选择自己在乎什么。

AI

GPT in 60 Lines of NumPy
https://jaykmody.com/blog/gpt-from-scratch/

投资

在投资分析中,简单的往往是实用的。我的投资理念很简单:在好行业中挑选好公司,然后等待好价格时买入。与之相对应的投资分析工具也同样简单。

  • 波特五力分析。不要孤立地看待一只股票,而要把一个公司放到行业的上下游产业链和行业竞争格局的大背景中分析,重点搞清三个问题:
    • 公司对上下游的议价权
    • 与竞争对手的比较优势
    • 行业对潜在进入者的门槛。
  • 杜邦分析。弄清公司过去5年究竟是靠什么模式赚钱的(高利润、高周转还是高杠杆),然后看公司战略规划、团队背景和管理执行力等是否与其商业模式一致。例如,
    • 高利润模式的看其广告投入、研发投入、产品定位、差异化营销是否合理有效,
    • 高周转模式的看其运营管理能力、渠道管控能力、成本控制能力等是否具备
    • 高杠杆模式的看其风险控制能力、融资成本高低等。
  • 估值分析。通过同业横比和历史纵比,加上市值与未来成长空间比,在显著低估时买入。

这“三板斧”分别解决的是好行业、好公司和好价格的问题,挑出来的“三好学生”就是值得长期持有的好股票了。

javascript

js 爬虫
https://github.com/zloirock/core-js/blob/master/scripts/usage/usage.mjs

others

TL;DR: The Top 6 Text Summarization APIs
https://rapidapi.com/blog/top-text-summarization-apis/

随机卡通头像
Vanilla JavaScript Library For Creating Avatars On The Client or Server-Side
https://webcodeflow.com/avataaars-js

SQLite the only database you will ever need in most cases
https://www.unixsheikh.com/articles/sqlite-the-only-database-you-will-ever-need-in-most-cases.html
https://news.ycombinator.com/item?id=34812527

Goodbye, CSS-Tricks!
https://geoffgraham.me/goodbye-css-tricks/
https://news.ycombinator.com/item?id=34864701
https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Write a First Person Game in 2KB With Rust
https://grantshandy.github.io/posts/raycasting/

数字人建模软件,有14天试用 https://www.agisoft.com/ Process digital images and generate 3D spatial data. Fast and highly accurate.

Deepfakes中文版,汉化版下载,各换脸软件下载(都已整理好)
https://blog.csdn.net/woniu211111/article/details/107901535
https://github.com/deepfakes/faceswap
https://blog.csdn.net/kaidikake/article/details/105224241

java

Bistoury原理解析
https://cloud.tencent.com/developer/article/1553180

Bistoury
去哪儿网开源的一个对应用透明无侵入的Java应用诊断工具,可以让开发人员无需登录机器或修改系统,就可以从日志、内存、线程、类信息、调试、机器和系统属性等各个方面对应用进行诊断,提升开发人员诊断问题的效率和能力。内部集成了arthas,所以它是arthas的超集。其中两个比较有特色的功能:在线DEBUG、动态监控,就是基于 Instrumentation + ASM 做的。

iBatis详解以及和MyBatis区别
https://www.iocoder.cn/MyBatis/x-plugins/

https://blog.csdn.net/zzuhkp/article/details/123518287

spring-boot-starter-parent 和 spring-boot-dependencies 都进行了依赖管理,如果依赖中存在漏洞我们就需要紧急进行修复,它们之间的升级方式有所不同。

  • 对于 spring-boot-starter-parent 而言,我们可以直接在 properties 中指定依赖的版本,因为在 spring-boot-dependencies 中包的坐标使用了这个属性值作为版本号
  • 对于 spring-boot-dependencies,如果要进行依赖升级,配置属性是不行的,需要在 spring-boot-dependencies 前面加上要升级的依赖的坐标
  • 如果要升级的依赖不是 spring-boot-starter-parent 或 spring-boot-dependencies 管理的依赖,还可以直接把它加到 dependencies 标签下,这样依据最短路径原则,我们直接配置的依赖会覆盖间接引入的依赖

202301

java

SpringCloud之Eureka详细的配置
https://www.cnblogs.com/BlogNetSpace/p/11264235.html
ubuntu 安装 rabbitmq
https://blog.csdn.net/sepnineth/article/details/126235964
搭建Eureka - 分区
https://blog.csdn.net/wxy540843763/article/details/100046858
Spring boot config 配置及刷新
https://blog.csdn.net/backonway/article/details/85094571
实体映射最强工具类:MapStruct 真香!
https://cloud.tencent.com/developer/article/1996748

mapstruct坑:Internal error in the mapping processor: java.lang.NullPointerException at org.mapstruct.
https://blog.csdn.net/qq_37132495/article/details/122010257

Setting -->Build,Execution,Deployment -->Compiler -->User-local build process VM options (overrides Shared options):
-Djps.track.ap.dependencies=false

解决 HikariPool-1 - Exception during pool initialization.问题
https://blog.csdn.net/qq_40369243/article/details/115818732

Spring Security 实战干货:用户信息UserDetails相关入门
https://segmentfault.com/a/1190000020628228?utm_source=tag-newest
spring-cloud-gateway之GlobalFilter
https://www.jianshu.com/p/55de48fc484b
SpringCloud:学习Gateway网关拦截器的ServerWebExchange
https://www.cnblogs.com/fdzang/p/11812348.html
统一认证中心 Oauth2 认证坑
https://blog.csdn.net/wangsofa/article/details/121155006
Spring Security OAuth2 单点登录
https://www.cnblogs.com/cjsblog/p/15512596.html
GateWay 中StripPrefix的作用
https://blog.csdn.net/pichcar1982/article/details/120427469
Spring Security Oauth2 ResourceServerConfigurerAdapter (资源服务器配置)
https://blog.csdn.net/wangooo/article/details/113924394
Spring Security OAuth2 Opaque 令牌的简单使用指南
https://blog.csdn.net/new_ord/article/details/127834421
springcloud — 微服务鉴权管理Spring Security OAuth2原理解析(五)
https://blog.csdn.net/qq_38658567/article/details/113249583
springboot以jar包运行
https://www.cnblogs.com/xiaohang123/p/14945194.html
如何在spring security手动自定义用户认证SecurityContextHolder设置Authentication?
https://blog.51cto.com/u_12004792/5786751

http://localhost:8611/auth-dev.yml
http://localhost:8611/auth/dev
http://localhost:8612/actuator/gateway/routes

前端

浏览器原生支持ES6 export和import模块
http://www.hlwen.com/2022/09/22/757.html

Node.js 如何处理 ES6 模块
http://www.ruanyifeng.com/blog/2020/08/how-nodejs-use-es6-module.html

vue项目多环境配置(.env)的实现
https://www.jb51.net/article/217747.htm

PWA超简单入门
https://juejin.cn/post/6844903584899792903
https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps
https://web.dev/progressive-web-apps/

尤雨溪:Turbopack真的比Vite快10倍吗?
https://blog.csdn.net/gtLBTNq9mr3/article/details/127680877

谈谈JS二进制:File、Blob、FileReader、ArrayBuffer、Base64
https://blog.csdn.net/qiwoo_weekly/article/details/127255281

webpack打包之sourcemap
https://blog.csdn.net/formylovetm/article/details/126095387

redis

一篇文章搞定Redis Stream
https://blog.csdn.net/lt_xiaodou/article/details/126525965

不管是list还是订阅/发布模式,都有其弊端,比如list不能友好的重复消费,需要重复消费的话,需要程序代码去控制;而订阅/发布模式是一种转发消息的模式,只有订阅者在线的时候才能接收到消息,订阅者不在线期间产生的消息,就丢掉了。而Stream,有借鉴Kafka一些市面上成熟的消息队列的思想,可以消费失败重复消费,消息是持久化的。

postgre

默认配置

$ cat ~/.psqlrc
\timing
\pset border 2

PostgreSQL中文文档
https://www.yiibai.com/manual/postgresql/index.html

linux

clear all iptables rules
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT
iptables -t nat -F
iptables -t mangle -F
iptables -F
iptables -X

stress-ng: Simulate specific cpu percentages
https://serverfault.com/questions/796225/stress-ng-simulate-specific-cpu-percentages

I designed stress-ng so that one can specify 0 for the number of stressor processes to match the number of on-line CPUs, so to load each cpu at say 40%, use

stress-ng -c 0 -l 40

ssh 超时
https://www.bbsmax.com/A/MyJxnVG1dn/

服务端
vi /etc/ssh/sshd_config

    # server每隔60秒给客户端发送一次保活信息包给客户端
    ClientAliveInterval 60
    # server端发出的请求客户端没有回应的次数达到86400次的时候就断开连接,正常情况下客户端都会相应
    ClientAliveCountMax 86400

客户端
vi /etc/ssh/ssh_config

    # client 每隔60秒给客户端发送一次保活信息包给客户端
    ServerAliveInterval 60
    # client 端发出的请求服务端没有回应的次数达到86400次的时候就断开连接,正常情况下服务端都会相应
    ServerAliveCountMax 86400

How can I tail a zipped file without reading its entire contents?
https://stackoverflow.com/questions/1183001/how-can-i-tail-a-zipped-file-without-reading-its-entire-contents

No, you can’t. The zipping algorithm works on streams and adapts its internal codings to what the stream contains to achieve its high compression ratio.

Without knowing what the contents of the stream are before a certain point, it’s impossible to know how to go about de-compressing from that point on.

If it’s an option, then bzip2 might be a better compression algorithm to use for this purpose.

Bzip2 uses a block compression scheme. As such, if you take a chunk of the end of your file which you are sure is large enough to contain all of the last chunk, then you can recover it with bzip2recover.

How to get few lines from a .gz compressed file without uncompressing
https://stackoverflow.com/questions/8151380/how-to-get-few-lines-from-a-gz-compressed-file-without-uncompressing

gzip -cd CONN.20111109.0057.gz | head

zip, gzip, bzip2

  • gzip 只能压缩文件, 不能压缩目录, 后缀名为 .gz, 而且不保留原文件,还可以和 tar 命令一起构成 Linux 操作系统中比较流行的压缩文件格式。
  • bzip2 是gzip的升级版本,-压缩比比较高,- k 产生压缩文件后保留原文件

[译] 理解 zip 和 gzip 压缩格式背后的压缩算法
https://zhuanlan.zhihu.com/p/143459234

  • 虽然各种压缩算法适用于不同场景,但是它们的底层都是基于 DEFLATE。
  • DEFLATE 是同时使用了 LZ77 算法与哈夫曼编码(Huffman Coding)的一种无损数据压缩算法。
  • DEFLATE 最初是作为 LZW 以及其它受专利保护的数据压缩算法的替代版本而设计的。
  • 从技术上来说,zip 压缩格式是支持使用其他的压缩算法的,但是 DEFLATE 是其中最常用的一种。
  • zip 是一种相当简单的分别压缩每个文件的存档格式,分别压缩文件允许不必读取另外的数据而检索独立的文件。
  • zip 和 gzip(gz)不兼容,虽然它们都是使用相同的 deflate 压缩算法
  • zip 更像一个打包器,能把多个多件放到一个zip中;gzip 一次只对一个文件压缩,通常与 tar 命令一起用。
  • gz 的压缩速度更快,而 bz 的压缩比更好
  • GZIP 最早由 Jean-loup Gailly 和 Mark Adler 创建,用于 unix 系统的文件压缩,ZIP 文件格式是一种数据压缩和文档储存的文件格式。

Extract only a specific file from a zipped archive to a given directory
https://unix.stackexchange.com/questions/14120/extract-only-a-specific-file-from-a-zipped-archive-to-a-given-directory

unzip -l myarchive.zip
unzip -p myarchive.zip path/to/zipped/file.txt >file.txt
unzip -p myarchive.zip path/to/zipped/file.txt | head 
unzip -j "myarchive.zip" "in/archive/file.txt" -d "/path/to/unzip/to"
unzip -j myarchive.zip in/archive/file.txt another/file.ext -d /path/to/unzip/to
unzip -j archive.zip "sub/dir/*" -d "dest/dir"

I changed my hostname, why is my bash PS1 prompt unchanged?
https://unix.stackexchange.com/questions/15643/i-changed-my-hostname-why-is-my-bash-ps1-prompt-unchanged

echo 'mynewhostname' | sudo tee /etc/hostname
sudo hostname -F /etc/hostname
vi /etc/hosts
    127.0.0.1    mynewhostname.mydomainname.com    mynewhostname

SSH server gives “userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]” when connecting with Putty
https://unix.stackexchange.com/questions/721606/ssh-server-gives-userauth-pubkey-key-type-ssh-rsa-not-in-pubkeyacceptedalgorit

There are several types of keys and signature algorithms in the SSH protocol.
RSA keys, which have the key type ssh-rsa, can be used to sign with

  • SHA-1 (in which case, the signature type is ssh-rsa),
  • SHA-256 (which has signature type rsa-sha2-256),
  • or SHA-512 (which has signature type rsa-sha2-512).

backend

理解OAuth 2.0
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

Parquet 就是一种基于列式存储的文件格式,它有两个主要优点 [4]:

高度可压缩性:.json 或 .csv 文件通常默认未压缩,而 Parquet 会压缩数据,因此可以节省大量磁盘空间。表 通常包含具有大量唯一值的列(high cardinality(这里理解为出现次数多且值不同);例如用户 ID)和只有少数唯一值的列(low cardinality(虽然出现次数很多,但值都相同);例如国家)。频率越低,压缩效果越好(可能)——下一节将详细介绍。

文件查询/过滤下推:在读入之前修剪不必要的数据。这可以缩短加载时间并优化资源消耗。如果需要从一千个表中获取两列,你不需要扫描所有行来获取这两个属性——你直接获取整个这两列。

Arrow 序列化设计提供了一个“数据头”,它描述了表中所有列的所有内存缓冲区的确切位置和大小。这意味着你可以内存映射巨大的、大于 RAM 的数据集,并在它们上就地评估 pandas 风格的算法,而无需像现在使用 pandas 那样将它们加载到内存中。你可以从 1 TB 表的中间读取 1 兆字节,而只需支付执行这些总计 1 兆字节的随机读取的成本

下面这两个方式中需要进行权衡:

  • 优化磁盘空间/磁盘上的长期存储 → Parquet
  • 优化数据交换和快速检索 → Arrow

简单理解parquet文件格式——按列存储和元数据存储
https://blog.csdn.net/zhang35/article/details/122284903

Apache Arrow :零内存读取DataFrame
https://blog.csdn.net/qq_43232373/article/details/123995262

AWS 数据清洗技术栈

  • AWS S3 是一种对象存储服务,提供行业领先的可扩展性、数据可用性、安全性和性能。
  • Parquet 仅仅是一种列式存储格式,它是语言、平台无关的,并且不需要和任何一种数据处理框架绑定。
  • Apache Arrow 为平面和层次数据定义了一种与语言无关的柱状内存格式,这种格式的组织用于在现代硬件(如cpu和gpu)上进行高效的分析操作。pyarrow 是用于 Arrow 的 Python 库。
  • AWS Glue 是一项无服务器数据集成服务,它简化了发现、准备、移动和集成来自多个来源的数据以进行分析、机器学习(ML)和应用程序开发的工作。
  • Amazon Athena 是一种交互式查询服务,让您能够轻松使用标准 SQL 直接分析 Amazon S3 中的数据。

athena 的价格,扫描 1T 数据是5美元, 可以省钱的考虑点:

  • parquet 本身是压缩的,另外 athena 应该也支持压缩后的csv.gz格式。
  • parquet 是列数据库文件格式,如果查询语句里用不到所有列的话,一次查询可能不需要扫描整个文件,扫描量会少一些,这点比csv好。
  • parquet 支持分区,如果提前能知道以后可能的查询,可以设计好分区key,每次扫描可以继续减少扫描量。

mysql

mysql 排序,利用变量实现 显示排序序号
https://blog.csdn.net/weixin_55806809/article/details/122931550

  • “ := ” 赋值的意思 。 set 和 update 时, 但是一般都用 “ = ” 。 select 时 只能使用“ := ”方式
  • “ = ” set 和 update时 ,表示赋值。select 时 , 表示是判断。

code

set @i = 0;
set @sco = null;
select
student_id,
score,
case when @sco = score then @i else @i := @i + 1 end as 排名序号,
@sco := score
from tb_score where course_id = 1 ORDER BY score desc

SELECT sid,sname,gender,age,(@i:=@i+1) AS '序号'
FROM student,(SELECT @i:=0) AS itable;

MySQL 性能监控4大指标——第一部分
https://www.jianshu.com/p/36f385935ebd

Mysql Performance_schema简介, 表和常用性能查询
https://blog.csdn.net/solinger/article/details/122300008

哪类的SQL执行最多?

SELECT DIGEST_TEXT,COUNT_STAR,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY COUNT_STAR DESC limit 10\G

哪类SQL的平均响应时间最多?
SELECT DIGEST_TEXT,COUNT_STAR,AVG_TIMER_WAIT,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY AVG_TIMER_WAIT DESC limit 10\G

哪类SQL扫描记录数最多?
SELECT DIGEST_TEXT,SUM_ROWS_EXAMINED ,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_ROWS_EXAMINED DESC limit 10\G

SELECT DIGEST_TEXT,ROUND((SUM(sum_timer_wait) / SUM(count_star)) avg_time,FIRST_SEEN,LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY ROUND((SUM(sum_timer_wait) / SUM(count_star))  DESC limit 10\G

SELECT * FROM sys.statements_with_runtimes_in_95th_percentile limit 10\G

SHOW GLOBAL STATUS LIKE "Questions";

SELECT schema_name
     , SUM(count_star) count
     , ROUND(   (SUM(sum_timer_wait) / SUM(count_star))
     / 1000000) AS avg_microsec

     FROM performance_schema.events_statements_summary_by_digest

 WHERE schema_name IS NOT NULL
 GROUP BY schema_name;

Find last query executed by specific session on MySQL server
https://dataedo.com/kb/query/mysql/find-last-query-executed-by-session

set global log_output = 'table';
set global general_log = 'on';
select *,CONVERT((argument) USING utf8) t  from mysql.general_log limit 10\G
set global general_log = 'off';

table operator

  • check table: 检查 InnoDB 和 MyIsam 是否有错误。检查表或者视图是否存在错误
  • optimize table: 恢复被删除的块和重组表,清理碎片
  • analyze table: 检测和重组表的关键字分布情况。用来分析和存储表的关键字的分布,使得系统获得准确的统计信息,影响 SQL 的执行计划的生成。
  • repair table : 修复表

MySQL中analyze table的作用是?生产上操作会有什么风险?
https://www.modb.pro/db/168442

一、analyze table的作用
1、analyze table 会统计索引分布信息。
2、对于 MyISAM 表,相当于执行了一次 myisamchk --analyze
3、支持 InnoDB、NDB、MyISAM 等存储引擎,但不支持视图(view)
4、执行 analyze table 时,会对表加上读锁(read lock)
5、该操作会记录binlog

二、生产上操作的风险
1、analyze table的需要扫描的page代价粗略估算公式:sample_pages * 索引数 * 表分区数。
2、因此,索引数量较多,或者表分区数量较多时,执行analyze table可能会比较费时,要自己评估代价,并默认只在负载低谷时执行。
3、特别提醒,如果某个表上当前有慢SQL,此时该表又执行analyze table,则该表后续的查询均会处于waiting for table flush的状态,严重的话会影响业务,因此执行前必须先检查有无慢查询。

算法

  • KMP:用于字符串的匹配问题,对于普通的做法需要O(n*m)的复杂度暴力匹配,一旦失配需要从这一次原串匹配的开头字符的下一个字符开始匹配,也就是意味着原串所正在匹配的位置 i 可能会一直回退。KMP复杂度O(m+n),KMP的做法就是保证了指向原串正在匹配的位置的i不会回退。

  • Trie树:(字典树,多模式串匹配算法)一种树形结构,它是一种专门处理字符串匹配的数据结构,用来解决在一组字符串集合中快速查找某个字符串的问题(本质是利用字符串之间的公共前缀,将重复的前缀合并在一起)。

  • AC自动机:Trie树跟AC自动机之间的关系,就像单串匹配中朴素的串匹配算法与KMP算法一样,只不过前者针对的是多模式串。所以AC自动机实际上就是在Trie树之上,加了类似KMP的next数组,只不过此处的next数组是构建在树上。

202212

## windows

powershell 提示没权限,先用管理员模式启动

set-ExecutionPolicy RemoteSigned

linux

无法用 key ssh 到远程主机

journalctl -fu ssh
    userauth_pubkey: key type ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]

vi /etc/ssh/sshd_config.
    PubkeyAcceptedAlgorithms=+ssh-rsa

sudo systemctl restart sshd

LVM

pv lv vg 介绍

  • PV(physical volume) 即物理卷,就是物理磁盘,可以通过 fdisk -l 查看操作系统有几块硬盘
  • VG(volume group) 即卷组,就是一组物理磁盘的组合,里面可以有一块硬盘也可以有多块硬盘
  • LV(logical volume)及逻辑卷,就是在 VG (指定的物理磁盘组)里面划分出来的
  • 可以说成是 PV 就是硬盘,而 VG 就是管理硬盘的操作系统,而 LV 就是操作系统分出来的各个分区.
  • PV->VG->LV-> 文件系统使用(挂载到某个目录)
  • 硬盘或分区做成 pv,然后将 pv 或多个 pv 建立 vg,vg 上建立 lv

git 配置

git config --global http.proxy http://127.0.0.1:10800
git config --global https.proxy https://127.0.0.1:10800

git config --global --unset http.proxy
git config --global --unset https.proxy

git config --global url."https://".insteadOf git://

git config --list --show-origin

fio 磁盘性能测试工具
https://www.cnblogs.com/lyhabc/p/16708771.html

dd 命令来测试性能,有如下问题:

  • dd 命令的 IO 模型单一,只能测试顺序 IO,不能测试随机 IO。
  • dd 命令可设置的参数较少,并且测试结果不一定能反映出磁盘的真实性能。
  • dd 命令的设计初衷就不是用例测试性能的,在 dd 的手册中可以看到。
  • 无法设置队列深度,因此不推荐用 dd 命令来测试最大读 IOPS。

fio 测试模板

#read 顺序读 吞吐量
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=read -size=10G -nrfiles=1 -filename=fio_readputth_test.txt -name='fio read test' -iodepth=2 -runtime=120 -numjobs=4 -time_based=1 -allow_mounted_write=1 -group_reporting

#write 顺序写 吞吐量
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=write -size=10G -nrfiles=1 -filename=fio_writeputth_test.txt -name='fio write test' -iodepth=2 -runtime=120 -numjobs=4 -time_based=1 -allow_mounted_write=1 -group_reporting


#read 顺序读
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=read -size=2G -nrfiles=1 -filename=fio_read_test.txt -name='fio read test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#write 顺序写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=write -size=2G -nrfiles=1 -filename=fio_write_test.txt -name='fio write test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#readwrite 顺序混合读写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=readwrite -size=2G -nrfiles=1 -filename=fio_readwrite_test.txt -name='fio readwrite test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#randread 随机读
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=randread -size=2G -nrfiles=1 -filename=fio_randread_test.txt -name='fio randread test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#randwrite 随机写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=randwrite -size=2G -nrfiles=1 -filename=fio_randwrite_test.txt -name='fio randwrite test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

#randrw 随机混合读写
fio -ioengine=libaio -direct=1 -bs=4k -thread -rw=randrw -size=2G -nrfiles=1 -filename=fio_randrw_test.txt -name='fio randrw test' -iodepth=4 -runtime=60 -numjobs=8 -time_based=1 -allow_mounted_write=1 -group_reporting

,对于小块io(以64k为界)只需要关注iops,平均时延(lat中的avg),大块io关注吞吐和平均时延(lat中的avg)即可

java

大白话讲解Spring的@bean注解
https://zhuanlan.zhihu.com/p/99870991

从广义上Spring注解可以分为两类:

  • 一类注解是用于注册 Bean,比如 @Component , @Repository , @ Controller , @Service , @Configration 这些注解就是用于注册 Bean,放进 IOC 容器中。
  • 一类注解是用于使用 Bean,比如 @Autowired , @Resource 注解,这些注解就是把屋子里的东西自己拿来用,如果你要拿,前提一定是屋子(IOC)里有的,不然就会报错。

Bean 注解

  • Spring 的 @Bean 注解用于告诉方法,产生一个 Bean 对象,然后这个 Bean 对象交给 Spring 管理。
    • 产生这个 Bean 对象的方法 Spring 只会调用一次,随后这个 Spring 将会将这个 Bean 对象放在自己的 IOC 容器中。
  • @Component , @Repository , @Controller , @Service 这些注解只局限于自己编写的类,
    • 而 @Bean 注解能把第三方库中的类实例加入 IOC 容器中并交给 spring 管理。
  • @Bean 注解的另一个好处就是能够动态获取一个 Bean 对象,能够根据环境不同得到不同的 Bean 对象。

Java随机生成RSA密钥对
https://blog.csdn.net/msq16021/article/details/123743361

SpringBoot Security 自定义登录页面
https://blog.csdn.net/weixin_42555971/article/details/127440094

基于数据库自定义UserDetailsService实现JWT认证
https://blog.csdn.net/lazy_LYF/article/details/127284982

单点登录SSO,JWT进行跨域身份验证,前端登录实现Coding在线(十一)
https://blog.csdn.net/wang121213145/article/details/123553741

SpringSecurity以及Oauth2(笔记)
https://blog.csdn.net/weixin_46949627/article/details/126698801

Spring MVC中redirect重定向3种方式(带参数)
https://blog.csdn.net/weixin_39973810/article/details/84847922

javascript

npm install 报错

  • git 挂代理:git config --global http.proxy http://127.0.0.1:10800
  • git 默认使用 http:git config --global url.“https://”.insteadOf git://
  • node-scss匹配的最高版本才nodjs 14,不能要最新版本的 nodejs
  • 跟linux还是windows没啥关系,linux也不行

其他

https://v2ex.com/t/901954 你们的 NAS 部署了什么有趣的服务?

  • 网盘:seafile,坚果云, dufs,filebrowser,baidunetdisk,timemachine,icloudpd,filebrowser
  • 文件同步:syncthing/nextcloud,etesync,icloudpd,samba
  • 照片:mt-photos,PhotoPrism,photoview
  • 内网穿透:cloudflared,frpc,tailscale
  • 内网组网:tailscale
  • 梯子:openclash,stashapp,subconverter,v2ray
  • 统一登录:authelia
  • 下载:aria2,aria2pro,qbittorrent
  • 搜索引擎:whoogle/searxng
  • 容器管理:portainer/watchtower
  • 密码管理:vaultwarden
  • 反代网关:traefik
  • git 仓库:gitea,Gogs
  • 网盘文件目录:alist
  • DNS:adguard-home,Adguard home DNS
  • 笔记博客:mastodon,outline,b3log/siyuan
  • 网站监控:uptime-kuma
  • RSS: rsshub,freshrss,ttrss
  • 智能家居:Home Assistant,doods2
  • 音视频:Jellyfin
  • 聊天:Snikket

笔记软件

需求

做一个单机不联网的笔记软件,能够

  • 编辑 markdown 文件
  • 编辑 excel, csv 文件
  • 编辑 word 文件
  • 画脑图
  • 画原型图
  • 画流程图
  • 画架构图
  • 画 uml 图
  • 画 ER 图
  • 涂鸦

开源组件

202211

linux

手把手教你使用VSCode进行linux内核代码阅读和开发
https://zhuanlan.zhihu.com/p/558286384

指定ssh key 克隆代码

git clone git@provider.com:userName/projectName.git --config core.sshCommand="ssh -i ~/location/to/private_ssh_key"

vscode 阅读内核源码配置

对比

  • source insight ,因为内核下有多个平台的头文件、源码,
    往往能找到很多个同名函数或变量的定义,还得一个一个去确认,非常麻烦。
  • vscode 加上 C++ Intellisense 插件或者 global 插件,类似source insight,
    需要手动排除未编译文件减小索引范围,代码定位不准。
  • 文本浏览工具和 grep 进行代码搜索浏览,这种方法最简单,效率也最低。
  • 使用 vim + ctags,比较高大上,但我觉得vim里打开很多文件不太方便,不太适合阅读大工程的代码。
  • vscode + remote ssh + clangd,clangd 插件用于代码语义分析、代码补全、跳转等。
    该方案克服了上面列举的几种方案的几乎各种缺点,能做到代码精准跳转、精准自动补全,

总体流程:

  • 安装 vscode
  • 安装 Remote SSH
  • 连接到远程 linux
  • 远程安装 clangd server
  • 本地安装 clange 插件
  • 配置 clangd 插件
  • linux 相关操作
  • 打开远程 linux 内核目录,等待 clangd 索引完毕
  • ctrl+t 查找符号,f12 查找定义,shift+alt+f12 查找引用,alt+箭头 编辑点跳转

clangd 插件配置

--compile-commands-dir=${workspaceFolder}
--background-index
--completion-style=detailed
--header-insertion=never
-log=info

linux 相关操作:

# 如果 vscode 远程无法安装 clang server,则手工安装
wget https://gitee.com/zhengqijun/clangd/releases/download/15.0.3/clangd-linux-15.0.3.zip

# 安装 bear,生成 compile_commands.json
sudo apt install bear
bear make bzImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-

# 如果上面生成的 json 文件无效,再尝试下面的脚本
./scripts/gen_compile_commands.py

了解linux内核必读的五本书
https://zhuanlan.zhihu.com/p/359049747

  • 《Linux内核设计与实现》 简称 LKD,内容比较浅显易懂,个人认为是内核新人首先必读的书籍。
  • 《深入理解Linux内核》简称 ULK,相比于LKD的内容不够深入、覆盖面不广,ULK要深入全面得多。
  • 《Linux设备驱动程序》简称 LDD,驱动开发者都要人手一本了。
  • 《深入理解Linux虚拟内存管理》简称 LVMM,介绍Linux虚拟内存管理机制。
  • 《深入理解LINUX网络内幕》,讲解网络子系统实现的书。

pip3 报错

AttributeError: module 'lib' has no attribute 'X509_V_FLAG_CB_ISSUER_CHECK'

解决

apt remove python3-openssl -y 
apt autoremove

linux 命令示例速查
https://github.com/cheat/cheat
https://mp.weixin.qq.com/s/CEOU9LDSKU05uJSvgLSMZg

查看两个时间点之间的日志

sed -n '/2022-11-01T16:52:40/,/2022-11-01T16:52:42/p' /var/log/nginx/access.log | more

Linux sed命令完全攻略(超级详细)
http://c.biancheng.net/view/4028.html

mmap的几种使用场景
https://www.cnblogs.com/Arnold-Zhang/p/15686868.html
https://izualzhy.cn/mmap

mysql

JSON_TABLE - The Best of Both Worlds
https://dev.mysql.com/blog-archive/json_table-the-best-of-both-worlds/

查看长语句进度
https://www.lanmper.cn/mysql/t8551

select SQL_TEXT,ROWS_EXAMINED,ROWS_AFFECTED,ROWS_SENT, TIMER_WAIT/(1000*1000*1000) wait_ms, LOCK_TIME/(1000*1000*1000)

lock_ms from performance_schema.events_statements_current where SQL_TEXT is not null and TIMER_WAIT/(100010001000) > 100 order by TIMER_WAIT desc\G

  • TIMER_WAIT 事件经过的时间(持续时间),单位是皮秒(万亿分之一秒)
  • LOCK_TIME 等待表锁所花费的时间,该值以微秒为单位计算,但归一化为皮秒,以便与其他性能模式计时器进行比较。
  • ROWS_AFFECTED 语句影响的行数。
  • ROWS_SENT 语句返回的行数。
  • ROWS_EXAMINED 服务器层检查的行数(不计算存储引擎内部的任何处理)。

How to create index on json column in MySQL?
https://stackoverflow.com/questions/38389075/how-to-create-index-on-json-column-in-mysql

CREATE TABLE inventory(
items JSON,
INDEX i1 ( (JSON_VALUE(items, '$.name' RETURNING CHAR(50))) ),
INDEX i2 ( (JSON_VALUE(items, '$.price' RETURNING DECIMAL(5,2))) ),
INDEX i3 ( (JSON_VALUE(items, '$.quantity' RETURNING UNSIGNED)) )
);

SELECT items->"$.price" FROM inventory
WHERE JSON_VALUE(items, '$.name' RETURNING VARCHAR(50)) = "hat";

SELECT * FROM inventory
WHERE JSON_VALUE(items, '$.price' RETURNING DECIMAL(5,2)) <= 100.01;

SELECT items->"$.name" AS item, items->"$.price" AS amount
FROM inventory
WHERE JSON_VALUE(items, '$.quantity' RETURNING UNSIGNED) > 500;

postgre

内核 IO 参数
sysctl -a |grep vm.dirty_background_ratio

推荐配置

40 core, 80 thread @ 2.2Ghz
256GB RAM
16TB NVMe storage (RAID10 usable ~8TB), 28GB/s sequential read, 26GB/s sequential write, 4.9M random read IO/s, 4.4M random write IO/s

可视化执行计划

https://tatiyants.com/pev/#/plans

kill sql

# only select
SELECT pg_cancel_backend(PID);

# can be update, delete
SELECT pg_terminate_backend(PID);

show processlist

SELECT pid, datname AS db, query_start AS start, now() - query_start AS lap, query 
FROM pg_stat_activity 
WHERE state <> 'idle' and query not like '%pg_stat_activity%'  
and (now() - query_start) > interval '1 seconds';

理财

日内做多策略

  • 看 5 分钟级别 K 线
  • 低开,不做
  • 开盘第一条 K 线长上影线,中性,等待,观察第二根 K 线
  • 开盘光头大阳线,做多信号 +1
  • 前一日下午盘在均线上方运行,尾盘稳定,做多信号 +1
  • 前一日高波动震荡,做多信号 -1
  • 开仓后做动态止损,随着价格上升,提高止损位
  • 开仓后第一次斜率变缓不止盈,等待第二次拉升或跌到止损位
  • 开仓后出现震荡,持续 10 根 K 线不创新高后止盈出场
  • 二次拉升后斜率变缓后止盈出场
  • 连续 3 根光脚阴线后止损出场

python 蜡烛图
https://www.statology.org/matplotlib-python-candlestick-chart/
https://www.geeksforgeeks.org/how-to-create-a-candlestick-chart-in-matplotlib/
https://www.highcharts.com.cn/docs/candlestick

大数据

Flink 从 0 到 1 学习
https://github.com/zhisheng17/flink-learning
http://www.54tianzhisheng.cn/2018/10/13/flink-introduction/#

数据分层详解ODS、DWD、DWM、DWS、ADS
https://blog.csdn.net/qq_38730338/article/details/122713887

数据仓库

  • Data warehouse(可简写为DW或者DWH)数据仓库,是在数据库已经大量存在的情况下的一整套包括了etl、调度、建模在内的完整的理论体系。
  • 数据仓库的方案建设的目的,是为前端查询和分析作为基础。
  • 数据仓库并不是数据的最终目的地,而是为数据最终的目的地做好准备,这些准备包含:清洗、转义、分类、重组、合并、拆分、统计等

分层:

  • ODS: Operation Data Store 数据准备区,也称为贴源层
    • 经过抽取、洗净、传输,也就是ETL过程之后进入本层。
    • 为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可。
    • 来源:
      • 业务库:
        • 离线:sqoop 定时抽取数据;
        • 实时: 使用 canal 监听 mysql 的 binlog 日志
      • 埋点日志:
        • 离线:日志一般是以文件的形式保存,可以选择使用 flume 来定时同步;
        • 实时:spark streaming,Flink、Kafka
      • 消息队列:ActiveMQ、Kafka
  • DWD:数据细节层 data warehouse details
    • 业务层和数据仓库的隔离层,保持和ODS层一样的数据颗粒度
    • 主要是对 ODS 数据层做一些数据的清洗和规范化的操作,比如去除空数据、脏数据、离群值等。
    • 为了提高 ODS 的易用性,该层通常会才采用一些维度退化方法,将维度退化至事实表中,减少事实表和维表的关联。
  • DWM:数据中间层 Data Warehouse Middle
    • 对通用的核心维度进行聚合操作,算出相应的统计指标,提升公共指标的复用性。
  • DWS:数据服务层 Data Warehouse Service
    • 整合汇总成分析某一个主题域,用于提供后续的业务查询,OLAP 分析,数据服务等。
    • 该层的数据表会相对较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。
  • ADS:数据应用层 Application Data Service
    • 一般会存放在 ES、Redis、PostgreSQL 供数据产品和数据分析使用的数据。
    • 也可存放在 hive 或者 Druid 中,供数据分析和数据挖掘使用,常用的数据报表应该存在这里。
  • Fact Table: 事实表
    • 指存储有事实记录的表,比如系统日志、销售记录等。
    • 事实表的记录在不断地增长,比如电商的商品订单表
  • Dimension Table:维表层
    • 与事实表相对应的一种表,它保存了维度的属性值,可以跟事实表做关联。
    • 相当于将事实表上经常重复出现的属性抽取、规范出来用一张表进行管理。
    • 高基数维度数据:一般是用户资料表、商品资料表类似的资料表,数量较大。
    • 低基数维度数据:一般是配置表,比如枚举字段对应的中文含义,或者日期维表等,数量较小。

https://blog.csdn.net/weixin_37536020/article/details/106815387
Spark DAG(Directed Acyclic Graph) 有向无环图

概念理解:

  • 一个 Transform 操作(即懒加载方法)转换成一个 RDD。
  • RDD 之间存在依赖关系,最后通过一个 Action 操作函数对数据进行计算。
  • 我们把 RDD 间组成的计算链,称为 DAG。
  • 通过 RDD 间的依赖关系,可以跟踪依赖链找到该分区的父分区,重新计算该分区数据,
    • 采用这种逆推父分区,恢复数据的方式,实现了 RDD 的容错机制。
  • Action 操作对应一个 Job 任务,根据依赖关系,将 DAG 划分为不同的阶段。
  • Task 对应一个分区,一个 Task 就是一个分区,RDD1 有 2 个分区,即 2 个 Task。

RDD 之间的依赖关系:

  • 窄依赖:
    • 父分区和子分区存在一对一的关系,比如:map 、filter、union函数。
    • 不会引入Shuffle的概念,不会发生磁盘 IO 读写。
    • DAG 中连续连续多个窄依赖,会放到一起执行。
  • 宽依赖:
    • 父分区和子分区存在多对多的关系,比如groupBy、sortByKey 等带分组功能函数。
    • 引入了 Shuffle 的概念,会发生磁盘 IO 读写。
    • 宽依赖数据丢失时,可以从 Shuffle 临时文件恢复数据

执行 Job 阶段划分过程:

  • Spark 在执行 Transformation 类型操作时,都不会立即执行,而是懒计算。
  • 执行若干步 Transformation 类型操作后,一旦遇到 Action 操作,才会真正触发计算。
  • 从当前 Action 往前回溯,如果遇到的是窄依赖则应用流水线优化,继续往前找,直到遇到一个宽依赖。
  • 依赖要进行 Shuffle,不执行流水线优化,所以将这一阶段执行过程组装为一个 Stage。
  • 再从当前宽依赖开始向前找,重复刚才的步骤,从而将整个 DAG 划分为若干 Stage。

一文学完Spark常用算子(Spark算子大全)
https://blog.csdn.net/u011109589/article/details/125675177

Spark 算子分为以下三类:

  • Value
    • 输入分区与输出分区一对一型: map flatMap mapPartitions glom
    • 输入分区与输出分区多对一型: union cartesian
    • 输入分区与输出分区多对多型: grouBy
    • 输出分区为输入分区子集型: filter distinct subtract sample takeSample
    • Cache: cache persist
  • Key-Value
    • 输入分区与输出分区一对一: mapValues
    • 对单个 RDD 或两个 RDD 聚集: combineByKey reduceByKey partitionBy
    • 两个RDD聚集: Cogroup
    • 连接: join leftOutJoin rightOutJoin
  • Action
    • 无输出: foreach
    • HDFS: saveAsTextFile saveAsObjectFile
    • Scala: collect reduceByKeyLocally lookup count top reduce fold aggregate
  • 转换算子
    • Value类型: 1. map 2. mapPartitions 3. mapPartitionsWithIndex 4. flatMap 5. glom 6. groupBy 7. filter 8. sample 9. distinct 10. coalesce 11. sortBy
    • 双Value类型: 1. intersection 2. union 3. subtract 4. zip
    • K-V类型: 1. partitionBy 2. reduceByKey 3. groupByKey 4. aggregateByKey 5. foldByKey 6. combineByKey 7. join 8. sortByKey 9. mapValues 10. cogroup
  • 行动算子 1. reduce 2. collect 3. count 4. first 5. take 6. takeOrdered 7. aggregate 8. fold 9. countByValue 10. countByKey 11. foreach 12. save

spark 下载
https://spark.apache.org/downloads.html
https://mirrors.tuna.tsinghua.edu.cn/apache/spark/

wget https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-3.3.1/spark-3.3.1-bin-hadoop3-scala2.13.tgz
tar xf spark-3.3.1-bin-hadoop3-scala2.13.tgz
cd spark-3.3.1-bin-hadoop3-scala2.13
./bin/spark-shell --version

Spark:从“大数据的Hello World”开始
https://zhuanlan.zhihu.com/p/407652473

scala> import org.apache.spark.rdd.RDD
import org.apache.spark.rdd.RDD

scala> val rootPath: String = "."
val rootPath: String = .

scala> val file: String = s"${rootPath}/README.md"
val file: String = ./README.md

scala> val lineRDD: RDD[String] = spark.sparkContext.textFile(file)
val lineRDD: org.apache.spark.rdd.RDD[String] = ./README.md MapPartitionsRDD[3] at textFile at <console>:1

scala> val wordRDD: RDD[String] = lineRDD.flatMap(line => line.split(" "))
val wordRDD: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[4] at flatMap at <console>:1

scala> val cleanWordRDD: RDD[String] = wordRDD.filter(word => !word.equals(""))
val cleanWordRDD: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[5] at filter at <console>:1

scala> val kvRDD: RDD[(String, Int)] = cleanWordRDD.map(word => (word, 1))
val kvRDD: org.apache.spark.rdd.RDD[(String, Int)] = MapPartitionsRDD[6] at map at <console>:1

scala> val wordCounts: RDD[(String, Int)] = kvRDD.reduceByKey((x, y) => x + y)
val wordCounts: org.apache.spark.rdd.RDD[(String, Int)] = ShuffledRDD[7] at reduceByKey at <console>:1

scala> wordCounts.map{case (k, v) => (v, k)}.sortByKey(false).take(5)
val res0: Array[(Int, String)] = Array((23,the), (16,to), (15,Spark), (13,for), (9,##))

简化

text_file = sc.textFile("hdfs://...")
counts = text_file.flatMap(lambda line: line.split(" ")) \
             .map(lambda word: (word, 1)) \
             .reduceByKey(lambda a, b: a + b)
counts.saveAsTextFile("hdfs://...")

Spark和Flink的对比,谁才是大数据计算引擎王者?
https://blog.csdn.net/educast/article/details/119929704

Spark详解(02) - Spark概述
https://www.cnblogs.com/meanshift/p/16063784.html

Spark 集群的独立部署环境

  • 不需要依赖其他的资源调度框架,自身就实现了资源调度的功能
  • 环境中还有其他两个核心组件:Master 和 Worker
  • Master 是一个进程,主要负责资源的调度和分配,并进行集群的监控等职责,类似于 Yarn 环境中的 RM
  • Worker 也是进程,一个 Worker 运行在集群中的一台服务器上,由 Master 分配资源对数据进行并行的处理和计算,类似于 Yarn 环境中 NM。

ApplicationMaster

  • Hadoop 用户向 YARN 集群提交应用程序时,提交程序中应该包含 ApplicationMaster,
    • 用于向资源调度器申请执行任务的资源容器 Container
    • 运行用户自己的程序任务 job
    • 监控整个任务的执行
    • 跟踪整个任务的状态
    • 处理任务失败等异常情况。
  • 说的简单点就是,ResourceManager(资源)和 Driver(计算)之间的解耦合靠的就是 ApplicationMaster。

Yarn 环境

  • Client 和 Cluster,主要区别在于:Driver 程序的运行节点位置。
  • Yarn Client 模式
    • Client 模式将用于监控和调度的 Driver 模块在客户端执行,而不是在 Yarn 中,所以一般用于测试。
    • Driver 在任务提交的本地机器上运行
    • Driver 启动后会和 ResourceManager 通讯申请启动 ApplicationMaster
    • ResourceManager 分配 container,在合适的 NodeManager 上启动 ApplicationMaster,负责向 ResourceManager 申请 Executor 内存
    • ResourceManager 接到 ApplicationMaster 的资源申请后会分配 container,然后 ApplicationMaster 在资源分配指定的 NodeManager 上启动 Executor 进程
    • Executor 进程启动后会向 Driver 反向注册,Executor 全部注册完成后 Driver 开始执行 main 函数
    • 之后执行到 Action 算子时,触发一个 Job,并根据宽依赖开始划分 stage,每个 stage 生成对应的 TaskSet,之后将 task 分发到各个 Executor 上执行。
  • Yarn Cluster 模式
    • Cluster 模式将用于监控和调度的 Driver 模块启动在 Yarn 集群资源中执行。一般应用于实际生产环境。
    • 在 YARN Cluster 模式下,任务提交后会和 ResourceManager 通讯申请启动 ApplicationMaster,
    • 随后 ResourceManager 分配 container,在合适的 NodeManager 上启动 ApplicationMaster,此时的 ApplicationMaster 就是 Driver。
    • 后续和 Yarn Client 一样

spark-关于spark分区的理解
https://blog.csdn.net/qq_34224565/article/details/108556055

  • 确切的说,spark 没有分区,是 RDD 有分区。分区是 spark 在内存中进行并行计算时的一块独立的空间,是 RDD 并行计算的最小单元。
  • RDD 的数据集在逻辑上被划分为多个分片,每一个分片称为分区,而每个分区的数值计算都是在一个任务中进行的。
  • 任务的个数,也是由 RDD (准确来说是 job 最后一个 RDD)的分区数决定。
  • 数据源为 hdfs 时,rdd 的分区数由 hdfs 的 block 数决定,类似于 mr 的分片数跟 block 数相同,是考量了磁盘 IO 的性能后作出的选择。
  • 正常情况下,数据源为 hdfs 时,读取时是不需要设置分区数的,设置了反而会影响效率。
  • 分区数越多越好吗?
    • 分区数太多意味着任务数太多,每次调度任务也是很耗时的,所以分区数太多会导致总体耗时增多。
    • 如果一个分区的数据量过小,则 task 的调度会影响效率,如果分区数相对于 cores 过小,则会造成资源浪费。
  • 分区数太少会有什么影响?
    • 分区数太少的话,会导致一些节点没有分配到任务;
    • 分区数太少的话,会导致一些节点没有分配到任务;
    • 分区数不合理,会导致数据倾斜问题;
  • 官方建议 partitionNum 为 executor-cores * num-executor 的 2~3 倍。

分区方式
https://blog.csdn.net/dmy1115143060/article/details/82620715

  • Spark包含两种数据分区方式:HashPartitioner(哈希分区)和RangePartitioner(范围分区)。
  • 一般而言,对于初始读入的数据是不具有任何的数据分区方式的。
  • 数据分区方式只作用于<Key,Value>形式的数据。
  • 当一个 Job 包含 Shuffle 操作类型的算子时,如groupByKey,reduceByKey etc,此时就会使用数据分区方式来对数据进行分区
  • 在 Spark Shuffle 阶段中,共分为 Shuffle Write 阶段和 Shuffle Read 阶段
    • Shuffle Write 阶段中,Shuffle Map Task 对数据进行处理产生中间数据,然后再根据数据分区方式对中间数据进行分区。
    • Shffle Read 阶段中的 Shuffle Read Task 会拉取 Shuffle Write 阶段中产生的并已经分好区的中间数据。

Scala基础教程
https://blog.csdn.net/zzy979481894/article/details/123890912

其它

  • 俗话说:兔子不吃窝边草 可俗话又说:近水楼台先得月
  • 俗话说:宰相肚里能撑船 可俗话又说:有仇不报非君子
  • 俗话说:人不犯我,我不犯人。 可俗话又说:先下手为强,后下手遭殃。
  • 俗话说:男子汉大丈夫,宁死不屈。可俗话又说:男子汉大丈夫,能屈能伸。
  • 俗话说:打狗还得看主人  可俗话又说:杀鸡给猴看。
  • 俗话说:车到山前必有路  可俗话又说:不撞南墙不回头
  • 俗话说:礼轻情谊重        可俗话又说:礼多人不怪
  • 俗话说:人多力量大        可俗话又说:人多嘴杂
  • 俗话说:一个好汉三个帮  可俗话又说:靠人不如靠己
  • 俗话说:人往高处走        可俗话又说:爬的高,摔得重。

电路

德州仪器电路仿真 TINA-TI(TM)模拟器简介
http://training.eeworld.com.cn/TI/video/18813

整流电路
https://blog.csdn.net/cherrychen666/article/details/112986395

Tina-TI——小巧好用又高效的原理图仿真软件
https://zhuanlan.zhihu.com/p/437404464

  • TI 提供了很多仿真样例,包括音频、比较器、控制环路、电流环路、振荡器、功率放大器、传感器等等。
  • 仿真分析包括直流分析、交流分析、傅里叶分析、噪声分析等。
  • 直流分析可以用来测量某一些节点电压和直流传输特性等,如下可以测量某些节点的电压值。
  • 交流分析包括节点电压、振幅、相位、时延、奈奎斯特等。
  • 交流中分析bode图的幅频和相位曲线。
  • 测量工具包括常见的信号分析仪、示波器、XY记录器、函数发生器、万用表。

aws

ddb test

import boto3
from boto3.dynamodb.conditions import Key
ddb = boto3.resource('dynamodb')

test = ddb.Table('test')

print('insert data')
test.put_item(Item={'domain': 'hello.com', 'email': 'hao@hello.com'})
test.put_item(Item={'domain': 'hello.com', 'email': 'jimmy@hello.com'})
test.put_item(Item={'domain': 'gmail.com', 'email': 'onlytiancai@gmail.com'})

print('scan data')
response = test.scan()
for i in response['Items']:
    print(i)

print('query data')
response = test.query(
    KeyConditionExpression=(Key('domain').eq('hello.com') & Key('email').eq('hao@hello.com'))
)
for i in response['Items']:
    print(i)

print('delete data')
test.delete_item(Key={'domain': 'hello.com', 'email': 'hao@hello.com'})
test.delete_item(Key={'domain': 'hello.com', 'email': 'jimmy@hello.com'})
test.delete_item(Key={'domain': 'gmail.com', 'email': 'onlytiancai@gmail.com'})

DynamoDB基本概念
https://zhuanlan.zhihu.com/p/72397412

DynamoDB-二级索引
https://zhuanlan.zhihu.com/p/72610885

202210

后台开发

微服务应用 API 设计规范
https://blog.jaggerwang.net/microservice-application-api-design-specification/

API 版本

  • 对于内部使用的 API,自己可以控制客户端升级节奏,应避免使用 API 版本,因为维护多版本 API 的成本很高。
  • 对于对外开放的 API,由于无法控制使用方客户端升级节奏,那么可以通过多版本 API 来实现平滑升级,在废弃老版 API 之前给使用方留足够的升级时间。
  • API 版本号可在不同的层级上添加,以前面的创建用户 API /api/user/user/create 为例,按作用范围由大到小有以下几种方式:

code

/api/v1/user/user/create 在应用网关层级添加(推荐);
/api/user/v1/user/create 在微服务层级添加;
/api/user/user/v1/create 在模块层级添加;
/api/user/user/create/v1 在 API 层级添加;

硬件

按下键盘后为什么屏幕上就会有输出
https://www.51cto.com/article/698488.html

内存中有这样一部分区域,是和显存映射的。啥意思,就是你往上图的这些内存区域中写数据,相当于写在了显存中。而往显存中写数据,就相当于在屏幕上输出文本了。

mov [0xB8000],'h' 
mov [0xB8002],'e' 
mov [0xB8004],'l' 
mov [0xB8006],'l' 
mov [0xB8008],'o' 

I2C接口与SPI和UART接口的区别
https://blog.csdn.net/chenhuanqiangnihao/article/details/123359352

总线接口 UART I2C SPI USB的异同点

  • UART(RS232) 通用异步串行口,速率不快,可全双工,结构上一般由波特率产生器、UART 发送器、UART 接收器组成,硬件上两线,一收一发。
  • SPI 高速同步串行口,高速,可全双工,收发独立,同步接口,可实现多个 SPI 设备互联,硬件 4 条线。
  • I2C 双向、两线、串行、多主控接口标准。速率不快,半双工,同步接口,具有总线仲裁机制,非常适合器件间近距离经常性数据通信,可实现设备组网。
  • USB 通用串行总线,高速,半双工,由主机、hub、设备组成。设备可以与下级 hub 相连构成星型结构。

OLED显示屏是利用有机电自发光二极管制成的显示屏,其中每一个像素点就是一个led。

ESP8266、ESP32和STM32的区别
https://baijiahao.baidu.com/s?id=1730615149655141528

  • ESP8266,价格 10 元左右。
  • ESP32,是 ESP8266 的升级版本,速度更快还带有蓝牙 4.2 和蓝牙低功耗,价格在20元左右
    • 优点:
      • ESP32 可用引脚比 ESP8266 更多
      • 双核处理器能够多线程实时处理;
      • 高速主频 240MHZ,对比 STM32F1 的 72MHZ 和 STM32F4 的168MHZ,速度快很多,价格 STM 系低出非常多;
      • 自带蓝牙和 Wifi,不用再花费成本去购置额外模块,成本更加低;
      • 编程上可以使用 arduino 环境,编程难度比 STM32 低很多,开源项目很多,开发速度很快。
    • 缺点:
      • 引脚数量过少是现阶段 ESP32 的硬伤之一
  • STM32 是一种基于ARM架构的32位微控制器。
    • 优点:
      • 通讯接口十分丰富,如 USART,I2C,SPI,CAN,以太网通讯等;
      • 可用 GPIO 数量非常多,可以控制大量设备;
      • 定时器数量很多,中断系统也十分完善,能实现非常复杂的逻辑;
      • 多路 ADC 和 DAC 功能,可用于读取大量传感器等;
      • 可运行 Free RTOS,RT thread,UCOS 等实时操作系统,可用于控制复杂系统;
      • 可连接 SD 卡,LCD 屏,有摄像头接口,可读取 USB 功能等。
    • 缺点:
      • STM32 的价格一直在上涨。如果不需要以太网、摄像头和 DACD 等功能时可以考虑 F1 系列。
      • 上手有一定难度,需要一定的时间。

前端

最简洁Vue+Electron项目搭建教程
https://zhuanlan.zhihu.com/p/335225253

vue3.x+ts项目创建,配置流程
https://blog.csdn.net/csl125/article/details/126000350

electron install

npm config set ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/
export ELECTRON_MIRROR=https://npm.taobao.org/mirrors/electron/
npx electron-forge import
npm install --save-dev electron --registry=https://registry.npm.taobao.org
npm install --save-dev @electron-forge/cli --registry=https://registry.npm.taobao.org
npx electron-forge import
npm run make

electron-vite | 新一代electron开发构建工具
https://juejin.cn/post/7084126780390375461

├──src
|  ├──main
|  |  ├──index.js
|  |  └──...
|  ├──preload
|  |  ├──index.js
|  |  └──...
|  └──renderer
|     ├──src
|     ├──index.html
|     └──...
├──electron.vite.config.js
└──package.json

搭配 TypeScript 使用 Vue
https://cn.vuejs.org/guide/typescript/overview.html

深入理解 TypeScript
https://jkchao.github.io/typescript-book-chinese/#why

https://github.com/sindresorhus/electron-store
https://github.com/louischatriot/nedb

网络

iperf3-vsock: how to measure VSOCK performance
https://stefano-garzarella.github.io/posts/2019-08-22-vsock-iperf3/

Iperf3网络性能测试工具详解教程
https://www.cnblogs.com/xuanbjut/p/14144255.html

  • Iperf是美国伊利诺斯大学(University of Illinois)开发的一种开源的网络性能测试工具。可以用来测试网络节点间(也包括回环)TCP或UDP连接的性能,包括带宽、抖动以及丢包率,其中抖动和丢包率适应于UDP测试,而带宽测试适应于TCP和UDP。
  • Iperf是一款基于TCP/IP和UDP/IP的网络性能测试工具,可以用来测量网络带宽和网络质量,提供网络延迟抖动、数据包丢失率、最大传输单元等统计信息。网络管理员可以根据这些信息了解并判断网络性能问题,从而定位网络瓶颈,解决网络故障。

code

# server
iperf3 -s -i 1 -p 5200
# client
iperf -c 127.0.0.1 -i 1 -t 60 -p 5200

带宽测试通常采用UDP模式,因为能测出极限带宽、时延抖动、丢包率。在进行测试时,首先以链路理论带宽作为数据发送速率进行测试,例如,从客户端到服务器之间的链路的理论带宽为100Mbps,先用-b 100M进行测试,然后根据测试结果(包括实际带宽,时延抖动和丢包率),再以实际带宽作为数据发送速率进行测试,会发现时延抖动和丢包率比第一次好很多,重复测试几次,就能得出稳定的实际带宽。

# server
iperf3 -s -i 1 -p 5210
# client
iperf3 -u -c 127.0.0.1 -b 100m -t 10 -p 5210 -b 40G

TCP 和 UDP 可以使用同一个端口吗?
https://www.51cto.com/article/714728.html

linux

CPU内存乱序访问与内存屏障
https://blog.csdn.net/denglin12315/article/details/124488188

CPU内存乱序访问发生的原因

  • 编译优化,指令重排导致乱序
    • 编译器在编译代码时不感知多线程并发执行情况。
  • CPU运行,指令执行乱序
    • 在单核CPU 上,不考虑编译器优化导致乱序的前提下,多线程执行不存在内存乱序访问的问题。

什么时候用内存屏障

  • 单线程代码的程序不需要关心内存乱序的问题。
  • 在多线程编程中,由于使用互斥量,信号量已经隐式包含各种内存屏障,内存乱序的问题同样不需要考虑了。
  • 只有当使用无锁(lock-free)技术时,才需要考虑在合适的地方加入合适的memery barrier

Linux内存屏障使用注意事项:

  • 所有的 CPU Memory barrier(除了数据依赖barrier<smp_read_barrier_depends()>之外)都隐含了编译器barrier。
  • 这里的 SMP 开头的 Memory barrier 会根据配置在单处理器上直接使用编译器 barrier,而在 SMP 上才使用 CPU Memory barrier
  • CPU Memory barrier 中某些类型的 Memory barrier 需要成对使用

volatile 关键字与内存屏障

编译器在编译用 volatile 关键字修饰的变量的时候,对于该变量的访问操作,生成的指令会直接去该变量对应的内存中取值,而不会用寄存器暂存该变量的中间结果。

#define barrier() __asm__ __volatile__("": : :"memory")
#define mb() alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)    #读写屏障
#define rmb() alternative("lock; addl $0,0(%%esp)", "lfence", X86_FEATURE_XMM2)   #读屏障
#define wmb() alternative("lock; addl $0,0(%%esp)", "sfence", X86_FEATURE_XMM)    #写屏障

解决内核竟态的方法
https://blog.csdn.net/weixin_58458700/article/details/120497321

  • 中断屏蔽
    • 单核的cpu有效
    • 临界区很小,里面不可以有延时或者耗时的操作(copy_to_user)
    • 如果中断屏蔽的时间很长,会导致用户的数据丢失或内核的崩溃.
  • 自旋锁
    • 自旋锁是针对于多核处理器设计的
    • 自旋锁在上锁的时候会关闭抢占.
  • 信号量
    • 得不到锁的进程处于一个休眠的状态
    • 信号量不会关闭抢占
    • 保护的临界区可以很大
  • 互斥体
    • 保护的临界区可以很大,里面可以有延时,耗时,甚至休眠的操作
    • 在保护临界区较少的临界资源时,互斥体的效率高于信号量。
  • 原子变量/操作
    • 原子操作本身就是一个变量,这个变量的修改内核做了防竞态的过程。
    • 这个变量值修改的过程是通过内联汇编完成,对这个变量的操作看成一个不可被分割的整体。

Linux内核快速处理路径尽量多用slab而慎用kmalloc
https://blog.csdn.net/dog250/article/details/105544111

  • kmem_cache 是针对特定数据结构的独享内存池子,它以 最小化碎片 的原则为特定的场合提供 可高效访问 的内存,比如 sock,sk_buff 这些。
  • 当你调用 kmalloc(size, flags) 申请内存时,系统会根据你的size向上寻找一个最接近的kmem_cache,然后在其中为你分配所需的内存。
  • 并不是说 32 字节的结构体分配就一定会获得连续的内存,而 64 字节的就不会, 这完全取决于你的系统当前的整体 kmalloc 使用情况。
  • kmalloc 并不适合快速路径的内存分配,它只适合稳定的,离散的管理结构体的内存分配。
  • 大家之所以普遍喜欢用 kmalloc,因为它简单,快捷,少了 kmem_cache 的 create 和 destroy 的维护操作。
  • kmalloc 有个副作用,就是它只有固定的大小,比如你分配一个 24 字节大小的结构体,事实上系统会给你 32 字节。
  • 在诸如网络协议栈处理这种相对快速的路径中,比如skbuff,sock,nfconntrack 等结构体均是在自行维护的独享 kmem_cache 中被管理的,这保证了内存分配的尽可能的连续性,尽可能的最少碎片。
    • kmem_cache 的 obj 可以随意释放。
    • kmem_cache 的 obj 按照释放的逆序进行分配。
    • kmem_cache 的 free 相当于 push 操作,而 alloc 相当于 pop 操作。
  • 在连续的内存上进行遍历,其性能远超在离散的内存上进行遍历!
  • 我们使用自行维护的kmem_cache slab时,当从中分配的对象插入链表时,要尽量按照其内存地址的升序插入链表确定的位置,这样在遍历链表时可以达到最大化预取的效果。
    • 尽可能节省内存,保持内存的紧凑。
    • 提高 CPU dcache 的命中率,最大化 preload 效果。
  • 根据 slab 对象的内存使用 hlistaddbefore[rcu],hlistaddbebind[rcu]将对象插入 hlist 的特定位置,而不是简单使用 hlistaddhead。

ssh 隧道

ssh -CfNg -L 48175:127.0.0.1:48175 ubuntu@8.8.8.8

按进程关键字杀进程

ps -C "ssh -CfNg -L 48175:127.0.0.1:48175" -o pid= | xargs kill

https://blog.csdn.net/zqixiao_09/article/details/79265789
linux上的自旋锁有三种实现:

  1. 在单cpu,不可抢占内核中,自旋锁为空操作。
  2. 在单cpu,可抢占内核中,自旋锁实现为“禁止内核抢占”,并不实现“自旋”。
  3. 在多cpu,可抢占内核中,自旋锁实现为“禁止内核抢占” + “自旋”。

非抢占式内核: 如果一个进程在内核态运行,其只有在以下两种情况会被切换:

  • 其运行完成(返回用户空间)
  • 主动让出 cpu(即主动调用 schedule 或内核中的任务阻塞——这同样也会导致调用 schedule)

抢占式内核: 如果一个进程在内核态运行,其只有在以下四种情况会被切换:

  • 其运行完成(返回用户空间)
  • 主动让出 cpu(即主动调用 schedule 或内核中的任务阻塞——这同样也会导致调用 schedule)
  • 当从中断处理程序正在执行,且返回内核空间之前(此时可抢占标志premptcount须为0) 。
  • 当内核代码再一次具有可抢占性的时候,如解锁及使能软中断等。

其它

  • 禁止内核抢占只是关闭“可抢占标志”,而不是禁止进程切换。
    • 显式使用 schedule 或进程阻塞(此也会导致调用schedule)时,还是会发生进程调度的。
  • 对于多核抢占与多核非抢占的情况,在使用自旋锁时,其情况基本是一致的。
    • 因为在多核抢占的情况下,使用自旋锁会禁止内核抢占,这样多核抢占就相当于多核非抢占的情况。

被自旋锁保护的临界区代码执行时,它不能因为任何原因放弃处理器:

  • 被自旋锁保护的临界区代码执行时,不能进入休眠。
  • 被自旋锁保护的临界区代码执行时,不能被被其他中断中断。
  • 被自旋锁保护的临界区代码执行时,内核不能被抢占。

所以现代处理器在处理自旋锁时都会设定自旋上限时间以防死锁. 另自旋锁在单核非抢占式CPU上是无效的.被设为空操作,不做任何事.

C++性能优化(十二)——自旋锁
https://blog.csdn.net/A642960662/article/details/123029988

互斥锁

  • 属于 sleep-waiting 类型锁。Linux Kernel 2.6.x 稳定版开始,Linux 的互斥锁都是 futex (Fast Usermode Mutex)锁。
  • Futex 是一个在 Linux 上实现锁定和构建高级抽象锁如信号量和 POSIX 互斥的基本工具。
  • Futex 是由用户空间的一个对齐的整型变量和附在其上的内核空间等待队列构成。
  • 多进程或多线程绝大多数情况下对位于用户空间的futex的整型变量进行操作(汇编语言调用 CPU 提供的原子操作指令来增加或减少)
  • 而其它情况下则需要通过代价较大的系统调用来对位于内核空间的等待队列进行操作(如唤醒等待的进程/线程或将当前进程/线程放入等待队列)。
  • 除了多个线程同时竞争锁的少数情况外,基于futex的lock操作是不需要进行代价昂贵的系统调用操作的。
  • 互斥锁实际上是 count=1 情况下的 semaphore。

互斥锁缺点:

  • 等待互斥锁会消耗时间,等待延迟会损害系统的可伸缩性。
  • 优先级倒置。低优先级的线程可以获得互斥锁,因此会阻碍需要同一互斥锁的高优先级线程。
  • 锁护送(lock convoying)。如果持有互斥锁的线程分配的时间片结束,线程被取消调度,则等待同一互斥锁的其它线程需要等待更长时间。

自旋锁(spin lock)

  • 属于 busy-waiting 类型锁。
  • 在多处理器环境中,自旋锁最多只能被一个可执行线程持有。
  • 如果一个可执行线程试图获得一个被其它线程持有的自旋锁,那么线程就会一直进行忙等待,自旋(空转),等待自旋锁重新可用。
  • 如果自旋锁未被争用,请求锁的执行线程便立刻得到自旋锁,继续执行。
  • 自旋锁不会使线程状态发生切换,一直处于用户态,即线程一直都是 active 的;
  • 不会使线程进入阻塞状态,减少了不必要的上下文切换,执行速度快
  • 通常适用在时间极短的情况,因此操作系统的内核经常使用自旋锁。
  • 但如果长时间上锁,自旋锁会非常耗费性能。
  • 线程持有锁时间越长,则持有锁的线程被 OS调度程序中断的风险越大。
  • 如果发生中断情况,那么其它线程将保持旋转状态(反复尝试获取锁)。

互斥锁和自旋锁对比:

  • spinlock 不会使线程状态发生切换,mutex 在获取不到锁的时候会选择sleep。
  • spinlock 优点:没有耗时的系统调用,一直处于用户态,执行速度快。
  • spinlock缺点:一直占用 CPU,而且在执行过程中还会锁 bus 总线,锁总线时其它处理器不能使用总线。
  • mutex 获取锁分为两阶段
    • 第一阶段在用户态采用 spinlock 锁总线的方式获取一次锁,如果成功立即返回;
    • 否则进入第二阶段,调用系统的 futex 锁去 sleep,当锁可用后被唤醒,继续竞争锁。
  • mutex 优点:不会忙等,得不到锁会 sleep。
  • mutex 缺点:sleep 时会陷入到内核态,需要昂贵的系统调用。

几种自旋锁实现:

  • raw_spinlock:
    • 在单处理机环境中可以使用特定的原子级汇编指令 swap 和 test_and_set 实现进程互斥。
    • 多处理器环境目前多以锁总线形式保证 test_and_set 指令执行的原子性。
    • 由于传统自旋锁无序竞争的本质特点导致锁竞争争不公平。
      • 释放自旋锁时的重置操作将无效化所有其它正在忙等待的处理器的缓存。
      • 在处理器拓扑结构中临近自旋锁拥有者的处理器可能会更快地刷新缓存,因而增大获得自旋锁的机率。
    • 由于每个申请自旋锁的处理器均在全局变量 slock 上忙等待,系统总线将因为处理器间的缓存同步而导致繁重的流量。
  • ticket spinlock:
    • 排队自旋锁,线程将严格地按照申请顺序依次获取排队自旋锁,从而完全解决了不公平问题。
    • slock 字段被分成两部分 Owner 和 Next
      • 分别保存锁持有者和未来锁申请者的票据序号(Ticket Number)
      • 只有 Owner 和 Next 相等时,才表明锁处于未使用状态。
    • 在大规模多处理器系统和 NUMA 系统中
      • 由于执行线程均在同一个共享变量 slock 上自旋,申请和释放锁的时候必须对slock进行修改,将导致所有参与排队自旋锁操作的处理器的缓存变得无效。
      • 如果竞争比较激烈,频繁的缓存同步会导致繁重的系统总线和内存的流量,降低整体性能。
  • mcs spinlock:
    • 每个锁的申请者(处理器)只在一个本地变量上自旋。
    • 自旋锁的空间复杂度(即锁数据结构和锁操作所需的空间开销)为常数,占用空间大。
    • 在没有处理器缓存一致性协议保证的系统中也能很好地工作。
  • qspinlock:
    • 基于 mcs spinlock 设计思想但解决了接口不一致或空间太大的问题

在CPU较少的情况下, qspinlock的性能和ticket spinlock的性能差不多, 在CPU较多的情况下,qspinlock的性能远好于ticket spinlock。

Linux 性能优化
https://blog.csdn.net/a642960662/category_11641226.html

  • stress 压力测试工具
  • sysbench 压力测试工具
  • sysstat 性能监控工具
  • BCC 性能监控工具
  • 性能监控工具
  • 网络配置工具
  • 网络流量监控工具
  • 网络测试工具
  • Kernel Bypass
  • CPU 性能分析工具
  • CPU 性能优化原理
  • CPU 性能调优
  • CPU Cache
  • CPU 绑定
  • 中断绑定

从自旋锁、睡眠锁、读写锁到 Linux RCU 机制讲解
https://blog.csdn.net/u010180372/article/details/119470638

单核

  • 我们只需要通过关中断 就可以实现 sequential access
  • local_irq_disable() 和 preempt_disable() 就能实现

多核

  • 对于一个数据结构, 一旦他已经被一个 core 给 lock 了,当前运行在另一个 core 上的 thread 就需要等待锁释放, 所以需要一个循环等待的过程, 叫做自旋.
  • 具体实现的关键部分是通过 CPU 提供的一种 swap (test_and_set)指令,执行一个原子操作的读出值和放入新值。
    • 把 1 放进去, 拿出来 1, 说明被锁了
    • 把 1 放进去,拿出来 0,说明当前 thread/core 拿到这个锁

rics-v 代码

void acquire(struct spinlock *lk)
{
    push_off(); // disable interrupts to avoid deadlock.
    if(holding(lk)) panic("acquire");

    // On RISC-V, sync_lock_test_and_set turns into an atomic swap:
    //   a5 = 1
    //   s1 = &lk->locked
    //   amoswap.w.aq a5, a5, (s1)
    while(__sync_lock_test_and_set(&lk->locked, 1) != 0)
        ;

    // Tell the C compiler and the processor to not move loads or stores
    // past this point, to ensure that the critical section's memory
    // references happen strictly after the lock is acquired.
    // On RISC-V, this emits a fence instruction.
    __sync_synchronize();

    // Record info about lock acquisition for holding() and debugging.
    lk->cpu = mycpu();
}

内存屏障做的事情

  • 在编译器上很好理解就算防止编译过程的指令重排导致的持有锁状态更新和锁实际状态的不一致,
  • 而其在 CPU 上其实就是做一个简单的清空流水线,

spinlock 的 overhead

  • 内存屏障导致的清空流水线浪费一个流水线长度,
  • 循环等待的不断 CAS 的过程
  • amoswap 涉及多核 CPU 的 cache coherence MESI 的东西.

性能保证

  • 关抢占, 关中断后能够使需要锁的操作快速运行完,防止拿到锁后 context switch 出去导致别的线程/核心需要等该核心轮转
  • Linux spinlock 的实现:spinlock 持有 lock 之后关了 preempt 不关 interrupt。
  • 有一个 irqsave 版本会关,要点是:process 和 中断都想获取一个资源的时候,就要 avoid deadlock。

仔细看了下这个排队自旋锁ticket spinlock,解决锁竞争不公平的的实现太巧妙了,就用 Owner 和 Next 俩个半拉(用的一个union)的字段就完美解决了。

还了解了下用户态的自旋锁和内核态的自旋锁不是一回事,因为用户态的自旋锁不能关中断,也不能关抢占,所以不能防止进程被切走,所以临界区性能是无法得到高性能保障的,所以应用层的自旋锁要有一些特殊的优化,比如用 PAUSE 指令让 CPU 执行一些 NOP 类似的效果,避免 reorder 和频繁地清空流水线,再比如说在单核 CPU上提前 yield 防止忙等待,降低CPU的功耗和发热。

频繁的 CAS 操作会产生大量 hazard 的 load 和 store,让流水线指令重排机制认为出现 memory order violation,有可能为了安全而清空流水线,pause 能避免大量循环后再 context switch。

虚拟机 ESXi、PVE、unRaid对比
https://zhuanlan.zhihu.com/p/166352130

  • ESXi,是 VMWare vSphere Hypervisor 套件之下重要组件。前身是 ESX,依赖 Linux 源码,后来抛弃 Linux 源码做成了 ESXi。
    • 整个产品商用气息浓重,界面清晰易用,但硬件兼容性较差(主要面向服务器),没什么扩展性(毕竟不是 linux)。
  • PVE,全称 Proxmox Virtual Environment,是基于 Debian 的 Linux 系统,虚拟机内核为 KVM。
    • 硬件兼容性优秀。界面功能不强,很多操作要靠命令行,但扩展能力几乎是无限的。
  • unRaid,其实是个NAS系统,是基于Slackware的Linux系统,虚拟机内核也是KVM。
    • 磁盘阵列管理非常有特色,灵活性很高。同时还有很不错的插件、Docker和虚拟机支持。

mysql

中位数

https://stackoverflow.com/questions/1291152/simple-way-to-calculate-median-with-mysql

SELECT AVG(dd.val) as median_val
FROM (
SELECT d.val, @rownum:=@rownum+1 as `row_number`, @total_rows:=@rownum
  FROM data d, (SELECT @rownum:=0) r
  WHERE d.val is NOT NULL
  -- put some where clause here
  ORDER BY d.val
) as dd
WHERE dd.row_number IN ( FLOOR((@total_rows+1)/2), FLOOR((@total_rows+2)/2) );

两个数据库之间导数据
How can I transfer data between 2 MySQL databases?
https://stackoverflow.com/questions/3242504/how-can-i-transfer-data-between-2-mysql-databases

We have also used FIFO’s to great effect to avoid the overhead of actually writing to disk,
or if we do need to write to disk for some reason, to pipe it through gzip.

mkfifo /tmp/myfifo
gzip -c /tmp/myfifo > /tmp/mytable.csv.gz &
SELECT * FROM mytable INTO OUTFILE '/tmp/myfifo'
  FIELDS TERMINATED BY ',' 
  OPTIONALLY ENCLOSED BY '"' 
  ESCAPED BY '\\\\' 
  LINES TERMINATED BY '\\n' ;

gunzip -c /tmp/mytable.csv.gz > /tmp/myfifo &
LOAD DATA INFILE '/tmp/myfifo' INTO TABLE mytable 
  FIELDS TERMINATED BY ',' 
  OPTIONALLY ENCLOSED BY '"' 
  ESCAPED BY '\\\\' 
  LINES TERMINATED BY '\\n' ;

How to take mysql dump of selected columns of a table
https://stackoverflow.com/questions/15264597/how-to-take-mysql-dump-of-selected-columns-of-a-table

mysql> CREATE TABLE `tempTable` AS SELECT `columnYouWant` from `table`;
$> mysqldump yourDB tempTable > temp.sql

$> mysql yourDB < temp.sql
mysql> RENAME TABLE `table` TO `tableBackup`, `tempTable` TO `table`;

查看每个表的大小

SELECT
  TABLE_NAME AS `Table`,
  ROUND((DATA_LENGTH + INDEX_LENGTH) / 1024 / 1024) AS `Size (MB)`
FROM
  information_schema.TABLES
WHERE
  TABLE_SCHEMA = "dirtable"
ORDER BY
  (DATA_LENGTH + INDEX_LENGTH)
DESC
limit 15;

流媒体

SRS是一个简单高效的实时视频服务器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT/GB28181。
https://ossrs.net/lts/zh-cn/docs/v4/doc/introduction

开源复刻:OBS如何支持直播多人连麦,可连麦的在线发布会
https://github.com/ossrs/srs/issues/2749

GO

Go语言中你不知道的Interface详解
https://www.jb51.net/article/135149.htm

传统接口的缺陷

  • 侵入式通过 implements 把实现类与具体接口绑定起来了,因此有了强耦合;
  • 如果我修改了接口,比如改了接口方法,则实现类必须改动;
  • 如果我希望实现类再实现一个接口,实现类也必须进行改动;
  • 后续跟进者,必须了解相关的接口。

GO 接口的优点

  • 只要实现了与接口定义相同的方法,就算实现了某个接口,最重要的,随着代码的增加,你的类结构不会像 Java 那样发生爆炸。
  • 实现类的时候也不需要像 Java、PHP 一样引入各种接口,有可能你定义类的时候,某个接口还不存在。

elasticsearch

elasticsearch性能优化(一)
https://www.cnblogs.com/jelly12345/p/15322814.html

TF/IDF vs BM2.5
https://zhuanlan.zhihu.com/p/573284091
https://blog.csdn.net/qq_40859560/article/details/109147840

TF/IDF

  • 直觉上,一个词项在文档中出现次数越多,那么该词项和文档的相关性也应该越大。
  • 文档频率越大的词,在文档中越常见,区分作用越小,那么权重也应当越小。
  • 优点:
    • 简单,快速,如果语料库是不变的话,可以提前离线计算好语料库中所有词的 tfidf 值
  • 缺点:
    • 仅以“词频”度量词的重要性,后续构成文档的特征值序列,词之间各自独立,无法反映序列信息
    • tfidf 得到是一个稀疏而庞大的矩阵,需要采用降维方式,才方便做后续的文本任务
      • 而降维可能会损失一些信息,同时降维的也会提高模型的复杂度,而失去了原本快速的优点
    • tfidf 得到的 embedings 再输入后续的模型,做文本分类、文本匹配等任务,在效果上通常会差于采用词向量模型训练得到的 embedding。

BM25

  • BM25与之不同,它在TF计算方法中增加了一个常量k,用来限制TF值的增长极限。
  • 业务上可以理解为某一个因素的影响强度不能是无限的,而是有个最大值,这也符合我们对文本相关性逻辑的理解。
  • bm25 其实就是把 query 中每个词,在每篇文档中的 tfidf(改良后的)值求和即为该query与该文档的相似性得分。
  • 优点
    • 可以方便线下做离线先计算好文档中出现的每一个词的 idf 并保存为一个字典
      • 当用户搜了一个 query,直接分词然后查字典就能得到这个词的 idf,如果字典中没有idf值无意义,因为R=0。同于tfidf。

202209

mysql

数据同步平台CloudCanal的透明化、可视化运维之道
https://zhuanlan.zhihu.com/p/409094498

数据中台
https://gitee.com/zrxjava/srt-data
https://toscode.gitee.com/LuckyFishSpace/datax-cloud
https://gitee.com/LarkMidTable/LarkMidTable
https://gitee.com/475660/databand
https://gitee.com/WeBank/DataSphereStudio

dataease + cloudcanal + clickhouse

分布式存储:HDFS、HBase
行式关系存储:MySQL、Oracle
列式存储:ClickHouse
列族存储:HBase、Cassandra
文档库:ElasticSearch、MongoDB

查看默认密码

sudo cat /etc/mysql/debian.cnf

修改 datadir

systemctl stop mysql
mv /var/lib/mysql /data_ext/mysql_data_dir
# 父目录要有cd的权限
chmod o+x /data_ext

vi /etc/mysql/mysql.conf.d/mysqld.cnf
    datadir = /data_ext/mysql_data_dir


vi  /etc/apparmor.d/usr.sbin.mysqld
    # Allow data dir access
      /data_ext/mysql_data_dir/ r,
      /data_ext/mysql_data_dir/** rwk,
systemctl restart apparmor
systemctl start mysql

# 查看日志
journalctl -ru mysql

show variables like '%datadir%';

linux

TODO:
一篇文章带你读懂 io_uring 的接口与实现
https://zhuanlan.zhihu.com/p/380726590

存储大师班 | Linux IO 模式之 io_uring
https://zhuanlan.zhihu.com/p/389978597

https://man.archlinux.org/man/io_uring.7
https://blogs.oracle.com/linux/post/an-introduction-to-the-io-uring-asynchronous-io-framework

挂硬盘

lsblk
fdisk -l
parted /dev/xvdg
    mklabel gpt
    print
    mkpart primary 0% 100% 
    q
fdisk -l

mkfs.ext4 -T largefile /dev/xvdg1
mkdir /data_ext2
mount -t ext4 /dev/xvdg1 /data_ext2
echo '/dev/xvdg1 /data_ext2  ext4    defaults    0   0'  >>/etc/fstab

mkfs.xfs -f -n ftype=1 /dev/nvme1n1
mkdir /data_ext
mount -t xfs /dev/nvme1n1 /data_ext
echo '/dev/nvme1n1 /data_ext xfs  defaults    0   0'  >>/etc/fstab

扩展磁盘

在 aws 的 ebs console 修改卷的大小
lsblk
    nvme0n1     259:0    0   40G  0 disk
    └─nvme0n1p1 259:1    0   20G  0 part /
sudo growpart /dev/nvme0n1 1
df -hT
    Filesystem     Type      Size  Used Avail Use% Mounted on
    /dev/root      ext4       20G   20G  277M  99% /
# ext4
sudo resize2fs /dev/nvme0n1p1
# xfs 
sudo xfs_growfs -d /data_ext
df -hT /
    Filesystem     Type  Size  Used Avail Use% Mounted on
    /dev/root      ext4   39G   20G   20G  50% /

putty 免密无法登录 ubuntu 20.04

pubkeyauthentication yes
pubkeyacceptedkeytypes ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,ssh-ed25519-cert-v01@openssh.com,rsa-sha2-512-cert-v01@openssh.com,rsa-sha2-256-cert-v01@openssh.com,ssh-rsa-cert-v01@openssh.com,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa

shell for

  • for 循环在实际生成中应用非常多,避免人工重复的去操作某个事情

  • for 循环中的列表支持正则表达式

  • for 循环中使用(()),双括号内支持 C 语言的命令

  • for 循环中的变量,只是循环去取值列表中取值,然后进行 do 操作,所以取值列表中的参数个数,决定了循环的次数

    for i in {1…5};do echo $i;done
    for((i=1;i<=5;i++));do echo $i;done
    for i in seq 5;do echo $i;done

    for IP in cat /root/for/ip.txt #ip文件为存放ip地址的
    do
    ping -c 3 -i 0.2 -w 3 $IP &>/dev/null # -c 3 ping 3 次主机 -i 0.2 ping主机间隔 -w 3 ping主机超时间隔
    if [ $? -eq 0 ];then
    echo “host $IP is up”
    else echo “host $IP is down”
    fi
    done

    for user in cat /root/for/a.txt #a.txt为存放用户名单文件
    do
    if grep $user /etc/passwd &>/dev/null; then #检查用户是否存在
    echo “$user用户已经存在”
    elif [ -d /home/$user ];then #检查home下是否存在和用户相同的目录
    echo “$user用户存在宿主目录”
    else useradd $user #添加用户并设置初始密码
    echo “123456” |passwd --stdin $user &>/dev/null
    echo “$user用户已经创建,初始密码为:123456”
    fi
    done

qemu-system-arm仿真vexpress-a9踩坑记
https://www.jianshu.com/p/91baa4d140a2

Das U-Boot 是一个主要用于嵌入式系统的引导加载程序,可以支持多种不同的计算机系统结构,包括PPC、ARM、AVR32、MIPS、x86、68k、Nios与MicroBlaze。这也是一套在GNU通用公共许可证之下发布的自由软件。

qemu 挂 U 盘

qemu-img create -f raw disk.img 512M
mkfs -t ext4 ./disk.img
mkdir tmpfs
mount -o loop ./disk.img tmpfs/

vi tmpfs/hello.c
    #include <stdio.h>
    int main()
    {
        printf("HelloWorld! \n");
        return 0;
    }

arm-linux-gnueabi-gcc tmpfs/hello.c -o tmpfs/hello
arm-linux-gnueabi-gcc -static tmpfs/hello.c -o tmpfs/hello

ls tmpfs/
    hello  hello.c  lost+found
file tmpfs/hello
    tmpfs/hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=ee8ecff9cbfca92688bbbe7dd4e721ce9e6d23ce, not stripped
umount tmpfs

file disk.img
    disk.img: Linux rev 1.0 ext4 filesystem data, UUID=31c631fb-08fc-4874-8306-e2eae5441050 (extents) (64bit) (large files) (huge files)

qemu-system-arm -M vexpress-a9 -m 256M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -sd ./disk.img

ls /dev/mmcblk0* -l
    brw-rw----    1 0        0         179,   0 Sep 26 10:23 /dev/mmcblk0
mount -t ext4 /dev/mmcblk0 /mnt/
ls /mnt/
    hello       hello.c     lost+found

Linux ARM 环境
https://zhuanlan.zhihu.com/p/146580665

wget https://mirrors.tuna.tsinghua.edu.cn/kernel/v5.x/linux-5.4.5.tar.gz
wget https://busybox.net/downloads/busybox-1.28.4.tar.bz2
tar -xzvf linux-5.4.5.tar.gz
tar -jxvf busybox-1.28.4.tar.bz2
cd busybox-1.28.4
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make menuconfig

    Settings ---->

Build Options        [*]Build static binary(no shared libs)
make install
cd …
cp -r ./busybox-1.28.4/_install ./linux-5.4.5/

cd ./linux-5.4.5/_install/
mkdir etc
mkdir dev
mkdir mnt
mkdir -p etc/init.d

cd ..
vi _install/etc/init.d/rcS
    mkdir -p /proc
    mkdir -p /tmp
    mkdir -p /sys
    mkdir -p /mnt
    /bin/mount -a
    mkdir -p /dev/pts
    mount -t devpts devpts /dev/pts
    echo /sbin/mdev > /proc/sys/kernel/hotplug
    mdev –s

chmod +x _install/etc/init.d/rcS

vi _install/etc/fstab
    proc /proc proc defaults 0 0
    tmpfs /tmp tmpfs defaults 0 0
    sysfs /sys sysfs defaults 0 0
    tempfs /dev tmpfs defaults 0 0
    debugfs /sys/kernel/debug debugfs defaults 0 0

vi _install/etc/inittab
    ::sysinit:/etc/init.d/rcS
    ::respawn:-/bin/sh
    ::askfirst:-/bin/sh
    ::ctrlaltdel:/bin/umount -a -r

cd _install/dev
mknod console c 5 1
mknod null c 1 3
cd ..

export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make vexpress_defconfig
make menuconfig

General setup ---->
    [*]Initial RAM filesystem and RAM disk (initramfs/initrd) support
    (_install)Initramfs source file(s)
Boot option ---->
    ()Default kernel command string
Kernel features ---->
    Memory split(3G/1G user/kernel split) 
    [*] High Memory Support

vi ./usr/gen_initramfs_list.sh+131
    local dev="`LC_ALL=C ls -l "${location}"`"

make bzImage ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make dtbs

apt-get install gcc qemu qemu-system-arm gcc-arm-linux-gnueabi libncurses5-dev build-essential flex bison bc
qemu-system-arm -M vexpress-a9 -m 256M -kernel arch/arm/boot/zImage \
    -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" \
    -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic

killall qemu-system-arm

windows gcc
https://github.com/lordmilko/i686-elf-tools/releases/tag/7.1.0

浅析linux内存管理
https://blog.csdn.net/faxiang1230/article/details/105720640

linux-0.11
https://github.com/karottc/linux-0.11

Remove Last character in String
https://www.folkstalk.com/2012/05/remove-last-character-in-string-unix.html

sed s/.$// filename

#! /bin/bash
while read LINE
do
echo ${LINE%?}
done < filename

awk '{$0=substr($0,1,length($0)-1); print $0}' filename

awk 捕获正则分组
https://www.markhneedham.com/blog/2013/06/26/unixawk-extracting-substring-using-a-regular-expression-with-capture-groups/

抓包分析 TCP 连接时间

tcpdump -nn -v -i ens5 "(host 1.1.1.1 or 2.2.2.2) and tcp[tcpflags] & (tcp-syn) != 0"

awk '{match($1,/.*([0-9]\.[0-9]+)$/,arr); if($7=="[S],") {sync[$3]=arr[1];} {if($7=="[S.],") {ep=substr($5,1,length($5)-1); if(sync[ep]){print "local = "ep", connect time = "arr[1]-sync[ep];} }}} ' es_dump.txt| sort -rn -k7

tcpdump 看这一篇就够了
https://www.jianshu.com/p/e3292f4dcc99

https://askubuntu.com/questions/343727/filenames-with-spaces-breaking-for-loop-find-command
https://unix.stackexchange.com/questions/81349/how-do-i-use-find-when-the-filename-contains-spaces

查看当前目录下所有压缩文件的压缩内容

find . -type f -name '*.*' -print0 |
while IFS= read -r -d '' file; do
    if [ "${file##*.}"x = "zip"x ];then
        echo '###', $file
        unzip -O gbk -l "$file"
    fi
    if [ "${file##*.}"x = "rar"x ];then
        echo '###' $file
        rar v "$file"
    fi
done

linux 0.11 源码
linus曾经说过:RTFSC - Read The Fucking Source Code.
https://github.com/karottc/linux-0.11

关于这个Tiny_OS 这个是我随着《操作系统真象还原》从零开始自写的项目 当然现在里面的代码都是最后版本的代码了
https://gitee.com/residual_nozzle_on_dust/Tiny_OS

不解压查看压缩包文件列表

unzip -l a.zip
tar tvf a.tar.gz
rar v a.rar

6.S081 — 操作系统这门课程
https://mit-public-courses-cn-translatio.gitbook.io/mit6-s081/lec01-introduction-and-examples/1.1-ke-cheng-jian-jie

  • 理解操作系统的设计和实现。设计是指整体的结构,实现是指具体的代码长什么样。
  • 为了深入了解具体的工作原理,你们可以通过一个小的叫做 XV6 的操作系统,获得实际动手经验。
  • 通过研究现有的操作系统,并结合课程配套的实验,你可以获得扩展操作系统,修改并提升操作系统的相关经验,并且能够通过操作系统接口,编写系统软件。

ss 命令
ss -o state established

Linux环境编程:从应用到内核
https://book.douban.com/subject/26820213/

本书是Linux技术专家高峰和李彬的合力之作,是两个人多年开发经验的总结和分享,也是市场上唯一一本将Linux应用态与内核态相结合的技术图书,选择这种写作方式是为了向APUE的作者致敬。本书涵盖了APUE中大部分章节的内容,并针对Linux环境,以作者多年经验,详细解析了Linux常用接口的使用方法和陷阱。为了让读者更清楚地理解接口的工作原理,对于绝大部分接口,作者都会深入C库或内核源码进行全面分析。

Linux中的RCU机制[一] - 原理与使用方法
https://zhuanlan.zhihu.com/p/89439043
rcu 机制简介
https://zhuanlan.zhihu.com/p/113999842

iotop 非交互式

iotop -o -b -k -P -n3

crontab 设置重启后执行

sudo tail /var/spool/cron/crontabs/ubuntu
@reboot /home/ubuntu/reboot.sh >> /home/ubuntu/reboot.log 2>&1

rc.local里指定用户来运行程序

/bin/su - urs -c "/home/script/mount-oss.sh"

Linux Kernel Hash Table Behavior:
Analysis and Improvements
http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf

The Linux kernel employs hash table data structures to store high-usage data objects such as
pages, buffers, inodes, and others. In this report we find significant performance boosts with
careful analysis and tuning of four critical kernel data structures.

几种开源的TCP/IP协议栈分析
https://www.cnblogs.com/littleKing163/p/5003778.html

  • BSD TCP/IP协议栈,BSD栈历史上是其他商业栈的起点,大多数专业TCP/IP栈(VxWorks内嵌的TCP/IP栈)是BSD栈派生的。
  • uC/IP是由Guy Lancaster编写的一套基于uC/OS且开放源码的TCP/IP协议栈,亦可移植到其它操作系统,是一套完全免费的、可供研究的TCP/IP协议栈,uC/IP大部分源码是从公开源码BSD发布站点和KA9Q(一个基于DOS单任务环境运行的TCP/IP协议栈)移植过来。
  • LwIP是瑞士计算机科学院(Swedish Institute of Computer Science)的Adam Dunkels等开发的一套用于嵌入式系统的开放源代码TCP/IP协议栈。LwIP的含义是Light Weight(轻型)IP协议,相对于uip。LwIP可以移植到操作系统上,也可以在无操作系统的情况下独立运行。
    • LwIP TCP/IP实现的重点是在保持TCP协议主要功能的基础上减少对RAM的占用,一般它只需要几十K的RAM和40K左右的ROM就可以运行,这使 LwIP协议栈适合在低端嵌入式系统中使用。
    • LwIP的特性如下:
      • 支持多网络接口下的IP转发
      • 支持ICMP协议
      • 包括实验性扩展的的UDP(用户数据报协议),
      • 包括阻塞控制,RTT估算和快速恢复和快速转发的TCP(传输控制协议),
      • 提供专门的内部回调接口(Raw API)用于提高应用程序性能
      • 并提供了可选择的Berkeley接口API。
  • uIP是专门为8位和16位控制器设计的一个非常小的TCP/IP栈。完全用C编写,因此可移植到各种不同的结构和操作系统上,一个编译过的栈可以在几KB ROM或几百字节RAM中运行。
  • TinyTcp 栈是TCP/IP的一个非常小和简单的实现,它包括一个FTP客户。TinyTcp是为了烧入ROM设计的并且现在开始对大端结构似乎是有用的(初始目标是68000芯片)。

Cache和DMA一致性
https://zhuanlan.zhihu.com/p/109919756
并发基础理论:缓存可见性、MESI协议、内存屏障、JMM
https://zhuanlan.zhihu.com/p/84500221
Java网络编程与NIO详解8:浅析mmap和Direct Buffer
https://blog.csdn.net/AliCoder/article/details/103039202
漫谈linux文件IO
http://blog.chinaunix.net/uid-27105712-id-3270102.html

查看日志

journalctl --since yesterday
journalctl --since "30 min ago"

OOM排查与优化
https://blog.csdn.net/weixin_57400332/article/details/123812918

  • Linux内核有个机制叫OOM killer(Out-Of-Memory killer),该机制会监控那些占用内存过大,尤其是瞬间很快消耗大量内存的进程,为了防止内存耗尽内核会把该进程杀掉。
  • root 权限的进程通常被认为很重要,不应该被轻易杀掉,所以打分的时候可以得到 3% 的优惠(分数越低越不容易被杀掉)。

elasticsearch

Elasitcsearch CPU 使用率突然飙升,怎么办?
https://blog.csdn.net/laoyang360/article/details/122816850

核查 CPU 使用率

GET _cat/nodes?v=true&s=cpu:desc

核查热点线程

GET _nodes/my-node,my-other-node/hot_threads

检查长时间运行的搜索会阻塞搜索线程池中的线程。

GET _tasks?actions=*search&detailed

取消任务以释放资源

POST _tasks/oTUltX4IQMOUUVeiohTt8A:464/_cancel

elasticsearch 中的fielddata 和 doc_values
http://t.zoukankan.com/thewindyz-p-14360503.html

  • Doc Values 本质上是一个序列化的 列式存储, 列式存储 适用于聚合、排序、脚本等操作
  • Doc Values 通过序列化把数据结构持久化到磁盘,我们可以充分利用操作系统的内存,而不是 JVM 的 Heap
    • 当 working set 远小于系统的可用内存,系统会自动将 Doc Values 驻留在内存中,使得其读写十分快速
    • 当 working set 远大于可用内存时,系统会根据需要从磁盘读取 Doc Values,然后选择性放到分页缓存中
    • 很显然,这样性能会比在内存中差很多,但是它的大小就不再局限于服务器的内存了。
    • 如果是使用 JVM 的 Heap 来实现那么只能是因为 OutOfMemory 导致程序崩溃了。
  • 与 doc values 不同, fielddata 构建和管理 100% 在内存中,常驻于 JVM 内存堆;
    • fielddata 结构不会在索引时创建。相反,它是在查询运行时,动态填充;
    • 这意味着它本质上是不可扩展的,有很多边缘情况下要提防

同义词
Synonyms in Elasticsearch
https://medium.com/version-1/synonyms-in-elasticsearch-c527280ba8a5

The same, but different: Boosting the power of Elasticsearch with synonyms
https://www.elastic.co/blog/boosting-the-power-of-elasticsearch-with-synonyms

acronyms on Elastic Search request
https://stackoverflow.com/questions/67707925/acronyms-on-elastic-search-request

Function score query
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

java

java.security 框架之签名、加密、摘要及证书
https://blog.csdn.net/piaoranyuji/article/details/126122378

https://blog.csdn.net/am_Sun/article/details/106374866
Maven编译项目显示 程序包com.sun.*包不存在 【原因及三种解决方案】

IDEA 正常编译的项目,在生产环境 mvn package 报错

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project wxpaydemo: Compilation failure
[ERROR] /src/main/java/com/example/wxpaydemo/controller/TestController.java:[8,61] package com.sun.org.glassfish.external.statistics.annotations does not exist

解决:在 maven-compiler-plugin下 增加 forkcompilerArgs

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <encoding>UTF-8</encoding>
        <fork>true</fork>
        <compilerArgs>
            <arg>-XDignore.symbol.file</arg>
        </compilerArgs>
    </configuration>
</plugin>

线上启动

mvn clean package -Dmaven.test.skip=true
mkdir config
cp src/main/resources/application.yml ./config/
vi ./config/application.yml # 修改端口
    server:
      port: 8081        
java -jar target/wxpaydemo-0.0.1-SNAPSHOT.jar

# 修改代码或 resource 后要重新 mvn package 再启动 jar
mvn package && java -jar target/wxpaydemo-0.0.1-SNAPSHOT.jar

MVCS - Model View Controller Service
https://stackoverflow.com/questions/5702391/mvcs-model-view-controller-service

一般而言,影响视频画质的因素主要有以下几点:

硬件

一块带给无数人年少欢乐的CPU,别说你没用过它
https://zhuanlan.zhihu.com/p/415064726

《自己动手写CPU》读后感
https://zhuanlan.zhihu.com/p/278434972

MIPS架构CPU设计
https://gaozhiyuan.net/series/mips-cpu-design

【手写CPU】7.9 除法指令说明及实现
https://gaozhiyuan.net/computer/cpu/division-instruction-description-and-implementation.html

半导体所用的高纯硅是如何提纯到 99.999999999% 的?
https://www.zhihu.com/question/341011975

基础逻辑门
https://vlab.ustc.edu.cn/guide/doc_basic_logic.html
Verilog语法
https://vlab.ustc.edu.cn/guide/doc_verilog.html

KiCad EDA
A Cross Platform and Open Source Electronics Design Automation Suite
https://www.kicad.org/

流片一次有多贵?
http://news.sohu.com/a/564182392_121341339

先引用CMP(Circuits Multi-Projets,美国一家非营利性多项目晶圆服务组织)的公开报价吧。
按照这份报价,以业内裸芯(die)面积最小的处理器高通骁龙855为例(尺寸为8.48毫米×8.64毫米,面积为73.27平方毫米),用28纳米制程流片一次的标准价格为499,072.5欧元,也就是近400万元人民币!

https://vlab.ustc.edu.cn/guide/index.html
Logisim是一种用于设计和模拟数字逻辑电路的教育工具。

芯片设计之仿真工具
https://www.elecfans.com/d/1876977.html

  • 在通过Verilog语言完成芯片设计,且通过测试平台设计(编写testbench)对所设计的芯片施加激励和观测输出后,需要在计算机上模拟芯片设计,以判断所编写的代码是否符合预期。
  • 在计算机上模拟芯片设计需运用仿真工具,常用的EDA仿真工具主要由三家集成电路公司提供,分别是Mentor Graphics、Cadence、SYNOPSYS。

仿真的步骤如下:

  • 设置环境。包括在软件里设置相应的工程环境,设置相应的库文件,库文件是其他人员已完成的设计文件,当设计芯片需要某些已设计完成的文件时,可以调用库文件。
  • 编写Verilog代码。编写Verilog代码既可以使用文本编辑工具,也可以使用Modelsim中提供的代码编辑工具。
  • 编译。编译的目标是将Verilog代码转化成计算机上可以执行的程序。
  • 仿真。在仿真工具中模拟电路执行过程。
  • 分析仿真结果。 分析仿真结果是比较重要的步骤。分析仿真结果的目的是检查电路模拟的结果是否正确,是否符合预期的设计目标。

分析仿真结果的方法有多种:

  • 最直接的方法是用波形的方式检查,
  • 更高层次的方法包括数据流图(以图形方式来表达系统的逻辑功能、数据在系统内部的逻辑流向和逻辑变换过程)
  • 有限机(全称有限状态机,是一种用于进行对象行为建模的工具,作用是描述对象在其生命周期内所经历的状态序列,以及如何响应来自外界的各种事件)
  • 或用比较高效的方法定位故障发生的位置。

流程

  1. 用 Verilog 语言设计电路
  2. 编写 Testbench 施加激励,观测输出
  3. 使用 Modelsim 做仿真
  4. 用 KiCad 画 pcb
  5. 去立创平台做流片

https://brng.dev/blog/technical/tutorial/2019/05/11/icarus_gtkwave/

  • Icarus Verilog is a free Verilog simulator with some SystemVerilog support.
  • I personally enjoy using it because it’s really easy and quick to get it up and running.
  • Icarus Verilog compiles the Verilog source into a file that is executed by its simulator vvp.
  • GTKWave is a free waveform viewer, which is useful for debugging designs.

Xilinx Vivado卡在Initializing Language Server的解决方法
https://blog.csdn.net/yihuajack/article/details/120830612

打开 Tools -> Settings -> Tool Settings -> Text Editor -> Syntax Checking,将 Syntax checking 从 Sigasi 改为 Vivado:

【计算机组成原理】MIPS单周期CPU设计 | Verilog
https://www.bilibili.com/video/BV1rD4y1D7h9
https://github.com/qing-2/CPU

http://buthowdoitknow.com/
But How Do It Know? is the book you have been looking for if you want to know how computers work.

  • What is a bit?
  • What is a byte?
  • What is RAM?
  • What is a CPU?
  • What is a clock?
  • What is a computer?
  • What is a program?
  • How do the parts work together?
  • And much much more…

https://mcpedl.com/scott-cpu-map/

  • This is a fully functional 8Bit Computer in Minecraft Bedrock.
  • The design of the computer is based on the famous Scott CPU in the book But How Do It Know?
  • The Basic Principles of Computers for Everyone by J. Clark Scott. Give it a try!

QEMU虚拟机相关概念介绍
原文链接:https://blog.csdn.net/qq_34719392/article/details/125543643

  • Hypervisor介于虚拟机和宿主机操作系统之间,负责对宿主机资源(为方便表述,本文均以硬件资源为例,但实际上被虚拟化的不只有硬件资源)进行虚拟化,并将虚拟化后的硬件资源提供给虚拟机。Hypervisor分为两类:
    • Type-1 Hypervisor:位于操作系统内核空间,具备对宿主机硬件资源的直接访问权限。代表:Microsoft Hyper-V、Linux KVM、VMWare ESXi。
    • Type-2 Hypervisor:位于用户空间,需要通过操作系统内核才能访问硬件。代表:QEMU、Oracle VirtualBox。
  • QEMU 有两种工作模式:
    • QEMU 本身作为 Hypervisor。QEMU 与Linux 内核交互,从而获取虚拟化后的硬件。这就是前文所述的 Type-2 Hypervisor。
      • 交互层次:VM - QEMU - Linux Kernel - Driver - Hardware
    • QEMU 作为虚拟机与 Linux KVM 交互的中间层,仅负责传递交互信息,而不发挥 Hypervisor 的实际功能。真正发挥 Hypervisor 功能的是 Linux KVM。
      • 交互层次:VM - QEMU - Linux KVM - KVM Virtual Driver - Hardware
    • 第二种工作模式能够直接利用 KVM,因而效率更高。
    • 而第一种工作模式多用于不需要和硬件直接交互的场合,例如在虚拟机中启动虚拟机。
  • libvirtd、libvirt、virt-manager 的概念及与 QEMU 的关系
    • libvirtd 是 Linux 中的一个守护进程,其使用的是 libvirt 库。
    • libvirt 与 QEMU 的关系,类似于 Kubernetes 与 Docker 的关系:
      • QEMU 负责实际管理一台宿主机上的所有虚拟机;
      • 而 libvirtd 适用于一台宿主机上启用多台虚拟机的场景,它提供了一系列在虚拟机之间进行资源调度的接口,这些接口底层仍然是以 QEMU 命令来实现的。
    • virt-manager 是 libvirt 的图形化界面。
      • 在 virt-manager 上的所有操作,都会被映射为 libvirt 命令;
      • libvirt 命令又会被映射为 QEMU 命令;
      • 如果 QEMU 处于第二种工作模式,那么 QEMU 命令又会再次被映射为 KVM 命令。
    • virt-manager、libvirt、QEMU 与 KVM 都属于 Hypervisor 层次。
      • 前三者都处于用户空间,只有KVM处于内核空间。

Vivado安装和使用
https://vlab.ustc.edu.cn/guide/doc_vivado.html

一个典型的设计流程包括创建 model,创建用户约束文件,创建 Vivado 项目,导入已创建的model,编译约束文件,选择性调试运行时的行为仿真,综合你的design,实现design,生成 bitstream 文件,最后将 bitstream 文件下载到硬件中,并确认硬件能否正确的实现功能。

如何快速掌握一款MCU,可以从这几方面入手
https://mp.weixin.qq.com/s/YBP-bU3OfGqmSdniI-_3Tg

中断嵌套

中断嵌套是指中断系统正在执行一个中断服务时,有另一个优先级更高的中断提出中断请求,这时会暂时终止当前正在执行的级别较低的中断源的服务程序,去处理级别更高的中断源,待处理完毕,再返回到被中断了的中断服务程序继续执行的过程。

mcu就是单片机的意思,而plc是可编程逻辑控制器,两者都是可编程的控制器件。
https://www.sohu.com/a/569640464_120676425

  • PLC 就能够满足设备工业级要求,在抗干扰方面、输入和输出点可靠性方面更为优越,并采用可靠的组态方式,因此可靠性更高,而且通信方面有很多工业控制设备采用光纤以抗干扰。
  • PLC 等设备可采用整体式或者积木式,各个组件可以按需选用,并便于组态实现。各个工作站之间采用规范的总线通讯,这都是模块内置的,只需配置无须编写代码,简单可靠。
  • 在工业环境下,传感器的输出多采用4~20mA、0~10V的形式,这与MCU常用的0~3.3V或者0~5V的AD模块不相符合,因此需要针对工业环境设计传感信号接收模块。
  • PLC 是基于 mcu 的产品,在 mcu 的基础上增加了模块化的开发。不用编写底层的代码,无须了解单片机的底层资源。
  • 单片机开发需要从底层代码开始,需要用汇编或者C语言编写,其I/O接口、协议、读写时序、算法与数据结构都必须自己编写开发。

如何正确的评测视频画质
https://wangwei1237.github.io/2022/05/09/How-to-Assess-the-Video-Quality-Correctly/

  • 分辨率:图像中的像素数量,在特定尺寸下,分辨率越高,像素越多,显示的细节则更精细。[3]
  • 帧率:一秒内显示的图像数量,电影的帧率一般是 24fps,标准电视的帧率通常是 30fps。[3:1]
  • 亮度:可以显示的图像照明强度的范围,人眼能感知到的亮度范围在 10W 尼特左右。
  • 位深:每个像素可以显示的颜色数量,位深度越大,可显示的颜色越多,从而渐变更平滑、更自然。[4]
  • 色域:色域是某个特定的色彩的子集,用以表示可以显示的所有颜色的范围。色域一般使用 CIE 1931 色度图上的面积来表示,CIE 1931 曲线的边缘代表可见光光谱颜色的范围。[4:1]
  • 码率:编码每秒视频需要的 bit 数量称之为码率(bitrate)。在一定条件下,码率会影响视频的质量,码率越低,压缩率越大,画质相对越差。当然,并非码率越高画质越好,在很多情况下,更高的码率带来的往往却只是带宽的浪费。[5]

关于时钟与触发器的感想
https://blog.csdn.net/weixin_30349597/article/details/96950680

  • 时钟是时序电路的控制者” 这句话太经典了,可以说是FPGA设计的圣言。
  • FPGA的设计主要是以时序电路为主,因为组合逻辑电路再怎么复杂也变不出太多花样,理解起来也不没太多困难。 但是时序电路就不同了,它的所有动作都是在时钟一拍一拍的节奏下转变触发,可以说时钟就是整个电路的控制者,控制不好,电路功能就会混乱。
  • 时序逻辑电路的时钟是控制时序逻辑电路状态转换的“发动机”,没有它时序逻辑电路就不能正常工作,因为时序逻辑电路主要是利用触发器存储电路的状态,而触发器状态变换需要时钟的上升或下降沿!由此可见时钟在时序电路中的核心作用!

FPGA能代替CPU架构吗?
https://www.cnblogs.com/alifpga/p/9503593.html

FPGA基础知识介绍
https://vlab.ustc.edu.cn/guide/doc_fpga.html

  • FPGA(Field-Programmable Gate Array),即现场可编程门阵列。
  • 它是作为专用集成电路(ASIC)领域中的一种半定制电路而出现的,既解决了定制电路的不足,又克服了原有可编程器件门电路数有限的缺点。
  • 现如今的集成电路绝大部分采用 CMOS 工艺,基本结构是一个 N 沟道 MOS 管和一个 P 沟道 MOS 管。
  • NMOS 和 PMOS 可以认为是两种开关电路,两种电路均包含 G(栅极)、D(漏极)、S(源极)三个极。
  • 一个 NMOS 和一个 PMOS 可构成一个 CMOS 反相器, 同理,可构成 CMOS 的与非门、或非门。
  • 多个与非门可组成一个带有复位、置位功能的D触发器,而D触发器则是时序逻辑电路的最核心部件。
  • 由此可知,通过非门、与非门、或非门的有序堆叠,可实现任意功能的数字电路。
  • 如果有一款电路,其基本单元可配置成各种基本门,则其就具备了硬件编程能力。
  • FPGA就是这种芯片,它基于查找表(LUT:Look Up Table)技术的可编程逻辑器件。
  • 通过配置,LUT 可实现与门、或门、与非门、或非门或者其他简单组合逻辑功能,其本质上就是 1bit 位宽的 RAM。
  • CPU 中拥有控制取指、译码等流程,具备处理各式各样千奇百怪的指令要求的能力。
  • 相比之下 FPGA 只能根据一个固定的模式来处理输入的数据然后输出,这也是为什么 FPGA 经常被看作一种行家专属的架构。
  • 不同于 CPU 的是,FPGA 和 GPU 内都有大量的计算单元,因此它们的计算能力都很强。在进行神经网络运算的时候,两者的速度会比 CPU 快很多。
  • 但是 GPU 由于架构固定硬件原生支持的指令固定了,而 FPGA 则是可编程的。

mysql

UTC 时间

SET time_zone ='+8:00';

mysql> select now(),CONVERT_TZ(NOW(), '+08:00', 'UTC') utc, UTC_TIMESTAMP(),UTC_DATE(),UTC_TIME();
+---------------------+---------------------+---------------------+------------+------------+
| now()               | utc                 | UTC_TIMESTAMP()     | UTC_DATE() | UTC_TIME() |
+---------------------+---------------------+---------------------+------------+------------+
| 2022-09-07 17:43:23 | 2022-09-07 09:43:23 | 2022-09-07 09:43:23 | 2022-09-07 | 09:43:23   |
+---------------------+---------------------+---------------------+------------+------------+
1 row in set (0.00 sec)

code

Feature Toggles (aka Feature Flags)
https://martinfowler.com/articles/feature-toggles.html

docker

修改一个容器开机自动启动

docker update --restart=always c0d6948dae7a

PHP

config php slowlog

touch /var/log/php8.1-slow.log
chmod o+w /var/log/php8.1-slow.log
vi /etc/php/8.1/fpm/pool.d/www.conf
slowlog = /var/log/php8.1-slow.log
request_slowlog_timeout = 5s
php-fpm8.1 -tt
systemctl status php8.1-fpm
systemctl restart php8.1-fpm

nginx 超时

client_header_timeout 1000000;
client_body_timeout 1000000;
send_timeout 1000000;
fastcgi_read_timeout 1000000;

php-fpm 超时

request_terminate_timeout = 5s

遇到如下错误

2022/09/16 15:24:28 [crit] 3550790#3550790: *62 open() "/var/lib/nginx/fastcgi/1/03/0000000031" failed (13: Permission denied) while reading upstream, client: 122.5.23.146,

这样解决

sudo chown -R www-data:www-data /var/lib/nginx

nginx

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.1-fpm.sock;
}

composer 安装

curl -x 111.111.103.12:8080 ifconfig.me
composer config -l
composer config -g repo.packagist composer https://repo.packagist.org
sudo apt-get install php8.1-intl
HTTP_PROXY=http://111.111.103.12:8080  composer self-update
HTTP_PROXY=http://111.111.103.12:8080 composer -vvv install
sudo systemctl restart php8.1-fpm

composer install和update的使用经验
https://blog.csdn.net/u012449363/article/details/90436769

  • composer install 是从 composer.lock 读取第三方组件及其版本,并将其安装到 vendor 目录下。
    • 如果 composer.lock 文件不存在,则读取 composer.json 第三方组件及其版本,然后安装到 vendor 目录下。
  • update是直接从 composer.json 获取第三方组件及其版本,然后更新 composer.lock 文件。
    • 如果依赖的第三方组件有版本更新,update 会将最新的版本安装到 vendor 目录下,并更新 composer.lock。
  • 在生产环境下,直接使用 composer update 命令是有较大风险的。
  • 比较推荐的做法,将composer.json 和 composer.lock 都加入到版本管理中
    • 在开发过程中注意 composer.lock 中依赖版本的变化
    • 每次上线打包使用 composer install,从 composer.lock 中获取依赖的第三方组件和版本。
    • 如果需要更新第三方组件,执行 composer update 命令时,应该在后面追加有必要更新的组件库。

Get a stack trace of a running or hung PHP script
https://stackoverflow.com/questions/14261821/get-a-stack-trace-of-a-running-or-hung-php-script

前端

coffee script, less
https://coffeescript.org/
https://lesscss.org/

go

go runtime 简析
https://zhuanlan.zhihu.com/p/111370792

gdb

用QEMU模拟调试裸机ARM64汇编,支持gdb单步调试
https://blog.csdn.net/luteresa/article/details/119615923

gdb调试的layout使用
https://blog.csdn.net/zhangjs0322/article/details/10152279

远程调试内核:

target remote localhost:1234
b start_kernel
c
layout src

基本命令

layout:用于分割窗口,可以一边查看代码,一边测试。主要有以下几种用法:
layout src:显示源代码窗口
layout asm:显示汇编窗口
layout regs:显示源代码/汇编和寄存器窗口
layout split:显示源代码和汇编窗口
layout next:显示下一个layout
layout prev:显示上一个layout
Ctrl + L:刷新窗口
Ctrl + x,再按1:单窗口模式,显示一个窗口
Ctrl + x,再按2:双窗口模式,显示两个窗口
Ctrl + x,再按a:回到传统模式,即退出layout,回到执行layout之前的调试窗口。

run(简写r): 运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
continue(简写c):继续执行,到下一个断点处(或运行结束)
next(简写n): 单步跟踪程序,当遇到函数调用时,直接调用,不进入此函数体;
step(简写s):单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
until:运行程序直到退出循环体; / until+行号: 运行至某行
finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息。
call 函数(参数):调用“函数”,并传递“参数”,如:call gdb_test(55)
quit:简记为 q ,退出gdb

重新定义Hello World

目录

  • 原始的 Hello World 程序
  • 配置开发环境
  • 单元测试
  • 代码实现
  • 代码调试
  • 安全测试 fuzz
  • 性能测试
  • 性能剖析
  • 性能优化

原始的 Hello World

原始的 Hello World 程序是 Brian Kernighan 和 Dennis Ritchie(K&R) 在 1978 年为《The C Programming Language》一书写的例子,后来成为了所有程序员的入门必学的例子。

#include <stdio.h>

main()
{
    printf("hello, world\n");
}

可以看到,这段代码和现在的 C 代码有很大的差别,main 函数没有参数也没有返回值,因为那会 C 语言的规范还没有确定,硬件也比较受限。而且原始的 hello world 程序全是小写,hello 后面有个逗号,但结尾没有句号,这应该是随手示例的。

要编译这段古老的代码,我们要使用 C90 标准:

$ gcc -std=gnu90 k-r-hello-world.c
$ ./a.out
hello, world

参考链接:

配置开发环境

工欲善其事必先利其器,假设我们使用 VIM 开发 C 语言,首先要在 ~/.vimrc 里设置一些简单的配置:

set nocp nu et ts=4 sw=4 sta hls si noeb vb t_vb=
autocmd FileType c nnoremap <buffer> <F5> :!gcc -g -Wall  % && ./a.out<CR>

第一行是通用的设置,要使用 VIM 写代码我一般都会先设置它,就一行也很好好记

  • nocp: 让 VIM 不在兼容模式下运行
  • nu: 显示行号
  • et: expandtab 的缩写,表示输入 tab 时插入空格
  • ts=4: tabstop 的缩写,输入 tab 插入 4 个空格
  • sw=4: shiftwidth 缩写,用shift+>> 时调整缩进时移动 4 个空格
  • sta: smarttab 的缩写,基于已有行的缩进来确定,在新行的开始位置
  • hls: hlsearch 的缩写,高亮显示搜索的关键字
  • si: smartindent 的缩写,每一行都和前一行有相同的缩进量
  • noeb vb t_vb=: 关闭按错键时的响铃声和屏幕闪烁,否则太烦了

第二行是设置当文件是 C 语言文件时,在正常模式下按 F5 键会编译和运行程序,相当于一个快速运行快捷键。

  • -g 是开启调试模式,会生成调试符号,出错时的错误信息能看到行号。
  • -Wall 是开启所有警告,以最严格的模式来写代码,养成好的习惯。

写一个新的 hello-world.c 再按 F5 试试:

#include <stdio.h>

int main()
{
    printf("hello world.\n");
    return 0;
}

好了,现在我们就可以快乐的写代码了,如果你记不住 VIM 的配置,那可以简化一下:

set nu et ts=4

然后新开一个窗口进行编译和测试

gcc hello-world.c && ./a.out

还有一个小技巧是写 C 代码的时候,有时候需要查看函数的帮助,可以将光标移动到函数上,按 shit+k 查看帮助,按 q 退出,这是 VIM 内置的。

一个好的开发工具往往会事半功倍,自己试一下在自己熟悉的编程工具里如何完成如下任务:

  • 跳转到上一次编辑的位置
  • 跳转到一个函数的定义
  • 查找函数的所有引用
  • 跳到匹配括号的开始和结尾
  • 快速注释和取消注释一行或多行

单元测试

下面我们写一个有意义的程序,把一个路径和一个文件名连接在一起,比如把 /tmpgirl.jpg 连接在一起就是 /tmp/girl.jpg

大家一定听过 TDD 测试驱动,就是写代码之前先写测试,但写测试前得先有测试框架,我们可以使用 CMocka,原因是简单够用,下面是安装过程:

git clone --single-branch --depth 1 https://git.cryptomilk.org/projects/cmocka.git
cd cmocka
mkdir build && cd build
cmake ..
make -j8
sudo make install

编写一个 cmocka-test.c 文件,测试下官方例子:

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>

/* A test case that does nothing and succeeds. */
static void null_test_success(void **state) {
    (void) state; /* unused */
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(null_test_success),
    };

    return cmocka_run_group_tests(tests, NULL, NULL);
}

这时候按 F5 是无法编译了,大概会看到这样的错误:

/tmp/cc1roVOc.o: In function `main':
cmocka-test.c:(.text+0x6f): undefined reference to `_cmocka_run_group_tests'
collect2: error: ld returned 1 exit status

这因为我们编译的时候没有链接 cmocka 的库,所以要修改下 ~/.vimrc 的配置

autocmd FileType c nnoremap <buffer> <F5> :!gcc -g -Wall %  -lcmocka && ./a.out<CR>

这时候按 F5 应该能够看到单元测试的输出,可以看到运行了一个测试,并且通过了。

[==========] tests: Running 1 test(s).
[ RUN      ] null_test_success
[       OK ] null_test_success
[==========] tests: 1 test(s) run.
[  PASSED  ] 1 test(s).

如果运行程序的时候报如下的错误:

./a.out: error while loading shared libraries: libcmocka.so.0: cannot open shared object file: No such file or directory

这是因为运行时找不到动态链接库,我们要修改下环境变量来解决,在 shell 里修改 LD_LIBRARY_PATH 并重新用 VIM 打开代码运行:

export LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH

要永久修改共享库查找路径的话可以在 /etc/ld.so.conf 里指定。

好了,单元测试库是可以用了,我们就可以写代码了,写代码之前我们还要先定义接口,就是函数的签名,参数和返回值。
本着接口和实现分离的原则,我们一般会把函数声明放到头文件里,新建一个 join-path.h 文件:

int join_path(char *buf, int buflen, const char *base, const char *file);

我们做如下约定

  • 函数名是 join_path
  • buf 是拼接结果的缓冲区
  • buflen 是缓冲区长度,防止拼接后缓冲区溢出
  • base 是目录的路径,如 /tmp
  • file 是文件名,如 girl.jpg
  • 返回值为 int,0 表示成功,非 0 表示出错,一般 unix 下是这样约定的。

新建代码实现文件 join-path.c,先写个空的实现函数,没有实际逻辑:

#include <stdio.h>

int join_path(char *buf, int buflen, const char *base, const char *file) {
    return 0;
}

新建 join-path-test.c 文件来写测试代码

#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include <stdint.h>
#include <cmocka.h>
#include "join-path.h"
#include "join-path.c"

static void join_test01(void **state) {
    char buf[100];
    int ret = join_path(buf, 100, "/tmp", "girl.jpg");
    assert_int_equal(0, ret);
    assert_string_equal("/tmp/girl.jpg", buf);
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(join_test01),
    };

    return cmocka_run_group_tests(tests, NULL, NULL);
}

大部分代码和 CMocka 的实例代码是一样的,不同的地方是:

  • include 了被测代码的头文件和实现文件,因为我们是测试自己的代码,可以直接引入源码文件,这样 F5 就可以看到测试结果, 不需要修改链接选项。
  • 定义了一个 join_test01 的函数,相当于第一个测试用例:
    • 定义一个长度 为 100 个 buffer;
    • 调用 join_path 函数;
    • 断言函数返回 0;
    • 断言缓冲区为预期的结果 /tmp/girl.jpg
  • 在 main 函数里执行上面定义的测试。

好了,接口声明,代码实现和第一个单元测试都有了,我们 F5 来运行测试,预期会失败,但我们后面再让他成功。

[==========] tests: Running 1 test(s).
[ RUN      ] join_test01
111
[  ERROR   ] --- "/tmp/girl.jpg" != ""
[   LINE   ] --- join-path-test.c:13: error: Failure!
[  FAILED  ] join_test01
[==========] tests: 1 test(s) run.
[  PASSED  ] 0 test(s).
[  FAILED  ] tests: 1 test(s), listed below:
[  FAILED  ] join_test01

 1 FAILED TEST(S)

在 VIM 同时打开多个文件的话,可以按 :bn:bp 进行切换,比如我们就打开了 3 个文件:join-path.hjoin-path.cjoin-path-test.c

我们要对单元测试进行更多的熟悉,尝试做如下任务:

  • 了解更多的断言,如断言数组中包含指定元素;
  • 在每个单元测试前面进行准备工作,后面做资源回收工作;
  • 对被测函数依赖的函数进行 mock;
  • 断言某个函数以指定的参数被调用;
  • 临时屏蔽某个测试用例;
  • 评估被测代码的测试覆盖率;

代码实现

终于可以正式的开始写代码实现了,第一个可以想到的就是用 snprintf 函数实现:

int join_path(char *buf, int buflen, const char *base, const char *file) {
    snprintf(buf, buflen, "%s/%s", base, file);
    return 0;
}

F5 运行测试

[==========] tests: Running 1 test(s).
[ RUN      ] join_test01
[       OK ] join_test01
[==========] tests: 1 test(s) run.
[  PASSED  ] 1 test(s).

妥了,测试通过了,喝杯咖啡奖励一下自己。接着做更多的测试,写第 2 个用例,并在 main 函数里增加一行以便测试它:

static void join_test02(void **state) {
    char buf[3];
    int ret = join_path(buf, 3, "/tmp", "girl.jpg");
    assert_int_equal(0, ret);
    assert_string_equal("/tmp/girl.jpg", buf);
}

int main(void) {
    const struct CMUnitTest tests[] = {
        cmocka_unit_test(join_test01),
        cmocka_unit_test(join_test02),
    };

    return cmocka_run_group_tests(tests, NULL, NULL);
}

F5 测试,发现这次用例失败了:

[==========] tests: Running 2 test(s).
[ RUN      ] join_test01
[       OK ] join_test01
[ RUN      ] join_test02
[  ERROR   ] --- "/tmp/girl.jpg" != "/t"
[   LINE   ] --- join-path-test.c:20: error: Failure!
[  FAILED  ] join_test02
[==========] tests: 2 test(s) run.
[  PASSED  ] 1 test(s).
[  FAILED  ] tests: 1 test(s), listed below:
[  FAILED  ] join_test02

 1 FAILED TEST(S)

因为这次的缓冲区长度我们故意给了 3 个,根本放不下拼接后的结果,所以我们预期这时候返回值不应该为 0 ,我们修改下测试用例:

static void join_test02(void **state) {
    char buf[3];
    int ret = join_path(buf, 3, "/tmp", "girl.jpg");
    assert_int_not_equal(0, ret);
}

这时候运行测试肯定还是失败,我们的主要工作流程就是:

  • 编写新的单元测试,默认执行会失败
  • 修改代码,让失败的单元测试成功

上面的用例失败,说明我们没有对参数做严格的检查,我们来完完善它:

#include <string.h>

int join_path(char *buf, int buflen, const char *base, const char *file) {
    if (strlen(base)+strlen(file)+1+1>buflen) return -1;
    snprintf(buf, buflen, "%s/%s", base, file);
    return 0;
}

我们在 base 加上 file 再加上路径连接符 / 再加上 C 语言字符串终止符 0 的长度大于缓冲区长度时返回 -1。F5 测试:

[==========] tests: Running 2 test(s).
[ RUN      ] join_test01
[       OK ] join_test01
[ RUN      ] join_test02
[       OK ] join_test02
[==========] tests: 2 test(s) run.
[  PASSED  ] 2 test(s).

妥了, 2 个测试用例成功了,但我们不能靠假设编程,每个参数都会有各种可能的值传进来,还有别的边界条件要测吗?想一想:

  • 如果参数 buf, base, file 有一个是 NULL 程序能否正常运行,应如何修复。
  • 如果参数 buflen 是负数,程序能否正常运行,应如何修复。
  • 如果参数 base 或 file 不是一个以 \0 结尾的字符串,会发生什么,应如何修复。
  • 如何缓冲区的大小并没有 buflen 那么长,会发生什么,我们能修复吗?

代码调试

写 C 程序最常遇到的错误是什么?那肯定是内存错误,因为 C 语言里内存都要手动管理,各种数组也没有越界检查,一不小心就会出现内存错误。

我们新建 join-path-debug.c 来学习如何调试代码:

#include <stdio.h>
#include "join-path.c"
int main()
{
    char buf[3];
    join_path(buf, 100, "/tmp", "girl.jpg");
    return 0;
}

手工编译并运行,直接报错了,类型是调用栈错误,也是一种典型的内存错误,其它常见的还有段错误等。

$ gcc join-path-debug.c
$ ./a.out
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)

如果我们的代码量很大,执行程序异常崩溃,我们如何定位原因呢?这就得用到 gdb 调试工具了。首先编译时要加 -g 参数

gcc -g join-path-debug.c

然后用 gdb 来运行它:

$ gdb ./a.out
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Reading symbols from ./a.out...done.

输入 r 会运行程序,这里会看到遇到了内存错误,程序被终止了。

(gdb) r
Starting program: a.out
*** stack smashing detected ***: <unknown> terminated

Program received signal SIGABRT, Aborted.
__GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.

输入 bt 可以查看线程调用栈, 程序是被 libc 的栈检查机制终止的,最顶层的栈帧是 join-path-debug.c 的第 8 行 main 函数里引起的错误

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007ffff7a227f1 in __GI_abort () at abort.c:79
#2  0x00007ffff7a6b837 in __libc_message (entry=do_abort, fmt=fmt@entry=0x7ffff7b98869 "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007ffff7b16b31 in __GI___fortify_fail_abort (need_backtrace=need_backtrace@entry=false, msg=msg@entry=0x7ffff7b98847 "stack smashing detected") at fortify_fail.c:33
#4  0x00007ffff7b16af2 in __stack_chk_fail () at stack_chk_fail.c:29
#5  0x00005555555547cc in main () at join-path-debug.c:8

f 5 切换栈帧,并用 l 查看附近的代码

(gdb) f 5
#5  0x00005555555547cc in main () at join-path-debug.c:8
8       }
(gdb) l
3       int main()
4       {
5           char buf[3];
6           join_path(buf, 100, "/tmp", "girl.jpg");
7           return 0;
8       }

我们发现第 8 行代码并没有实际代码执行,怎么会出错呢,这其实是正常的。C 程序遇到的好多错误就是这样,出错的地点和引起错误的地点有可能离的很远,因为引起内存错误的代码可能执行了很久,才会被其它的代码使用这块内存的时候发现。

现在我们看到的例子是个特例,因为在第 8 行往上看一下就能找到问题:代码定义的缓冲区长度只有 3, 但给 join_path 传入的 buflen 参数是 100,所以 join_path 的参数检查并没有失败,这时候运行就会报错了。

那我们还有没有更可靠的方法来定位这种错误呢?有,那就是用 Address Sanitizer(Asan),这个工具已经集成到 gcc 里了,我们直接加几个参数就可以使用:

$ gcc -g -Wall -fsanitize=address -fno-omit-frame-pointer join-path-debug.c
$ ./a.out
=================================================================
==13565==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff97c3b743 at pc 0x7fb8cbce4f09 bp 0x7fff97c3b5d0 sp 0x7fff97c3ad60
WRITE of size 14 at 0x7fff97c3b743 thread T0
    #0 0x7fb8cbce4f08 in __interceptor_vsnprintf (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xa0f08)
    #1 0x7fb8cbce5286 in snprintf (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xa1286)
    #2 0x55bb3a82cb80 in join_path join-path.c:6
    #3 0x55bb3a82cc2c in main join-path-debug.c:6
    #4 0x7fb8cb874c86 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21c86)
    #5 0x55bb3a82ca29 in _start (a.out+0xa29)

Address 0x7fff97c3b743 is located in stack of thread T0 at offset 35 in frame
    #0 0x55bb3a82cb9c in main join-path-debug.c:4

  This frame has 1 object(s):
    [32, 35) 'buf' <== Memory access at offset 35 overflows this variable

这次妥了,直接定位到 join-path.c 的第 6 行触发了栈溢出,而且还显示这块内存是在 join-path-debug.c 的第4 行在栈上分配的,有了这些信息候再结合代码和调用栈就很容易定位错误了。

如果还是没有定位到错误,因为一些运行时的信息不确定,那可以继续用 gdb 来调试,去掉 asan 编译选项重新编译程序并用 gdb 启动

$ gcc -g -Wall join-path-debug.c
$ gdb ./a.out

根据 asan 的信息,在 join-path.c 的第 6 行增加断点:

(gdb) b join-path.c:6
Breakpoint 1 at 0x745: file join-path.c, line 6.

运行程序,可以看到在断点处停住了,可以很清楚的看到各个参数的值:

(gdb) r
Starting program: a.out

Breakpoint 1, join_path (buf=0x7fffffffe385 "\177", buflen=100, base=0x555555554863 "/tmp",
    file=0x55555555485a "girl.jpg") at join-path.c:6
6           snprintf(buf, buflen, "%s/%s", base, file);

也可以用 p 命令查看具体某个变量的值

(gdb) p base
$1 = 0x555555554863 "/tmp"
(gdb) p buflen
$2 = 100
(gdb) p file
$3 = 0x55555555485a "girl.jpg"
(gdb) p buf
$4 = 0x7fffffffe385 "\177"

这里看到 buflen 为 100,我们尝试跳到上一层堆栈找找有没有 buf 分配的代码:

(gdb) bt
#0  join_path (buf=0x7fffffffe385 "\177", buflen=100, base=0x555555554863 "/tmp", file=0x55555555485a "girl.jpg")
    at join-path.c:6
#1  0x00005555555547b3 in main () at join-path-debug.c:6
(gdb) f 1
#1  0x00005555555547b3 in main () at join-path-debug.c:6
6           join_path(buf, 100, "/tmp", "girl.jpg");
(gdb) l
1       #include <stdio.h>
2       #include "join-path.c"
3       int main()
4       {
5           char buf[3];
6           join_path(buf, 100, "/tmp", "girl.jpg");
7           return 0;
8       }

这里定位到 join-path-debug.c 的第 5 行定义 buf 只有 3 个的长度,找到了问题的原因。

假如说是一个正在运行的进程突然崩溃了,我们如何来定位原因呢?这时候就要调试 core dump文件了,首先在服务器上要做一些设置允许程序崩溃是产生 dump 文件。

sudo mkdir -p /data/coredump/
sudo chmod o+w /data/coredump
sudo bash -c 'echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern'
ulimit -c unlimited

上面代码是让 core dump 文件保存在 /data/coredump 下,并且 dump 文件名称包含程序名称和进程 ID,然后设置 dump 文件大小为无限制。

直接运行代码,就会产生 core dump 了。

$ ./a.out
*** stack smashing detected ***: <unknown> terminated
Aborted (core dumped)
$ ls /data/coredump/
core.a.out.14375

拿到 dump 文件后需要有原始的文件才能进行调试,先启动 gdb:

$ gdb ./a.out
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Reading symbols from ./a.out...done.

然后用 core-file 指令加载 core dump:

(gdb) core-file /data/coredump/core.a.out.14375
[New LWP 14375]
Core was generated by `./a.out'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
51      ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.

查看调用栈

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007fadd6b0f7f1 in __GI_abort () at abort.c:79
#2  0x00007fadd6b58837 in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7fadd6c85869 "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:181
#3  0x00007fadd6c03b31 in __GI___fortify_fail_abort (need_backtrace=need_backtrace@entry=false, msg=msg@entry=0x7fadd6c85847 "stack smashing detected") at fortify_fail.c:33
#4  0x00007fadd6c03af2 in __stack_chk_fail () at stack_chk_fail.c:29
#5  0x000055df3b1a47cc in main () at join-path-debug.c:8

live debug 能单步调试,设置断点等,但调试 core dump 基本上就是看一下调用栈,这是最重要的信息,一般也能够提供足够的线索来定位问题。

202208

postgree

How to copy with statement result to local in postgresql
https://stackoverflow.com/questions/64438775/how-to-copy-with-statement-result-to-local-in-postgresql

create temporary view data_to_export
as
with cte as (..)
select *
from cte
;

\copy (select * data_to_export) to ...

Postgres: return first N rows per group for groups having a minimum countI
https://stackoverflow.com/questions/38589305/postgres-return-first-n-rows-per-group-for-groups-having-a-minimum-counti

SELECT userid, createdat, displaydate
FROM (SELECT t.*,
             ROW_NUMBER() OVER (PARTITION BY userid ORDER BY createdat) as seqnum,
             COUNT(*) OVER (PARTITION BY userid) as cnt
      FROM data t
     ) x
WHERE x.seqnum <= 100 AND x.cnt > 100;

PostgreSQL操作JSON数据
https://blog.csdn.net/qq_42715450/article/details/121350279

 // -> 返回json
 select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->2 // 输出 {"c":"baz"}
 select '{"a": {"b":"foo"}, "c":{"a": "aaa"}}'::json->'a' // 输出 {"b":"foo"}

 // ->> 返回文本
 select '[{"a":"foo"},{"b":"bar"},{"c":"baz"}]'::json->>2 // 输出 {"c":"baz"}
 select '{"a": {"b":"foo"}, "c":{"a": "aaa"}}'::json->>'a' // 输出 {"b":"foo"}

 // #> 获取json子对象
 select '{"a": {"b":{"c": "foo"}}}'::json#> '{a,b}' // 输出 {"c": "foo"}
 select '{"a": {"b":{"c": "foo"}}}'::json#>> '{a,b}' // 输出 {"c": "foo"}

 // @> ———— 判断第一个json是否包含第二个
 select '{"a":1, "b":2}'::jsonb @> '{"b":2}'::jsonb   //输出t
 // <@ ———— 判断第一个json是否在第一个中
 select '{"b":2}'::jsonb <@ '{"a":1, "b":2}'::jsonb   //输出t

PostgreSQL 安装
https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-ubuntu-20-04

sudo apt install postgresql postgresql-contrib
sudo systemctl start postgresql.service
sudo -i -u postgres
psql

sudo -u postgres createuser --interactive
    mydb 
sudo -u postgres createdb mydb 
sudo adduser mydb 
sudo -u mydb psql
    \conninfo
    create schema mydb 
grep -n CREATE 1.sql
sed -n '1147637,1148637p' 1.sql  > 5.sql
sudo -u mydb psql -d mydb -U mydb -f 5.sql

PostgreSQL查询当前执行中SQL的执行计划——pg_show_plans
https://www.cnblogs.com/lovezhr/p/15180691.html

  • 通常情况,我们可以通过explain、explain analyze、explain verbose来获取执行计划。
  • 但是explain查询当前缓存的执行计划,在实际中估算的成本可能是不准确的,因为很可能估算的成本和实际运行的成本不一致。而explain analyze、explain verbose则会实际执行SQL,但在某些场景不会被允许执行。
  • 可以尝试采用开启一个事务后,explain analyze、explain verbose查看执行计划,最后rollback。
  • pg_show_plans是一个显示当前运行的所有SQL语句执行计划的模块。

AI

小波变换和傅里叶变换
https://blog.csdn.net/qq_43528044/article/details/121533574

  • 要讲小波变换,我们必须了解傅立叶变换。要了解傅立叶变换,我们先要弄清楚什么是”变换“。
  • 很多处理,不管是压缩也好,滤波也好,图形处理也好,本质都是变换。变换的是什么东西呢?是基,也就是basis。
  • 简单说,在线性代数里,basis 是指空间里一系列线性独立的向量,而这个空间里的任何其他向量,都可以由这些个向量的线性组合来表示。
  • 小波指的是一种能量在时域非常集中的波,它的能量有限,都集中在某一点附近,而且积分的值为零,这说明它与傅里叶波一样是正交波。

MediaPipe介绍
https://blog.csdn.net/weixin_38346042/article/details/123399492

  • MediaPipe为我们日常使用的革命性产品和服务提供动力。与资源消耗型的机器学习框架不同,MediaPipe只需要最少的资源。
  • MediaPipe是一个用于构建机器学习管道的框架,用于处理视频、音频等时间序列数据。
  • Solutions是基于特定的预训练TensorFlow或TFLite模型的开源预构建示例:
    • 人脸检测
    • Face Mesh
    • 虹膜
    • 手势
    • 姿态
    • 人体
    • 人物分割
    • 头发分割
    • 目标检测
    • Box Tracking
    • Instant Motion Tracking
    • 3D目标检测
    • 特征匹配
    • AutoFlip
    • MediaSequence
    • YouTube-8M
  • MediaPipe依赖OpenCV来处理视频,FFMPEG来处理音频数据。它还有其他依赖项,如OpenGL/Metal、Tensorflow、Eigen等。

javascript 函数时

实现分组聚合

> var group_by_count = list => list.reduce((a, b) => (a[b] = a[b] ? a[b]+1 : 1,a) , {})
undefined
> group_by_count([1,2,3,2,2,3])
{ '1': 1, '2': 3, '3': 2 }
> group_by_count('aabbbcc'.split(''))
{ a: 2, b: 3, c: 2 }
> var by_fun = x => x
undefined
> by_fun(5)
5
> var sum = list => list.reduce((r, x) => r+x, 0)
undefined
> sum([1,2,3])
6
> var avg = list => sum(list)/list.length
undefined
> avg([1,2,3])
2
> var group_by = (list, by) => list.reduce((r, x) => (k = by(x),r[k]||(r[k]=[]),r[k].push(x),r), {})
undefined
> groups = group_by([1,2,3,2,2,3], x=>x)
{ '1': [ 1 ], '2': [ 2, 2, 2 ], '3': [ 3, 3 ] }
> var agg = (groups, fun) => Object.entries(groups).reduce((r, x) => (r[x[0]]=fun(x[1]),r), {})
undefined
> agg(groups, sum)
{ '1': 1, '2': 6, '3': 6 }
> by_a = x=>x['a']
[Function: by_a]
> sum_b = x=>sum(x.map(y=>y['b']))
[Function: sum_b]
> var group_agg = (list, by_fun, agg_fun) => agg(group_by(list, by_fun), agg_fun)
undefined
> group_agg([{a:1,b:2},{a:1,b:2},{a:2,b:3}], by_a, sum_b)
{ '1': 4, '2': 3 }

Laravel

Schedule

$schedule->call(function () {
    Log::info('任务调度');
})->everyMinute();
->cron(‘* * * * *’); 在自定义Cron调度上运行任务

->everyMinute(); 每分钟运行一次任务
->everyFiveMinutes(); 每五分钟运行一次任务
->everyTenMinutes(); 每十分钟运行一次任务
->everyThirtyMinutes(); 每三十分钟运行一次任务
->hourly(); 每小时运行一次任务
->daily(); 每天凌晨零点运行任务
->dailyAt(‘13:00’); 每天13:00运行任务
->twiceDaily(1, 13); 每天1:00 & 13:00运行任务
->weekly(); 每周运行一次任务
->monthly(); 每月运行一次任务

C 语言

请SSE/SSE2熟悉的前辈指点下指令,比较简单
https://bbs.csdn.net/topics/391003443

  • src/des 地址十六字节对齐
  • 复制数据量 大于 512 bytes

标准库的 memcpy 在满足这两个条件的情况下 会使用 sse 的 movdqa 来复制

TLB缓存是个神马鬼,如何查看TLB miss?
https://zhuanlan.zhihu.com/p/79607142

perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses

How to increase performance of memcpy
https://stackoverflow.com/questions/4260602/how-to-increase-performance-of-memcpy

you should have SSE or similar extensions enabled as the vector unit often can write 128 bits to the memory compared to 64 bits for the CPU. and make sure that both the source and destination is aligned to 128 bits. If your source and destination are not aligned respective to each other your memcpy() will have to do some serious magic. :)

First of all, you need to check that memory is aligned on 16 byte boundary, otherwise you get penalties. This is the most important thing.

rep movsb指令解析
movsb指令用于把字节从ds:si 搬到es:di;rep是repeat的意思,rep movsb 就是多次搬运。搬运前先把字符串的长度存在cx寄存器中,然后重复的次数就是cx寄存器所存数据的值。

gcc 内联asm
https://blog.csdn.net/farmwang/article/details/50153529

#include <stdio.h>  
  
int main()  
{  
    int a=1, b=2, c=0;  
  
    // 蛋疼的 add 操作  
    asm(  
        "addl %2, %0"       // 1  
        : "=g"(c)           // 2  
        : "0"(a), "g"(b)    // 3  
        : "memory");        // 4  
  
    printf("现在c是:%d\n", c);  
    return 0;  
}  

软件架构设计 专栏
https://www.zhihu.com/column/kls-software-arch-world

弟子规:美国军方禁止在C语言程序中使用malloc
https://zhuanlan.zhihu.com/p/69365944

多核MMU和ASID管理逻辑
https://zhuanlan.zhihu.com/p/118244515

false sharing(伪共享) 及 c代码实现
https://zhuanlan.zhihu.com/p/417325161

MESI协议将cache line的状态分成以下四种:

  • Modified:当前CPU cache拥有最新数据,被修改过的(最新的cache line),其他CPU拥有失效数据(cache line的状态是Invalid),当被写回主存之后,该缓存行的状态会变成Exclusive状态,其他CPU必须在下次需要时从主存读取数据;
  • Exclusive:只有当前CPU中有数据,其他CPU中没有改数据,当前CPU的数据和主存中的数据是一致的,当有其他CPU读取该缓存行时,变为Shared;
  • Shared:当前CPU和其他CPU中都有共同数据,并且和主存中的数据一致,当一个CPU修改该缓存行时,其他CPU对应的缓存行数据变为Modified;
  • Invalid:当前CPU中的数据失效,数据应该从主存中获取,其他CPU中可能有数据也可能无数据,当前CPU中的数据和主存被认为是不一致的;

memcpy() implementation
https://codereview.stackexchange.com/questions/41094/memcpy-implementation

Very fast memcpy for image processing?
https://stackoverflow.com/questions/1715224/very-fast-memcpy-for-image-processing/1715385#1715385

implicit declaration of function ‘gets’; did you mean ‘fgets’?
c11下去除了gets函数,我们可以用fgets函数来代替。

Address Sanitizer 用法 asan
https://www.jianshu.com/p/3a2df9b7c353

Implementing realloc in C
https://codereview.stackexchange.com/questions/151019/implementing-realloc-in-c

munmap_chunk(): invalid pointer
https://stackoverflow.com/questions/32118545/munmap-chunk-invalid-pointer

realloc() invalid old size
https://stackoverflow.com/questions/24579698/realloc-invalid-old-size

appending to a memory-mapped file
https://stackoverflow.com/questions/4460507/appending-to-a-memory-mapped-file

void *new_mapping = mremap(mapping, size, size + GROWTH, MREMAP_MAYMOVE);
if (new_mapping == MAP_FAILED)
    // handle error
mapping = new_mapping;

How to get mmap’ed memory to sync to the file?
https://stackoverflow.com/questions/16032396/how-to-get-mmaped-memory-to-sync-to-the-file

Also, you need to set the size of the file with ftruncate. Otherwise the mmaped area just covers parts of the file that don’t exist.

If you really want to make sure that the data ends up on disk, use msync, but normally you’ll be able to see the contents you wrote into the mmap:ed area immediately unless you’re on one of the few operating systems that doesn’t have a unified buffer and object cache.

Linux内存映射
https://blog.csdn.net/qq_43334597/article/details/124306981

按文件分:

  • 文件映射:将一个文件的一部分直接映射到调用进程的虚拟内存中
  • 匿名映射:没有对应文件,被映射的分页会初始化为0

按权限分:

  • 私有映射:写时复制,变更不会再底层文件进行
  • 共享映射:变更发生在底层文件

将上面两两组合:

  • 私有文件映射:使用一个文件的内容来初始化一块内存区域
  • 私有匿名映射:为一个进程分配新的内存
  • 共享文件映射:代替 read() 和 write() 、IPC
  • 共享匿名映射:实现相关进程实现类似于共享内存

进程执行 exec() 时映射会丢失,但通过 fork() 的子进程会继承映射

qsort doesn’t sort negative floats correctly
https://github.com/emscripten-core/emscripten/issues/4204

用库函数 qsort 对 float 数组进行排序的时候有 bug,不能写成

return *(float*)a-*(float*)b

因为qsort对负的浮点数支持有问题,得写成

if (a>b) return 1;
if (a<b) return -1;
return 0;

随机浮点数: https://stackoverflow.com/questions/13408990/how-to-generate-random-float-number-in-c

float float_rand( float min, float max )
{
    float scale = rand() / (float) RAND_MAX; /* [0, 1.0] */
    return min + scale * ( max - min );      /* [min, max] */
}

How do realloc and memcpy work?
https://stackoverflow.com/questions/362760/how-do-realloc-and-memcpy-work

The performance of memcpy can’t really be better than O(N) but it can be optimized so that it outperforms manual copying; for example, it might be able to copy 4 bytes in the time it takes you to copy 1 byte. Many memcpy implementations are written in assembly using optimized instructions that can copy multiple elements at a time which is usually faster than copying data one byte at a time.

C - split string into an array of strings
https://stackoverflow.com/questions/11198604/c-split-string-into-an-array-of-strings

char    str[]= "ls -l";
char ** res  = NULL;
char *  p    = strtok (str, " ");
int n_spaces = 0, i;


/* split string and append tokens to 'res' */
while (p) {
  res = realloc (res, sizeof (char*) * ++n_spaces);
  if (res == NULL)
    exit (-1); /* memory allocation failed */
  res[n_spaces-1] = p;
  p = strtok (NULL, " ");
}

/* realloc one extra element for the last NULL */
res = realloc (res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = 0;

/* print the result */
for (i = 0; i < (n_spaces+1); ++i)
  printf ("res[%d] = %s\n", i, res[i]);

/* free the memory allocated */
free (res);

Removing trailing newline character from fgets() input
https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input

buffer[strcspn(buffer, "\n")] = 0;
buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...

line[strlen(line) - 1] = '\0';

char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
    size_t len = strlen(buffer);
    if (len > 0 && buffer[len-1] == '\n') {
        buffer[--len] = '\0';
    }
}

Trim a string in C [duplicate]
https://stackoverflow.com/questions/656542/trim-a-string-in-c

char *ltrim(char *s)
{
    while(isspace(*s)) s++;
    return s;
}

char *rtrim(char *s)
{
    char* back = s + strlen(s);
    while(isspace(*--back));
    *(back+1) = '\0';
    return s;
}

char *trim(char *s)
{
    return rtrim(ltrim(s));
}

// Note: This function returns a pointer to a substring of the original string.
// If the given string was allocated dynamically, the caller must not overwrite
// that pointer with the returned value, since the original pointer must be
// deallocated using the same allocator with which it was allocated.  The return
// value must NOT be deallocated using free() etc.
char *trimwhitespace(char *str)
{
  char *end;

  // Trim leading space
  while(isspace((unsigned char)*str)) str++;

  if(*str == 0)  // All spaces?
    return str;

  // Trim trailing space
  end = str + strlen(str) - 1;
  while(end > str && isspace((unsigned char)*end)) end--;

  // Write new null terminator character
  end[1] = '\0';

  return str;
}

C read file line by line
https://stackoverflow.com/questions/3501338/c-read-file-line-by-line

#define _GNU_SOURCE

FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
while ((read = getline(&line, &len, fp)) != -1) {
    printf("Retrieved line of length %zu:\n", read);
    printf("%s", line);
}
if (line) free(line);

python

基于pywebview的桌面小工具开发记录
https://www.jianshu.com/p/3909e8b90c22

史上最全面K近邻算法/KNN算法详解+python实现
https://zhuanlan.zhihu.com/p/341572059

def euc_dis(instance1, instance2):
    return np.sqrt(np.sum((instance1-instance2)**2))

def knn_classify(X, y, testInstance, k):
    dists=[euc_dis(x,testInstance) for x in X]
    idxknn= np.argsort(dists)[:k]
    yknn=y[idxknn]
    return Counter(yknn).most_common(1)[0][0]

predictions = [knn_classify(X_train, y_train, data, 3) for data in X_test]
correct = np.count_nonzero((predictions==y_test)==True)
print ("Accuracy is: %.3f" %(correct/len(X_test)))

如果选择较大K值,就相当于用较大邻域中的训练实例进行预测,其优点是可以减少学习的估计误差,但近似误差会增大,也就是对输入实例预测不准确,K值得增大就意味着整体模型变的简单

  • 近似误差:**可以理解为对现有训练集的训练误差。
  • 估计误差:**可以理解为对测试集的测试误差。
  • 近似误差关注训练集,如果k值小了会出现过拟合的现象,对现有的训练集能有很好的预测,但是对未知的测试样本将会出现较大偏差的预测。模型本身不是最接近最佳模型。
  • 估计误差关注测试集,估计误差小了说明对未知数据的预测能力好。模型本身最接近最佳模型。

鸢尾花(Iris)数据集
https://blog.csdn.net/qinzhongyuan/article/details/106434854

算法

史上最强图解Treap总结, 不是浅谈!
https://blog.csdn.net/simpsonk/article/details/72832959

树堆(Treap)图文详解与实现
https://cloud.tencent.com/developer/article/1177129

面试官问我:什么是树堆(Treap)?
https://zhuanlan.zhihu.com/p/375122996

gdb

gcc -g 051.c
gdb ./a.out
    r

javascript

使用 Service Workers
https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers

The difference between Service Workers, Web Workers and WebSockets
https://aarontgrogg.com/blog/2015/07/20/the-difference-between-service-workers-web-workers-and-websockets/

linux

聊聊CPU的LOCK指令
https://mp.weixin.qq.com/s/8A4sas51tqMmpOwa7pCnJg

计算机组成-无锁编程追求极致性能
https://zhuanlan.zhihu.com/p/330476321

Cache和DMA一致性
https://zhuanlan.zhihu.com/p/109919756

并发基础理论:缓存可见性、MESI协议、内存屏障、JMM
https://zhuanlan.zhihu.com/p/84500221

单片机入门之锁存器
https://baijiahao.baidu.com/s?id=1725115907776029134&wfr=spider&for=pc

  • 数字系统中,要经常用到能存储二进制信息(数字信息)的电路,而锁存器就具有这种功能。
  • 双稳态电路的特点是具有两个稳定的状态,并且在外加触发信号的作用下,可以由一种稳定状态转换为另一种稳定状态。
  • 锁存器基本特性:
    • 它有两个稳定状态,可分别用来表示二进制数0和1;
    • 在输入信号作用下锁存器的两个稳定状态可相互转换,输入信号消失后,已转换的稳定状态可长期保持(在通电状态下)。
  • RS锁存器可以由两个与非门,或者两个或非门实现。
  • 与非门的逻辑特点:全1输出0,有0输出1

特殊用途寄存器,顾名思义是仅为一项任务而设计的寄存器。例如,cs,ds,gs 和其他段寄存器属于特殊目的寄存器,因为它们的存在是为了保存段号。 eax,ecx 等是一般用途的寄存器,因为你可以无限制地使用它们。 例如,你不能移动 ds,但是可以移动 eax,ebx。

  • 通用目的寄存器比如有:eax、ecx、edx、ebx、esi、edi、ebp、esp
  • 特殊目的寄存器比如有:cs、ds、ss、es、fs、gs、eip、flag

分享一些eBPF技术相关的PDF
https://www.cnxct.com/ebpf-slide-pdf-share/
https://github.com/ehids/ebpf-slide

linux下直接I/O(direct io)深入解析与实践
http://t.zoukankan.com/zhjh256-p-12182523.html

  • 默认情况下,linux会将进程未使用的内存用于页面缓存,因为相比直接读写磁盘而言,内存的性能高几个数量级,即使是SSD亦如此。
  • 虽然页面缓存能够极大的提升性能,但是其不是没有缺点的,尤其是哪些只会读写一次或应用自身对数据进行了缓存的应用如oracle/mysql,如果全部os缓存,很可能会导致应用内存不足(特别是在应用不支持启动时lock memory或多应用环境下无法这么做时)。
  • 如果没有缓存,随机直接(指的是4K/8K块)I/O的性能是非常低下的。大块(顺序I/O)则快得多。
    • echo 1 > /proc/sys/vm/drop_caches 清空缓存
    • dd if=/dev/zero of=./a.dat bs=4k count=1M oflag=direct 小块io
    • dd if=/dev/zero of=./a.dat bs=1M count=4K oflag=direct 大块 io
    • sar -r 3 1000 监控内存变化
  • nocache命令,能够使得cp/scp等命令在执行后立刻清理页面缓存。
  • 可以通过 cgroup memcg 限制用户的使用量,但是因为 pagecache 是全局共享的(有可能是别的group申请的),所以 memcg 只能保证 rss+pagecache 不超过内存配额,不能单独限制每个 group 的 pagecache 用量,只是在内存不足时 pagecache 会被直接丢掉,虽然提供了 group 级别的统计功能,这样要精确隔离的话,就得为这些命令建立单独一个 cgroup。
    • 从上可知 cgroup 也可以和 dd 一样,可以保证不额外占用 pagecache,即使是用来过渡,但 cgroup 一定要保证有 rss 和 anon 外有一定的最小额外内存,否则容易发生 OOM。
  • nginx
    • 增加 directio 512k 指令后,nginx 对于静态资源就会走直接 I/O 模式了,也只有增加了该指令才是真正的直接I/O。
    • sendfile(它调用的是系统调用 sendfile,但是 sendfile 默认情况下并不走 NOCACHE_IO 模式,所以仍然会走页面缓存。
  • 对于文件读写,curl 的 --no-buffer 选项好像并没有生效,这样要想实现低内存占用文件,就得使用 java nio 或 c direct io 自行实现。
  • java 虽然提供了大量的 I/O 接口,但是大部分上层接口都是基于文件系统缓存的。要操作底层就需要对 NIO 比较熟悉了,核心又是 DirectBuffer 和 ByteBuffer
    • java 原生并不支持O_DIRECT选项,这样有个缺点就是写大文件会占用pagecache、亦或性能受到影响,因为要每次映射一部分,

一些主要应用和命令对文件I/O的管理方式。

应用	    默认模式(依赖OS或自身管理)	        相关控制参数
oracle	    sga控制	                                filesystemio_options
mysql	    buffer_pool控制	                        innodb_flush_log_at_trx_commit
mongodb	    依赖于操作系统	 
c	        通过 open 文件带上 O_DIRECT 参数,
            直接写到设备上。	 
java	    自己控制(文件读写除外),
            没有直接的参数控制	 
kafka	    scala写的,依赖于JVM,所以本质上也
            是自己控制,文件则依赖于OS	 
redis	    自己控制	                            maxmemory,提供了超过后的策略
zookeeper	跟kafka类似

cgroup

yum install libcgroup
service cgconfig start
cgcreate -a uft_trade_mysql -gmemory:memcg
cd /cgroup/memory/memcg/
cat memory.limit_in_bytes
echo 1048576 > memory.limit_in_bytes
echo $$ > tasks
cp a.dat.new ~/a.dat  # 限额 1M 时内存不足被OOM kill Killed

nginx 中的直接 I/O:

aio threads;
directio 512k;
output_buffers 1 8m;   # 其对性能会有高达10%的影响,用于设置从磁盘读取缓冲区响应的数量和大小。

TODO:

Linux 直接I/O 原理与实现
https://blog.csdn.net/qq_40989769/article/details/110645449
Linux操作系统I/O机制原理与实现(图文详解)
https://zhuanlan.zhihu.com/p/438526019
Java-NIO之Channel(通道)
https://blog.csdn.net/weixin_45566993/article/details/124096517
MMAP和DIRECT IO区别
https://www.cnblogs.com/zhaoyl/p/5901680.html
Java网络编程与NIO详解8:浅析mmap和Direct Buffer
https://blog.csdn.net/AliCoder/article/details/103039202

文件系统性能对比:https://blog.csdn.net/linkyy5/article/details/125955196

  • 高并发读写:btrfs 最优,xfs 及 ext4 稍好,zfs 及 ntfs 最差。
  • 随机读写:ntfs 最优,其余相差不大。
  • 顺序读写:ntfs 最优,btrfs 最差,其余相差不大
  • 顺序多文件写入:f2fs 最优,其余相差不大。
  • 并发多文件写入:ext4 最优,ntfs 最差,zfs 较弱,其余相差不大。
  • 顺序多文件写入不同子目录:f2fs 最优,其余相差不大。
  • 多客户使用体验:xfs 最优,ntfs 最差,reiserFS 较弱,其余皆优秀。

各个文件系统具有特性,且各有优缺点:

  • btrfs 仍处于开发阶段,其 COW (Copy On Write) 机制使其对数据库的插入操作表现较差。
  • xfs 和 ext4 的综合素质优秀,特定能力上不会过于耀眼,但是对用户来说综合体验最佳。
  • f2fs 在多文件情境下表现出色。
  • reiserFS 即将被 reiser4 文件系统取代,综合性能大不及其它系统。
  • ntfs 在串行的工作模式下,其随机读写和顺序读写能力都极高;反之,其在高并发高压环境下表现不佳。

许多文件系统并不一定专门为性能而生,它们都有自己的适用场景,每个文件系统都有其独特的设计初衷。例如:

  • btrfs 和 zfs 都具有 COW(Copy On Write) 机制。COW 机制使得它们在进行修改操作时具有不俗的性能,但也带来了磁盘空间的浪费,并增加了读取时的消耗。
  • btrfs 和 zfs 都自带 raid 功能。在数据可用性有要求的情况下,相比其他的文件系统,它们能提供开箱即用的 raid 阵列能力。
  • btrfs 对所有数据都带有 checksum 机制,确保文件完整性。
  • xfs 具有动态 inode 分配能力,适合大文件分配。

陈炽卉 AIX 性能管理与监控建议
http://www.360doc.com/content/22/0629/22/2245786_1038015973.shtml

How to check disk I/O utilization per process?
https://serverfault.com/questions/169676/how-to-check-disk-i-o-utilization-per-process

iotop
pidstat -dl 20
cut -d" " -f 1,2,42 /proc/[0-9]*/stat | sort -n -k +3

atop -a -w historical_everything.atop 10 1080 &
atop -r historical_everything.atop

    t - move forward to the next data gathering (10 seconds)
    d - show the disk io oriented information per process
    D - sort the processes based on disk activity
    T - go backwards 1 data point (10 seconds probably)
    h - bring up help
    b - jump to a time (nearest prior datapoint) - e.g. b12:00 - only jumps forward
    1 - display per second instead of delta since last datapiont in the upper half of the display

sudo apt install blktrace
sudo btrace /dev/mapper/ubuntu--server--vg-root
date >>/tmp/wtf && ps -eo "cmd,pid,min_flt,maj_flt" >>/tmp/wtf

Amazon MySQL RDS迁移到Amazon Aurora并要求最小停机时间
https://aws.amazon.com/cn/blogs/china/every-scene-mysql-database-move-to-amazon-aurora/

Perf with GUI
https://oopsmonk.github.io/posts/2022-04-28-perf/
https://github.com/KDAB/hotspot

perf stat -d ./a.out

View size of CPU cache through the command-line?
https://askubuntu.com/questions/724449/view-size-of-cpu-cache-through-the-command-line

lscpu | grep "cache"
getconf -a | grep CACHE

How to Use the time Command on Linux
https://www.howtogeek.com/415977/how-to-use-the-time-command-on-linux/

Using a \ character before the command name is the same as using command before the command name.

\time -f "Program: %C\nTotal time: %E\nUser Mode (s) %U\nKernel Mode (s) %S\nCPU: %P" sleep 1

游戏

  • GBA
    • 牧场物语:矿石镇的伙伴们
    • 最终幻想Advance
    • 恶魔城
    • 塞尔达传说缩小帽
    • 口袋妖怪
      • 精灵宝可梦红宝石·蓝宝石(2002-11-21)
      • 精灵宝可梦火红·叶绿(2004-01-29)
      • 精灵宝可梦绿宝石(2004-09-16)
      • 精灵宝可梦不可思议的迷宫:赤之救助队(2005-11-17)
    • 火焰纹章

马里奥大叔的所有资料
http://www.youxi131.com/wlyx/125604.html

PHP

显示错误
php -d display_errors=on artisan

mysql

查看 buffer pool

select @@innodb_buffer_pool_size / pow(2,30) as gibibytes;

按条件修改列

mysql> create database test;
Query OK, 1 row affected (0.01 sec)

mysql> use test;
Database changed
mysql> create table t1(c varchar(4));
Query OK, 0 rows affected (0.05 sec)

mysql> insert into t1 values (1),(2),(3);
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select * from t1;
+------+
| c    |
+------+
| 1    |
| 2    |
| 3    |
+------+
3 rows in set (0.00 sec)

mysql> update t1 set c = case when c='1' then 'a' when c='2' then 'b' when c='3' then 'c' else c end;
Query OK, 3 rows affected (0.00 sec)
Rows matched: 3  Changed: 3  Warnings: 0

mysql> select * from t1;
+------+
| c    |
+------+
| a    |
| b    |
| c    |
+------+
3 rows in set (0.00 sec)

VIM

vim 里的正则搜索,有特殊的语法+要转义

/^[0-9]\+,[^,]\+\n

How do I jump to the location of my last edit?
https://vi.stackexchange.com/questions/2001/how-do-i-jump-to-the-location-of-my-last-edit

`.
g, g;
ctrl+O ctrl+I

跳转指令

% 跳转到相配对的括号
gD 跳转到局部变量的定义处
'' 跳转到光标上次停靠的地方, 是两个', 而不是一个"
mx 设置书签,x只能是a-z的26个字母
`x 跳转到书签处("`"是1左边的键)
> 增加缩进,"x>"表示增加以下x行的缩进
< 减少缩进,"x<"表示减少以下x行的缩进

{ 跳到上一段的开头
} 跳到下一段的的开头
( 移到这个句子的开头
) 移到下一个句子的开头

[[ 跳转至上一个函数(要求代码块中'{'必须单独占一行)
]] 跳转至下一个函数(要求代码块中'{'必须单独占一行)

C-] 跳转至函数或变量定义处
C-O 返回跳转前位置
C-T 同上
nC-T 返回跳转 n 次

0 数字0,跳转至行首
^ 跳转至行第一个非空字符
$ 跳转至行尾

python

Invalid control character with Python json.loads
https://stackoverflow.com/questions/22394235/invalid-control-character-with-python-json-loads

json_str = json.loads(jsonString, strict=False)

202207

机构是如何评价基金经理的?
https://zhuanlan.zhihu.com/p/67250336

如何评价基金经理及基金的选择?
https://www.zhihu.com/question/22771562

python

lxml 使用
https://blog.csdn.net/ydw_ydw/article/details/82227699

from lxml import etree
html = etree.HTML(text)
for n in html.xpath('//h3[@class="text-heading css-1a2yizx"]'):
    print(n.text)
    for n2 in n.getnext().findall('li[@data-cy="browse-list-link"]/a'):
        print('\t%s' % (n2.text))

金融评测指标empyrical库详解Sortino、calmar、omega、sharpe、annual_return、max_drawdown
https://dev-docs.csdn.net/articles/c9ab471ae39247efa635f52081d88796/sharpe-sortino-omega-calmar-empyrical

国内装 virtual-env 报错

$ pip install virtual-env
Looking in indexes: http://mirrors.tencentyun.com/pypi/simple
ERROR: Could not find a version that satisfies the requirement virtual-env (from versions: none)
ERROR: No matching distribution found for virtual-env

如下可解决

pip install virtualenv -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com

将matplotlib绘制的图形直接以base64格式传递到html使用
https://www.jianshu.com/p/f3ea49e05600

from io import BytesIO
import base64
import numpy as np
import matplotlib.pyplot as plt

x = np.arange(100)
y = np.sin(x)

fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x,y)

# 写入内存
save_file = BytesIo()
plt.savefig(save_file, format='png')

# 转换base64并以utf8格式输出
save_file_base64 = base64.b64encode(save_file.getvalue()).decode('utf8')

vim

vim 最精简配置

set nocp nu ts=4 sw=4 et sta hls si noeb vb t_vb=

tmux

sudo apt-get install tmux
$ vim ~/.tmux.conf
    set-option -g mouse on

ctrl+b d
ctrl+b %
ctrl+b "
ctrl+b alt+left
tmux -ls
tmux tmux attach -t 0

tmux的复制粘贴

1. C-b [ 进入复制模式
2. 参考上表移动鼠标到要复制的区域,移动鼠标时可用vim的搜索功能"/","?"
3. 安空格键开始选择复制区域
4. 选择完成后安enter键退出
5. C-b ] 粘贴

postgree

取消分页

\pset pager off

显示边框

\pset linestyle ascii
\pset border 2
SELECT * FROM Pets;

sql split string by space into table in postgresql
https://stackoverflow.com/questions/1986491/sql-split-string-by-space-into-table-in-postgresql

select unnest(string_to_array('the quick lazy fox', ' '));

Word frequencies from strings in Postgres?
https://stackoverflow.com/questions/5226202/word-frequencies-from-strings-in-postgres

postgresql 数组类型
https://www.jb51.cc/postgresql/194660.html

用 python 写 postgree 自定义函数
https://www.postgresql.org/docs/current/plpython-funcs.html

# CREATE EXTENSION plpythonu;
CREATE EXTENSION

# CREATE OR REPLACE FUNCTION pysplit(s text)
#   RETURNS text
# AS $$
#   words = s.split()
#   return '|'.join([words[i]+' '+words[i+1] for i in range(len(words)-1)])
# $$ LANGUAGE plpythonu;
CREATE FUNCTION

# select regexp_split_to_table(pysplit('a b c d'), '\|');
 regexp_split_to_table
-----------------------
 a b
 b c
 c d
(3 rows)

PostgreSQL-触发器
http://www.manongjc.com/detail/29-qzkmtgoohzmphaz.html

触发器函数中的特殊变量

  • NEW:该变量为 INSERT/UPDATE 操作触发的行级触发器中存储的新的数据行,数据类型是 RECORD。 在语句级别的触发器里此变量没有分配,DELETE 操作触发的行级触发器中此变量也没有分配。
  • OLD:该变量为 UPDATE/DELETE 操作触发的行级触发器中存储的旧数据行,数据类型是 RECORD。 在语句级别的触发器里此变量没有分配, INSERT 操作触发的行级触发器中此变量也没有分配。
  • TG_NAME:数据类型是 name,该变量包含实际触发的触发器名。
  • TG_OP: 内容为 INSERT、UPDATE、DELETE、TRUNCATE 之一的字符串,用于指定 DML 语句的类型。
  • TG_TABLE_NAME: 触发器所在表的名称。

PostgreSQL 触发器
https://blog.csdn.net/pg_hgdb/article/details/121560616

# CREATE TABLE AUDIT(
EMP_ID INT NOT NULL,
ENTRY_DATE TEXT NOT NULL);

# CREATE TRIGGER example_trigger AFTER INSERT ON COMPANY FOR EACH ROW EXECUTE PROCEDURE auditlogfunc();

CREATE OR REPLACE FUNCTION auditlogfunc() RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO AUDIT(EMP_ID, ENTRY_DATE) VALUES (new.ID, current_timestamp);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 列出所有触发器 
SELECT * FROM pg_trigger;

-- 查看特定表的触发器
SELECT tgname FROM pg_trigger, pg_class WHERE tgrelid=pg_class.oid AND relname='company';

-- 删除触发器
drop trigger example_trigger on company;

postgres 自增序列
https://blog.csdn.net/m0_37664223/article/details/90052783

-- 查找 xxx 自增序列的当前值
select currval('xxx');
-- 查找 xxx 自增序列的下一个值
select nextval('xxx');
-- 创建 xxx 自增序列
CREATE SEQUENCE xxx
    INCREMENT 1    序列增长步值
    MINVALUE 1   最小值
    MAXVALUE 9999999999    最大值
    START 1  开始值
    CACHE 1  缓存值,会在cache中预存序列值,如果数据库异常关闭,序列值会丢失
    CYCLE;   循环,表示到最大值后从头开始

-- 修改 xxx 自增序列,除了 start 之外的其他值都可以修改
ALTER SEQUENCE xxx
    INCREMENT 10 
    MAXVALUE 100000000 
    CYCLE 
    NOCACHE ; 

----删除前先解除某个字段,例如表名是 student, name 字段对该序列的(序列名字是 name_seq)依赖
ALTER TABLE student ALTER COLUMN name SET DEFAULT null;

DROP SEQUENCE IF EXISTS "name_seq";

---- start_id 即 id 目前的最大值,可写为 1,
CREATE SEQUENCE "name_seq" START WITH start_id;
ALTER TABLE student ALTER COLUMN name SET DEFAULT nextval('name_seq'::regclass);

-- 设置自增长从当前最大值开始
select setval('seq', (select max(name) from "student"));

-- 重置自增字段为1
ALTER SEQUENCE seq RESTART WITH 1;

Postgresql 创建主键并设置自动递增的三种方法
https://blog.csdn.net/songchunyi/article/details/7711108

create table test_b
(
  id serial PRIMARY KEY,
  name character varying(128)
);

create table test_c 
(
  id integer PRIMARY KEY,
  name character varying(128)
);  
CREATE SEQUENCE test_c_id_seq
START WITH 1
INCREMENT BY 1
NO MINVALUE
NO MAXVALUE
CACHE 1;
alter table test_c alter column id set default nextval('test_c_id_seq');

创建索引

CREATE INDEX index_moni_gk_city_day ON moni_gk_city_day USING btree (datatime, citycode);

删除索引

drop index tab1_bill_code_index  ;

mysql

ip is blocked because of many connection errors 错误
https://debugah.com/host-blocked-because-of-many-connection-errors-how-to-solve-10147/

当客户端连接服务端超时(超过connect_timeout), 服务端就会给这个客户端记录一次error,当出错的次数达到max_connect_errors的时候,这个客户端就会被锁定。所以根据业务来尽量把这个值设置大一点,mysql默认值为10,我们可以根据具体需要设置大一点,这里设置为1000.(并非越大越好,越大被攻击时安全性越低)。
配置有master/slave主从数据库的要把主库和从库都修改一遍。

show status like  'Threads%';
SHOW VARIABLES LIKE '%error%';
SHOW VARIABLES LIKE '%wait_timeout%';
set global max_connect_errors = 1000;
flush hosts;

The value of the max_connection_errors system variable determines how many successive interrupted connection requests are permitted to myqsl server.

选取部分数据到新表

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
create table temp_temp as SELECT * FROM TABLE_NAME where a = 1;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

Any way to select without causing locking in MySQL?
https://stackoverflow.com/questions/917640/any-way-to-select-without-causing-locking-in-mysql

SELECT * FROM TABLE_NAME WITH (nolock)

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
COMMIT ;

mysql 出现 unblock with ‘mysqladmin flush-hosts’
https://wenku.baidu.com/view/0e7f56b268ec0975f46527d3240c844769eaa034.html

show variables like '%max_connect_errors%'; 
set global max_connect_errors = 100; 

flush hosts;

# vi /etc/my.cnf
max_connect_errors = 100

nginx

Nginx proxy_pass DNS Cache
https://www.nadeau.io/post/nginx-proxy_pass-dns-cache/

After some debugging, I finally discovered that the IP address nginx was hitting was different from the one that DNS was returning. It turns out that nginx resolves hostnames only once on load, meaning whatever IP address it got on load would stick around until reload.

server {
  listen 80;
  server_name files.example.com;

  // or use whatever resolver your machine is set to use
  resolver 8.8.8.8;

  set $proxy_pass_url http://example.s3.amazonaws.com;

  location / {
    proxy_pass $proxy_pass_url;
  }
}

nginx proxy_pass 后面是域名的时候,它会只解析一次 ip,然后缓存起来。

shell

ip 地址库:

命令行查询 ip 的所在地
https://www.maketecheasier.com/ip-address-geolocation-lookups-linux/

sudo apt-get install geoip-bin
geoiplookup 8.8.4.4

wget https://dl.miyuru.lk/geoip/maxmind/country/maxmind4.dat.gz
gunzip maxmind4.dat.gz
sudo mv maxmind4.dat /usr/share/GeoIP/GeoIP.dat.gz

wget https://dl.miyuru.lk/geoip/maxmind/city/maxmind4.dat.gz
gunzip maxmind4.dat.gz
sudo mv maxmind4.dat /usr/share/GeoIP/maxmind4.city.dat

wget https://dl.miyuru.lk/geoip/maxmind/asn/maxmind4.dat.gz
gunzip maxmind4.dat.gz
sudo mv maxmind4.dat /usr/share/GeoIP/maxmind4.asn.dat

geoiplookup -f /usr/share/GeoIP/GeoIP.dat.gz 54.241.194.177
geoiplookup -f /usr/share/GeoIP/maxmind4.city.dat 54.241.194.177
geoiplookup -f /usr/share/GeoIP/maxmind4.asn.dat 54.241.194.177

获取文件名

input="/home/data.txt"
file_name="${input##*/}"

How can I use sed to replace a multi-line string?
https://unix.stackexchange.com/questions/26284/how-can-i-use-sed-to-replace-a-multi-line-string

sed 多行模式

cat alpha.txt | tr '\n' '\r' | sed -e 's/a test\rPlease do not/not a test\rBe/'  | tr '\r' '\n'

sed 不带 -r 的正则表达式中括号里的空格要写在前面,不能写在后面

$ echo 'a-b c'| sed 's/[ a-z\-]/6/g'
66666
$ echo 'a-b c'| sed 's/[a-z\- ]/6/g'
sed: -e expression #1, char 14: Invalid range end
$ echo 'a-b c'| sed 's/[a-z- ]/6/g'
sed: -e expression #1, char 13: Invalid range end

tshark

https://www.jianshu.com/p/b78191fa4305

实时打印当前mysql查询语句

tshark -s 512 -i eth1 -n -f 'tcp dst port 3306' -R 'mysql.query' -T fields -e mysql.query

实时打印当前http请求的url(包括域名)

tshark  -s 512 -i eth0 -n -f 'tcp dst port 80'  -T fields -e http.host -e http.request.uri -l | grep -Ev '^\s+$' 

cloudwatch logs

nginx log format:带空格,带逗号的字段用引号括起来

log_format main '$time_iso8601 $status $request_time $upstream_response_time $upstream_cache_status $remote_addr "$http_x_forwarded_for" $http_host $upstream_addr "$request" $body_bytes_sent "$http_referer" "$http_user_agent"';

解析字段对应字段用引号括起来

parse '* * * * * * "*" * * "* * *" * * "*"' as time_iso8601,status,request_time,upstream_response_time,upstream_cache_status,remote_addr,http_x_forwarded_for, http_host,upstream_addr,method,url,http_version,body_bytes_sent,http_referer,http_user_agent
| limit 10

量化

宏观指标

  • GDP:国内生产总值
    • GDP 越高,表示国内经济越繁荣
  • CPI: 物价指数,反应通胀水平
    • 3% 是警戒线,高于警戒线,一般会紧缩
    • 低于 0 会通缩,问题更严重
    • 1-2% 是温和通胀,属于正常情况
  • PPI: 工业品价格指数,主要指原材料和能源价格,是周期类投资必看的指标。
    • 经济周期向上一般 PPI 会向上,
  • M0 M1 M2: M0 表示流通中的现金;M1 是 M0 + 活期存款; M2 是 M1 + 定期存款
    • 如果 M1 增速 大于 M2 说明市场资金很活跃,一般发生在牛市,原理就是大家把定期存款取出来到市场上了
    • 相反 M1 下穿 M2,意味着市场货币收缩了,大家把活期转成了定期,房价和权益市场就会下跌。
  • 十年期国债收益率:可以当做无风险收益率,
    • 国债收益率上升表示市场缺钱,对股市利空,如果利率长的太急,很有可能形成股债双杀。
    • 国债收益率下行,意味着市场上的钱越来越多,市场资金充裕,是投资债券的好时机。
    • 新债利率低于老债,所以大家都去买老债,所以债券价格就会上升。
  • 社融:社会融资总额,包括银行贷款,股票融资,发债融资,非标融资,专项债,社融反应资金的需求程度,
    • 社融一般会跟随 M2 的走势,如果 M2 上穿社融,说明放水意义不大了。
    • 社融下降意味着经济需求不足,说明大家对未来预期不好。
  • 社消总额:代表大家消费能力和意愿。
    • 社消下降说明消费出了问题。
    • 经济三驾马车:投资,进出口,消费。进出口受外部影响比较大,自己说了不算,假如投资也拉不动经济,就全部指望消费了。
  • PMI:采购人经理指数,表示工厂里的采购经理如何看待经济,通常是经济的先行指标。
    • 50 为枯荣线,枯荣线之上表示经济扩张,之下表示经济收缩。
    • 每个月会公布两个 PMI 指标,统计局的数据偏向国企大型企业,财新的数据代表中小企业。
  • CRB 指数:路透社编制的反应大宗商品周期性波动的指数,
    • 大宗商品主要分 4 类:1、工业金属,铜铝锌锡;2、贵金属,黄金白银;3、农产品,小麦玉米;4、能源品,煤炭石油。
    • 关注大宗商品的投资者需要关注 CRB 商品指数,如果不呈现上升趋势,周期行业还是少碰为好。
  • 库存周期:库存是一个重要的经济指标,反应经济周期。
    • 主动去库存:经济不景气,库存太大,降价甩卖,所以大宗商品会走低。
    • 被动去库存:经济复苏,涨价去库存,仓库的东西不多了,不着急卖了,因为供应短缺,所以大宗商品价格甚至会有上涨
    • 主动补库存:经济繁荣,价格涨,库存升,仓库的东西不够卖了,所以一边加价,一边压货。
    • 被动补库存:开始衰退,价格开始下降了,库存还在上升。
  • 信用利差:不同信用的人的融资利率不同,高信用和低信用的融资利率差就是信用利差。
    • 信用利差上升说明经济遇冷,银行给信用差的人的贷款利率提高,所以中小企业成本会上升。
    • 信用利差下降,说明银行不担心信用差的人违约,所以降低利率,中小企业会收益。
    • 信用利差上升时,股市表现就会不好。
    • 信用利差下降时,股市就不会那么糟糕了。
  • MLF 麻辣粉:中期借款便利,央行印出来的钱并借给商业银行的钱的利率,它代表基准贷款利率
    • MLF 下降,贷款利率也会下降,相当于变相降息
    • 相反,MLF 上升就有加息的效果
  • DR 007: 银行间市场 7 天质押回购利率
    • 上升过快,表示银行开始收缩了
  • 其它:逆回购,银行间拆借利率,税,失业率,铜金比,油金比,GDP和国债比值

WorldQuant 101 Alphas

WorldQuant 101 Alphas及一些思考
https://zhuanlan.zhihu.com/p/52459234

价量关系。就算是新股民也会听说价量的段子,什么最近大盘缩量啊,量在价先啊,高手只看K线和成交量啊啥的。确实,价量是交易最基本的组成要素,无论提到多高的高度不为过。通常把价涨量缩和价跌量升称为背离,剩下两个有人喜欢叫同向,我喜欢叫共振。最简单描述价量关系的指标就是相关系数,101 Alphas中有很多种写法。

  • 背离
    • -1 * correlation(volume, close, N) : 成交量与收盘价在N日内的背离程度
    • -1 * correlation(delta(volume, 1), delta(close,1), N): 成交量变动与收盘价日内变动在N日内的背离程度
    • -1 * correlation(rank(delta(volume), 1)), rank(delta(close,1)), N) : 成交量变动全市场强度与收盘价日内变动全市场强度在N日内的背离程度
    • -1 * correlation(ts_rank(delta(volume), 1),M), ts_rank(delta(close,1),K), N): 当日成交量变动在M日内的相对强度与当日收盘价日内变动在K日内的相对强度 在N日内的背离程度
  • 共振
    • 上面所有公式去掉-1
  • 契合程度
    • abs(correlation(·)) 这种写法,我称其为契合程度,在#036和#087中出现

单单就一个涨停板限制就可以把其中大多数alpha的构造逻辑摧毁,对于波动,在中国市场不太适合rank和ts_rank函数。

  • rank是横截面排序,某一股票的alpha在当前时刻下在其他所有股票的alpha中的位置;ts_rank是序列排序,某一股票的当前alpha在某段时间内的alpha中的位置。一个是与其他股票比较,一个是与自己比较,这两个函数都是在描述强弱。
  • 然而作用于涨跌幅的时候涨停板会从中作梗:首先是四舍五入的问题,涨停板的涨幅可以上达10.05%,下达9.95%,明明都是板却非要比个高低。由于磁吸效应的存在,涨停板强度的描述可以利用封板时间比,报成比,换手率等指标衡量。不过说回来,现在的主力真不喜欢拉板,熊市的磁吸效应没那么强而且从监管的角度来讲太危险了。
  • 其次是一字板本身的价量背离问题。对于单一bar来讲,一字板是最严重的价量背离。我不知道大多数人讲的价量关系是不是在流动性充裕的基础上的,当流动性有问题的时候,价量关系的衡量标准和平常必然不同。这个问题可以通过拉长时间区间来缓解,可以用长周期如周线来抵消涨停板带来的异常,也可以针对特点改一下rank与ts_rank。

基于短周期价量特征的多因子选股体系
https://www.cnblogs.com/bitquant/p/8393936.html

通过交易型阿尔法策略的研究,我们发现在A股市场,与传统多因子模型所获取的股票价值阿尔法收益相比,交易型阿尔法收益的空间更大、收益稳定性也更强。

即便是最纯粹的价值投资者也不得不承认,交易行为在短期内对股票价格起着几乎是决定性的影响,而发掘这种交易型套利空间正是量化投资的优势所在,因此量化模型在这一领域内应有着广泛的运用空间。

数值型因子的大规模分层测试—WorldQuant 101、国泰191、Sundays100+
https://zhuanlan.zhihu.com/p/60872286

国泰191 Alphas的研报《基于短周期价量特征的多因子选股体系》于2017年6月份公布,其中191个alphas有70个是WorldQuant 101因子原样照抄或者是小改一下

单因子测试

  • 主流单一因子测试方法也就分层法和 IC 法。
  • 不过需要注意的是,通常金工研究认为,测试单一因子的有效性应考虑市场因子、市值因子和行业因子的风险暴露,也即用线性回归残差替代因子本身。
  • 但我感觉不一定必须用,毕竟之后的因子库还要降维的。虽然可解释性上更低了一点,也更不符合金融行业的习惯,但在不深入挖掘某一因子的风险(收益)来源时,此举加大了工作量,说到底还是看需求。

分层法: 剔除风险暴露的因子值进行了月度调仓的分层法测试

  • 显著性(TOP20% 与 BOTTOM20% 差值的期望大不大)
  • 稳健性(TOP20% 与 BOTTOM20% 差值的方差小不小)
  • 在一条线上可以理解为收益率与回撤。
  • 但有很多因子你会发现,尾部的超额收益怎么都比不上中间两组。这就要用全市场的几条线来看了。

关于市值:Alpha = - closerank(vwap - close) / rank(vwap + close)

  • 市值因子一般认为是 CAPM 的漏洞,定价时就没考虑这个;
  • 市场对小公司的信息也没有挖掘得很充分。
  • 对于我国的低价因子还有两点,
    • 一是市场监管不到位导致的财务造假,
    • 二是注册制不到位导致的壳资源预期。
  • 这些都是制度问题,制度带来的收益必然随制度变化而变化。因此当我国退市、注册两个制度变化的时候,必然会对小市值策略产生影响,但不至于颠覆。
  • 我的愚见,对于一个所谓的好因子,首先应看是不是市值暴露带来的收益,即有没有市值味儿。
  • wq_alpha 和 gt_alpha 中,十分显著且稳定的基本上都有市值暴露。

短期价量背离程度的强度:rank(covariance(rank(high), rank(volume), 5))

  • 价量背离之前说过了是一个不错的因子,除了牛市中后期(加速)的时候,基本都有稳定的反向关系,无论参数从 5 到 20。
  • 加入 rank() 函数之后,牛市中后期也不会影响因子的稳定性,反而会得到超额收益,
  • 所以说,“放量大涨能延续” 说的是大盘,而不是个股(甚至大盘也不对)。缩量才是王道!!!

研报中的一些圣经

  • 事件因子圣经:20160527-国泰-事件驱动的因子化特征
  • 价值投资圣经:20170831-东方-质优股量化投资
  • 资金流因子圣经?:20180611-长江-资金流因子全测试
  • 多因子模型组合圣经:20171117-中信-多因子模型的组合优化与风险

技术指标调参
https://zhuanlan.zhihu.com/p/53279433

  • 技术分析到底有没有用我不知道,画线派、价量派和指标派各有各的理;
  • 有人认为只要精通一两种方法,也有人认为多种方法要结合使用。
  • 说到底,在技术分析没有引入“决策”之前,依旧可以将其视为因子,毕竟万物皆因子。是因子就可以检验相关性,这就是本文所探讨的东西。

本文选取了 6 类 10 种技术指标,计算他们的值,变动率,波动率与未来股票的值,变动率的关系。

  • 趋势类:MACD — macd;DMI — pdi-mdi;ADX — adx;
  • 随机类:KD — k-d;CCI — cci;
  • 波动类:STD — 平均股价的标准差;ATR—atr;
  • 成交量类:OBV — obv简单平均;
  • 通道类:SAR — 股价均值-sar;
  • 能量类:BRAR — br-ar;
  • benchmark:n日前的平均股价;

精选研报复现—牛熊线BBCurve
https://zhuanlan.zhihu.com/p/36437315

@jit
def cal_bull(close,mu,sigma,T,epsilon):
    return close * np.exp(T*mu + np.sqrt(T)*sigma*epsilon)

epsilon = scipy.stats.t.ppf(1-alpha/2,n) #ε
ripesd['logreturn'] = ripesd['close'].map(lambda x: np.log(x)).diff() #对数收益率
ripesd['mu'] = ripesd['logreturn'].rolling(n*T).mean() #μ
ripesd['sigma'] = ripesd['logreturn'].rolling(n*T).std() #σ
ripesd['close_-t'] = ripesd['close'].shift(T)
ripesd['bull'] = ripesd.apply(lambda x: cal_bull(x['close_-t'],x['mu'],x['sigma'],T,epsilon),axis=1)
ripesd = ripesd.dropna()

#上穿下穿买卖点
ripesd['buy'] = ripesd.apply(lambda x: True if x['close'] >= x['bull'] and x['close_-1'] <= x['bull_-1'] else False,axis=1)
ripesd['sell'] = ripesd.apply(lambda x: True if x['close'] <= x['bull'] and x['close_-1'] >= x['bull_-1'] else False,axis=1)


@jit
def cal_bull_3ver(close,mu,sigma,T,epsilon):
    return close * ((1+mu)**T + np.sqrt(T)*sigma*epsilon)

epsilon = scipy.stats.t.ppf(1-alpha/2,n)
ripesd['return'] = ripesd['close'].pct_change() #算术收益率
ripesd['mu'] = ripesd['return'].rolling(n*T).mean()
ripesd['sigma'] = ripesd['return'].rolling(n*T).std()
ripesd['close_-t'] = ripesd['close'].shift(T)
ripesd['bull'] = ripesd.apply(lambda x: cal_bull_3ver(x['close_-t'],x['mu'],x['sigma'],T,epsilon),axis=1)

世坤WorldQuant因子分析框架
https://zhuanlan.zhihu.com/p/396465853

  • 2015年公布的世坤101alpha论文讲述了World Quant(投资机构)用量价,波动率,流动性概念构建的101个当时实盘中被使用的选股因子。
  • 从本质来说因子可分趋势,回归,和趋势+回归;统计因子,和条件触发。
  • 实际交易中,盘口数据(order book),对冲成本,过拟合的哲学问题,怎么用机器学习去撸数以万计的alpha rank,时序,截面,lead-lag自变量因子,并保证系统先进(计算速度,cuda,防止internal crossing等)才是真正赚钱的机制。
  • 因此世坤公布这篇论文是目前国内大部分私募研究的基石,只能给大家提供研究的方向,根本不会堵塞公司本来的 alpha 通道。
  • 另外,一个很重要的结论是波动率对因子起决定性作用。而换手率(交易量)和对数回报并没有很大的相关性。
  • 因此除了频段以外,波动率是一个很好发分类法则去判断做趋势还是回归。(高频偏趋势,低频偏回归)
  • 在世坤 101 个因子里,平均协方差和夏普分别为 15.9% 和 2.25。

教你用Python计算对量化交易至关重要的VWAP指标
https://zhuanlan.zhihu.com/p/488527696

  • TP =(最高价+最低价+收盘价)/3V = 成交量

  • VWAP = (TP_1 * V_1 + TP_2 * V_2 + TP_n * V_n)/n

    Create VWAP function

    def vwap(df):
    v = df[‘volume’].values
    tp = (df[‘low’] + df[‘close’] + df[‘high’]).div(3).values
    return df.assign(vwap=(tp * v).cumsum() / v.cumsum())

    vwap(df)

Backtesting a Trading Strategy with Pandas and Python
https://www.learnpythonwithrune.org/backtesting-a-trading-strategy-with-pandas-and-python/

data['Signal'] = data['Adj Close'].rolling(5).mean() - data['Adj Close'].rolling(20).mean()
data['Position'] = (data['Signal'].apply(np.sign) + 1)/2

data.drop(['High', 'Low', 'Open', 'Volume', 'Close'], axis=1, inplace=True)
data.dropna(inplace=True)

data['Log return'] = np.log(data['Adj Close']/data['Adj Close'].shift())
data['Return'] = data['Position'].shift(1)*data['Log return']

data[['Log return', 'Return']].cumsum().apply(np.exp)

np.exp(data[['Log return', 'Return']].mean()*252)

data[['Log return', 'Return']].std()*252**.5

jupyter 无法预览

python -m pip install -I jinja2==3.0.3  

《甄嬛传》妃嫔合集
https://zhuanlan.zhihu.com/p/352962760

1.皇后2.华妃3.端妃4.敬嫔5.齐妃6.菀贵人/熹贵妃7.惠贵人8.安答应9.丽嫔10.曹贵人11.宁贵人12.瑛贵人13.欣常在14.祺嫔15.富察贵人16.夏常在17.余答应18.芝答应19.淳常在20.贞嫔21.康常在22.孙答应

An introduction to Byobu
https://simonfredsted.com/1588

Byobu advertises itself as a terminal multiplexer and a terminal window manager.

不ROOT不刷机,小米手机如何安装谷歌 GMS 三件套
https://zhuanlan.zhihu.com/p/211362120

  • Google Services Framework
  • Google play Services
  • Google Play Store

Effortless API Design
https://stoplight.io/studio

iotop常用快捷键:

  • 左右箭头:改变排序方式,默认是按IO排序。
  • r:改变排序顺序。
  • o:只显示有IO输出的进程。
  • p:进程/线程的显示方式的切换。
  • a:显示累积使用量。
  • q:退出。

Linux stress 命令
https://www.cnblogs.com/sparkdev/p/10354947.html

#消耗 CPU 资源
stress -c 4

# 消耗内存资源
stress --vm 2 --vm-bytes 300M --vm-keep

#消耗 IO 资源
stress -i 4

# 压测磁盘及 IO
stress -d 1 --hdd-bytes 10M

ulimit 命令详解
https://www.cnblogs.com/zengkefu/p/5649407.html

vi /etc/security/limits.conf
    * soft noproc 11000
    * hard noproc 11000

vi /etc/profile
    ulimit -u 10000
    ulimit -n 4096

https://unix.stackexchange.com/questions/34334/how-to-create-a-user-with-limited-ram-usage

The limits imposed by ulimit and limits.conf is per process. I definitely wasn’t clear on that point.
If you want to limit the total amount of memory a users uses (which is what you asked). You want to use cgroups.

Limit memory usage of a user
https://unix.stackexchange.com/questions/305026/limit-memory-usage-of-a-user

限制某用户每个进程的内存使用上限

  • 直接使用 ulimit 命令,作用范围是当前会话
  • 修改 /etc/profile,作用范围是所有人
  • 修改 /etc/security/limits.conf,作用范围可以是所有人,也可以指定组或人

测试

# 限制进程最大使用 2000M 内存 
$ ulimit -v 2000000

# 启动一个进程,使用 1G 内存,保持 5 秒 
$ stress --vm 1 --vm-bytes 1024M --vm-keep -t 5
stress: info: [2889506] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: info: [2889506] successful run completed in 5s

# 限制单进程最大使用 1000M 内存 
$ ulimit -v 1000000

# 启动一个进程,使用 1G(大于 1000M) 内存,预期运行失败 
$ stress --vm 1 --vm-bytes 1024M -t 5
stress: info: [2889759] dispatching hogs: 0 cpu, 0 io, 1 vm, 0 hdd
stress: FAIL: [2889760] (494) hogvm malloc failed: Cannot allocate memory
stress: FAIL: [2889759] (394) <-- worker 2889760 returned error 1
stress: WARN: [2889759] (396) now reaping child worker processes
stress: FAIL: [2889759] (451) failed run completed in 0s

# 启动 2 个进程,各使用 512M (小于 1000M) 内存,总共使用 1024 M,进程能够运行成功。
stress --vm 2 --vm-bytes 512M -t 5
stress: info: [2898454] dispatching hogs: 0 cpu, 0 io, 2 vm, 0 hdd
stress: info: [2898454] successful run completed in 5s

限制某个用户所有进程的总内存

创建一个资源限制组,限制最多使用 2 G 内存

$ cat /etc/cgconfig.conf
group memlimit2G {
    memory {
        memory.limit_in_bytes = 2000000000;
    }
}

设置 testuser 的内存只用上面定义的资源组

$ cat /etc/cgrules.conf
testuser   memory   memlimit2G/

安装和启动相关工具和服务

sudo apt install cgroup-tools
sudo cgconfigparser -l /etc/cgconfig.conf
sudo cgrulesengd

以 testuser 身份运行 2 个进程,每个进程使用 512M 内存,执行 5 秒,预期运行成功

$ sudo -u testuser stress --vm 2 --vm-bytes 512M -t 5
stress: info: [2946198] dispatching hogs: 0 cpu, 0 io, 2 vm, 0 hdd
stress: info: [2946198] successful run completed in 5s

以 testuser 身份运行 4 个进程,每个进程使用 512M 内存,执行 5 秒,预期运行失败

$ sudo -u testuser stress --vm 4 --vm-bytes 512M -t 5
stress: info: [2946363] dispatching hogs: 0 cpu, 0 io, 4 vm, 0 hdd
stress: FAIL: [2946363] (415) <-- worker 2946367 got signal 9
stress: WARN: [2946363] (417) now reaping child worker processes
stress: FAIL: [2946363] (421) kill error: No such process
stress: FAIL: [2946363] (451) failed run completed in 5s