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

todo

技术学习

  • 可以任意维度筛选,排序,分组,分栏的 TODO LIST。

理财

  • 使用前一天的开盘收盘最高最低成交价换手率波动率等作为特征,取 1-3 年的数据作为样本,以第二天的涨跌为分类标签,使用贝叶斯算法训练模型并预测第二天涨跌。
  • 把同一基金经理管理年限超过 5 年的基金,计算最近 1 年,3 年, 5 年的波动率,夏普率,年化收益,α 收益,β 收益,最大回撤,以及两两之间的相关性做成一个表格。

定期检查

  • 域名过期检查
  • 云主机过期检查
  • HTTPS 证书过期检查
  • 云主机定时备份
  • 手机定时备份
  • 电脑定时备份

idea

  • 程序员英语每日阅读

202206

解读历史波动率,发现交易机会
https://new.qq.com/rain/a/20210830A08VW100

波动率具有聚集性、均值回归、长记忆性和非对称性等特征。

  • 聚集性是指波动率具有高低波动率各自聚集的特征,即高波动率之后大概率还是高波动率,低波动率之后大概率还是低波动率,而且高波动率和低波动率聚集的时期会交替出现,呈现出的就是周期性。
  • 均值回归是指波动率没有长期上涨或者下跌的趋势,而是围绕均值上下波动。
  • 长记忆性指波动率存在较高的自相关特性,现在的波动率在很大程度上取决于其过去的波动率。
  • 波动率的非对称性主要体现在隐含波动率上,即标的价格上涨或下跌相同幅度对期权隐含波动率的影响并不相同。

说到企业估值,你怎能不知道现金流折现法?
https://baijiahao.baidu.com/s?id=1722719168861071511

一个公司的内在价值,取决于该公司未来能产生的自由现金流。

自由现金流折现法(Discounted Cash Flow ),简称 DCF。

无杠杆自由现金流/企业自由现金流

  • = EBIT-调整的所得税+折旧摊销—营运资金的增加—资本支出。
  • = 净利润+利息费用+所得税-调整的所得税+折旧摊销—营运资金的增加—资本支出。

为了防止 ssh 或 scp 时,提示是否需要确认 hosts,可以提前执行如下语句

ssh-keyscan abc.com >> ~/.ssh/known_hosts

ssh 或 scp 自动输入密码可以使用 sshpass

apt-get update
apt-get  install -y --force-yes sshpass
sshpass -p "xxxx" scp local remote 

Postgree 查看数据库,表,索引大小

查看各个库的大小

select pg_database.datname, pg_size_pretty (pg_database_size(pg_database.datname)) AS size from pg_database;

查看 public 库下所有表索引大小

select indexrelname, pg_size_pretty(pg_relation_size(relid)) from pg_stat_user_indexes where schemaname='public' order by pg_relation_size(relid) desc;

查看 public 库下所有表大小

select relname, pg_size_pretty(pg_relation_size(relid)) from pg_stat_user_tables where schemaname='public' order by pg_relation_size(relid) desc;

查看单个表大小

select pg_size_pretty(pg_relation_size('表名'));

查询所有表的大小并排序(包含索引)

SELECT table_schema || '.' || table_name AS table_full_name, pg_size_pretty(pg_total_relation_size('"'
    || table_schema || '"."' || table_name || '"')) AS size
FROM information_schema.tables
ORDER BY
pg_total_relation_size('"' || table_schema || '"."' || table_name || '"') DESC limit 20;

查询表大小按大小排序并分离data与index

SELECT
table_name,
pg_size_pretty(table_size) AS table_size,
pg_size_pretty(indexes_size) AS indexes_size,
pg_size_pretty(total_size) AS total_size
FROM (
SELECT
table_name,
pg_table_size(table_name) AS table_size,
pg_indexes_size(table_name) AS indexes_size,
pg_total_relation_size(table_name) AS total_size
FROM (
SELECT ('"' || table_schema || '"."' || table_name || '"') AS table_name
FROM information_schema.tables
) AS all_tables
ORDER BY total_size DESC
) AS pretty_sizes;

分区,挂磁盘

# 创建挂载目录
mkdir /data_ext2/

# 查看块设备,找到新硬盘
lsblk
file -s /dev/nvme2n1
    /dev/nvme2n1: data

# 分区并查看
mkfs -t xfs /dev/nvme2n1
file -s /dev/nvme2n1
    /dev/nvme2n1: SGI XFS filesystem data (blksz 4096, inosz 512, v2 dirs)
lsblk -f | grep nvme2n1
    nvme2n1     xfs                      de17daa1-9f10-4b60-adc9-2a7ed1557c89

# 挂载并查看
mount /dev/nvme2n1 /data_ext2
df -h /data_ext2

# 查看设备 id,并设置开机启动挂载
blkid
vi /etc/fstab
    UUID=7a0a651a-0000-0000-0000-717708af1dec /data_ext2  xfs  defaults 0 0

How to fix “MySQL server has gone away”, “Packets out of order” and similar MySQL connection errors
https://www.ryadel.com/en/fix-mysql-server-gone-away-packets-order-similar-mysql-related-errors/

for these errors:

MySQL server has gone away
Error reading result set's header
Error executing query
MySQL server has gone away for query
2006, MySQL server has gone away
Packets out of order. Expected X received Y. Packet size=Z
  • There’s a good chance that the server is dropping an incorrect or too large packet sent by the client. To fix that, check the max_allowed_packet variable value and set it to a very high value
  • The issue might be due to the fact that the server timed out and closed the connection. Check the wait_timeout MySQL variable value and ensure it’s large enough.
  • Additionally, if you’re getting the Packets out of order error in the PHP log, there’s an high chance that the issue is due to the fact that there’s an incompatibility between the PHP and MySQL versions you’re using.

我的一个不常访问的页面使用的如下的代码

$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, array(
    PDO::ATTR_PERSISTENT => true
));

但偶尔报下面的错误,不是经常

warning: Packets out of order. Expected 1 received 0. Packet size=145

我怀疑是我使用了 MySQL 持久连接,但这个页面不经常使用,造成这个连接长时间保持但没有任何真实请求,然后被 MySQL 单方面杀掉了,但我过了很久之后再刷新页面,PHP 尝试复用这个连接时,被 MySQL 拒绝了。

如果是一个比较活跃的站点,持久连接带来的好处可能比较明显,因为节省了很多连接建立的花时间。但一个请求量比较低的页面没有必要使用持久连接,不知道理解的对不对。

要想真正避免这个问题,我想在执行 SQL 之前要先执行个空的 MySQL ping 命令,验证 MySQL 连接是否有效,如果无效则重新连接,有效则直接使用。这个验证连接的操作可以设置一个缓存时间,比如 1 小时内不需要再次验证,以避免频繁的做无用功。


sql

TODO: MySQL窗口函数OVER()
https://blog.csdn.net/weixin_46544385/article/details/120609601

mysql 快速查看表的数据行数

set session information_schema_stats_expiry=0;
show table status like 'mytable'\G

Postgres array_to_string() and array_agg() to decouple your interface
https://pemungkah.com/postgres-array_to_string-and-array_agg-to-decouple-your-interface/

SELECT Array_to_string(Array_agg(number_of
                                 || ' '
                                 || status), ',  ') summary_status,
       Max(user_id) USER
FROM   (SELECT Count(*) number_of,
               status,
               user_id
        FROM   jobs
        GROUP  BY status,
                  user_id
        ORDER  BY user_id) AS foo
GROUP  BY user_id;

PostgreSQL:基于数组(外键)列联接2个表
http://ask.sov5.cn/q/rxkaSsHjMA

SELECT u.id, u.name,array_agg(g.name) group_names FROM users u JOIN groups g ON g.id = ANY (u.group_ids)
GROUP BY u.id, u.name;

postgree 里的换行

select 'test line 1'||E'\n'||'test line 2';

postgree 的表 a 有一个数组列 id_arr,格式类似于 [1,2,3],关联到 b 表的 id 列,我想得到 [a,b,c]

SELECT (select string_agg(b.name,',') from b where b.id = ANY(a.ids)) FROM a 

创建临时表,当你断开与数据库的连接后,临时表就会自动被销毁。 临时表只在当前连接中有效。

CREATE TEMPORARY TABLE 临时表名 AS
(
    SELECT *  FROM 旧的表名
    LIMIT 0,10000
);

MySQL 全文索引
https://blog.csdn.net/dreamyuzhou/article/details/120432893

  • 全文索引只能用于InnoDB或MyISAM表,并且只能为CHAR、VARCHAR或TEXT列创建。
  • MySQL提供了一个内置的全文ngram解析器,支持中文,日文和韩文(CJK),以及一个可安装的MeCab日文全文解析器插件。 “ngram全文解析器”和“MeCab全文解析器插件”
  • FULLTEXT索引定义可以在创建表时在CREATE TABLE语句中给出,也可以稍后使用ALTER TABLE或CREATE index添加。
  • 对于大型数据集,将数据加载到一个没有FULLTEXT索引的表中,然后在此之后创建索引,比将数据加载到一个已有FULLTEXT索引的表中要快得多。
  • 分区表不支持全文搜索

mysql的全文索引只有一种方法判断相关性,就是词频,索引并不会记录匹配的词在字符串中的位置。并且,全文索引和数据量有较大的关系,全文索引只会全部在内存中时,性能才会很好,因此当全文索引过大,不能全部读入进内存,性能就会比较差。
可以通过一下点,思考下全文索引的问题:

  • 修改一段文本中的100个单词时,需要索引100次。
  • 全文索引的长度对性能的影响也是巨大的
  • 全文索引会产生更多的碎片,需要频繁的优化(optimize table)操作
  • 内存和数据容量也是常可观,所以需要规划和参数控制这部分
  • 因为mysql复制机制是基于逻辑复制,产生的binlog很大,那就会出现主从延迟等问题。
  • 词分割(token_size)也是一个问题,单个汉字也能表达出不同的意思。
  • 查询上:如果sql中包含match against,而索引列上又正好有全文索引,那么mysql就一定会使用全文索引,如果此时还有其他索引,mysql也不会去对比那个索引性能更高。

MySQL 创建全文索引

-- 创建全文索引
CREATE FULLTEXT INDEX idx ON table_name(`columns`);

-- 创建表时自动加全文索引,临时表不支持
CREATE TABLE articles (
  id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
  title VARCHAR(200),
  body TEXT,
  FULLTEXT (title,body)
) ENGINE=InnoDB;

-- 插入测试数据
INSERT INTO articles (title,body) VALUES
('MySQL Tutorial','DBMS stands for DataBase ...'),
('How To Use MySQL Well','After you went through a ...'),
('Optimizing MySQL','In this tutorial, we show ...'),
('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
('MySQL vs. YourSQL','In the following database comparison ...'),
('MySQL Security','When configured properly, MySQL ...');

-- 简单全文搜索 
SELECT * FROM articles
WHERE MATCH (title,body)
AGAINST ('database' IN NATURAL LANGUAGE MODE);

+----+-------------------+------------------------------------------+
| id | title             | body                                     |
+----+-------------------+------------------------------------------+
|  1 | MySQL Tutorial    | DBMS stands for DataBase ...             |
|  5 | MySQL vs. YourSQL | In the following database comparison ... |
+----+-------------------+------------------------------------------+


-- 布尔搜索
SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);

+----+-----------------------+-------------------------------------+
| id | title                 | body                                |
+----+-----------------------+-------------------------------------+
|  6 | MySQL Security        | When configured properly, MySQL ... |
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...        |
|  2 | How To Use MySQL Well | After you went through a ...        |
|  3 | Optimizing MySQL      | In this tutorial, we show ...       |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ... |
+----+-----------------------+-------------------------------------+

-- 查询扩展搜索是对自然语言搜索的修改。
-- 搜索字符串用于执行自然语言搜索,然后将搜索返回的最相关行的单词添加到搜索字符串中,并再次执行搜索。
-- 查询返回第二次搜索的行.
SELECT * FROM articles
WHERE MATCH (title,body)
    AGAINST ('database' WITH QUERY EXPANSION);

+----+-----------------------+------------------------------------------+
| id | title                 | body                                     |
+----+-----------------------+------------------------------------------+
|  5 | MySQL vs. YourSQL     | In the following database comparison ... |
|  1 | MySQL Tutorial        | DBMS stands for DataBase ...             |
|  3 | Optimizing MySQL      | In this tutorial, we show ...            |
|  6 | MySQL Security        | When configured properly, MySQL ...      |
|  2 | How To Use MySQL Well | After you went through a ...             |
|  4 | 1001 MySQL Tricks     | 1. Never run mysqld as root. 2. ...      |
+----+-----------------------+------------------------------------------+

laravel

https://zhuanlan.zhihu.com/p/95558910
Laravel 一主多从配置

'mysql' => [
    'write' => [
        'host' => '192.168.1.180',
    ],
    'read' => [
        ['host' => '192.168.1.182'],
        ['host' => '192.168.1.179'],
    ],
    'driver' => 'mysql',
    'database' => 'database',
    'username' => 'root',
    'password' => '',
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix' => '',
]

https://lqwang.net/13.html

  • 使用 chunkById 或者 chunk 方法的时候不要添加自定义的排序,chunk和chunkById的区别就是chunk是单纯的通过偏移量来获取数据,chunkById进行了优化,不使用偏移量,使用 id 过滤,性能提升巨大。在数据量大的时候,性能可以差到几十倍的样子。
  • 而且使用chunk在更新的时候,也会遇到数据会被跳过的问题。
  • 同时 chunkById 在你没有传递 column 参数时,会默认添加 order by id,可能会遇到索引失效的问题。解决办法就是传递 column 参数即可。
  • 本人感觉 chunkById 不光是根据 Id 分块,而是可以根据某一字段进行分块,这个字段是可以指定的。

https://laravel.com/docs/master/broadcasting
https://learnku.com/docs/laravel/9.x/broadcasting/12223

For example, imagine your application is able to export a user’s data to a CSV file and email it to them. However, creating this CSV file takes several minutes so you choose to create and mail the CSV within a queued job. When the CSV has been created and mailed to the user, we can use event broadcasting to dispatch a App\Events\UserDataExported event that is received by our application’s JavaScript. Once the event is received, we can display a message to the user that their CSV has been emailed to them without them ever needing to refresh the page.

  • Laravel 通过 WebSocket 连接使它很容易的去「广播」您的服务端 Laravel 事件。
  • 广播 Laravel 事件允许您在服务器端 Laravel 应用程序和客户端 JavaScript 应用程序之间共享相同的事件名称和数据。
  • 广播背后的核心概念很简单:客户端连接到前端的命名频道,而您的 Laravel 应用程序将事件广播到后端的这些频道。
  • laravel-websockets 和 soketi 包为 Laravel 提供了与 Pusher 兼容的 WebSocket 服务器。 这些包允许您在没有商业 WebSocket 提供程序的情况下利用 Laravel 广播的全部功能。

算法

经典面试题:如何快速求解根号2?
https://mp.weixin.qq.com/s/ONv1k27PflPZstlv99Vfzw

如何最简单、通俗地理解LSTM?
https://www.zhihu.com/question/445411028/answer/2323876011

  • LSTM 是一种 RNN 模型
  • LSTM 是对简单循环神经网络的改进
  • LSTM 可以避免梯度消失的问题,可以有更长的记忆

大白话理解LSTM神经网络(附实例讲解)
https://blog.csdn.net/Iceberggg/article/details/124114192

长短期记忆神经网络(LSTM)是一种特殊的循环神经网络(RNN)。原始的RNN在训练中,随着训练时间的加长以及网络层数的增多,容易出现梯度爆炸或梯度消失的问题,导致无法处理较长序列数据,从而无法获取长距离数据的信息。为解决该问题,提出了它的改进方案,即LSTM神经网络。

设计思路

  • RNN 神经网络:记住所有信息,无论是有用的还是无用的。
  • LSTM 神经网络:选择一个记忆细胞,对信息有选择性地记忆。

前向传播

  • t 为时刻
  • C_{t} 为记忆细胞
  • h_{t} 为状态
  • x_{t} 为输入
  • f_{t} 为遗忘门
  • i_{t} 为更新门
  • o_{t} 为输出门

举例

  • 假设现在是期末考试周且你的脑容量有限,昨天你考完了高等数学,后天将考线性代数,你的线性代数老师也为你贴心地划好了考试重点。
  • RNN会记住所有的信息,无论是有用信息还是无用信息,即你复习了整本线性代数的书本,并将其内容与上一门高等数学的内容全部记忆了下来
  • 对于LSTM来说,你将遗忘大部分高等数学的内容,而只保留基础数学运算等通用内容,并且只复习记忆线性代数书本中老师划出的重点。
  • C_{t} X f_{t} 的会生成一系列 0-1 之间的数,如[0,1,0.7,0,0.3,1],对其赋权重后,进行选择性遗忘。
    • 遗忘大部分高等数学的知识,记忆能够用到线代考试中的基础数学运算等知识。
  • i_{t} 更新门
    • 老师所划出的重点并不会全部出现在试卷上,你可以在复习的过程中根据自己的理解,判断哪些内容可能考,哪些内容肯定不考,由此再进行筛选过滤。
  • 在 LSTM 的每个时间步里,都有一个记忆 cell,给予 LSTM 选择记忆的功能。

请问rnn(lstm)和hmm在处理序列问题上的区别和优缺点在于?
https://www.zhihu.com/question/55007302/answer/1744376871

  • 在特定问题下,参数设置正确,相关论文已经证明HMM与LSTM能达到类似的效果。
  • 但是越先进的模型,调参成本越低。
  • 在时间序列预测问题上,可能 LSTM 不需要做特别多的参数调整就优于 HMM
  • 自然语言处理上,BERT 不需要做特别多的参数调整就优于 LSTM

深度学习做股票预测靠谱吗?
https://www.zhihu.com/question/54542998/answer/2361320437

  • 我有无数的本科生从youtube上抄了一堆直接应用LSTM在股票价格上的预测,说r^2高达99%,然后我让他们用daily return做一遍,立刻不说话了。
  • 究其原因,是股票价格的时间序列非常persistent,而在take first-order difference之后,return的信噪比又过低,所以LSTM肯定没办法。
  • LSTM在经济学里适合做什么呢?适合做宏观数据,一群月度季度宏观数据放在一起train,得到的结果是非常棒的。为什么呢?因为宏观本来就有lead-lag indicators,你LSTM做的是定量上的贡献。
  • 在去掉seasonality之后如果还有很多信息,那么LSTM才会好(例如宏观数据)。
  • lstm 绝对是靠谱的。我就知道国内某头部量化2017 年到2019年用lstm做出了很好的收益。但具体做法绝对不是一般人想的那么简单。任务的目标、使用的数据、处理的特征,都不是一般人能想到的
  • 任务的目标是个很重要的问题,很多人都没考虑清楚任务的目标就上LSTM
  • 如果预测价格而不是return,线性模型都能给搞出高R^2来,把价格作为预测目标说明完全没有上道在胡做一气。不要预测价格,要预测收益率。
  • 在不讨论因子有效性的前提下讨论模型work不work没有意义。没有因子,别玩模型。
  • 混沌理论,尤其李天岩教授的研究,对股市预测有一定的帮助。所以金融领域,混沌理论应该是正确的突破方向。
  • 幻方之前的报告明确表示,小资金量只用盘口数据+LSTM是可以赚钱的,但是他们也说特征工程有trick(估计有什么自己的因子)
  • 宏观惯性大,微观在搞布朗运动
  • 不是LSTM不行,而是关键方法设计和改进需要适合数据特性,做好预处理,做好需要处理的各种多模态数据的准备…毕竟直接套用LSTM,那是肯定不行…LSTM背后应该是一类方法,而不只是调用出来的tf里的一个确定的方法
  • 特征挖得好加点非线性就能work,和lstm关系也不大
  • 单变量序列,前后变化幅度上下0.1,不平稳,硬套lstm[飙泪笑] 老师!我有个时间复杂度O(1)的好主意,和你lstm一个水平:x(t) = x(t-1)[飙泪笑] 换daily return了?老师这题我也会!x(t) = mean(x[t-n: t-1])
  • feature不行吧,对着一堆噪声再好的模型也学不到语义,而且直接上lstm也太…
  • 时序的默认假设就是有很强的关联性。单股数据内在关联实际上很弱,也就是所谓的信噪比非常低。这种情况下,越强的神经网络越容易出问题。因为噪声模式占主导,不经过特定的特征选择和滤噪,基本上只有过拟合噪声一条命。
  • 对价格建模确实精确的一无是处
  • 其实最大问题是时序非稳态,随着时间的变化时序的模式变了,机器学习还是按照过去训练集给出的模式来预测,结果肯定拉跨。说到底非稳态时序预测就是搞不定,arima不行,啥神经网络也不是万能药。
  • lstm 在高频预测方面还是有一定收益的
  • 如果是youtube上面涉及到的first difference的方法我见过大部分是只使用股票价格去套lstm。这个问题出在数据上而不是lstm这个模型本身有没有效。
  • 如果训练数据本身对结果就没有说明度模型选什么model已经不重要了……现在业内普遍的做法是训练数据用的因子是截面的基本面+量价因子(类MSCI Barra 或者Fama的做法),target用收益率或者对数收益率。
  • 如果做非线性模型除了单lstm还有CNN+LSTM或者几种stacking的做法,做RF的也有,反正这个见仁见智吧跟设备还有交易速度也有关。
    另外宏观跟微观世界也差很多……有时候tick级动量因子就很有效反而日间的时候无效,有时候正好相反。
  • 另外不同市场区别也很大,之前有段时间开盘那段趋势性很强,然后就有人做那种开盘型的momentum策略,结果最近日内波动上来了被爆锤。
  • 归根结底,海量有效的因子库还是基础,模型是5%-6%的问题(这个我随便臆测的数哈不一定对,重点还是放在因子上)。
  • 所以现在头部量化都是疯狂卷设备,招一堆因子民工进去挖因子,毕竟越同质化的因子注定策略收益越会被其他使用相同因子的同类策略压缩掉,总之是越来越卷
  • 为什么说return信噪比低呢?这不应该比close 高?对数化遮盖了很多低频信息
  • 预测return和你说的那些任务,难度和收益的差别堪比打游戏和打赢一场战争。。并且也不应该指望很高的r2,0.01就有用处了。0.1就逆天了
  • 如果把预测股票视为一个分类问题,0跌 1涨呢?
    • 方向准确率也比较难有比随机猜的50%更好的效果,而且拿方向准确率交易本身也不靠谱,就算能到75%,也有可能3天赚的钱1天直接双倍亏回来。
    • 如果真的有75%,我完全可以分散成20个仓位,取预测上涨百分比最高的前20,上涨的概率越大仓位分配重,不多贪,每天能吃1个点一年都是10倍,三年一千倍
    • 比特币分钟线搞过52%准确率的,期望收益率十万分之五每分钟
  • 做差分或者对return rate做预测或者是对01涨跌分类预测会不会work(比last day baseline好)
    • 预测收益率or Diff是最最最基本的…work与否取决于因子质量,模型没有门槛,但因子库有。
  • 模型不是越高深效果越好,而是有各自适用的范围。比如,如果linear regression都过拟合,那用ML和DL就没什么意义了。
  • 我个人的经验,日度的数据,用ML预测无卵用,加上盘口的高频数据ML倒是有可做的空间,但是还是无法满足DL对数据的质量要求。
  • 当然,如果是对策略进行优化,而不是纯以预测股价为目的,ML应该会有更多的应用空间。但总而言之DL现在做量化的应该是几乎不用的。
  • 一圈实验下来,确实觉得对策略优化是大概率的没走“邪路”。尤其是只用日频数据的alpha类策略,用ML来预测市场就像水中捞月。
  • 不论回归,分类,不管统计学习,机器学习,深度学习,都是跑的概率。可以说是对你“见过的数据”做了一次拟合实验,想找到里面的规律――概率。
  • 下围棋是归纳还是博弈?
    • 下围棋是两人之间的博弈没错,但是深度学习alphago在这里面的作用起的是归纳历史棋局的作用。围棋虽然复杂,但是规则是有限的,也是明确的,所以在大量数据和高性能计算上,深度学习通过归纳下围棋的方法能打赢人类。但是市场跟围棋不一样,市场由于有很多人参与,规则是无限的,也是不明确的,很难用一个统一的模型去寻找规律。当然有可能存在短时间某种规律一直有效的情况,所以说有些因子在某些特定环境有效。
  • 如果说机构还能构建模型,对散户来说应该是通过归纳找出某周期内胜率大于50%的操作方式,合理设置盈亏比,严格执行之。并时时统计这个周期内胜率变化,一旦变化,相应策略也要调整。市场是混沌的,预测冇意义,一切都是概率变化而已
  • 股市预测的问题本质上是一个online learning 的问题,因为股票市场上的规律是不断地在变的。这也是为什么传统机器学习方法和深度学习方法在金融市场上容易被当成笑话的原因。也因此,reinforcement learning 是显然不适合金融市场的,reinforcenment learning的反馈太慢了,所以需要大量的数据才能学到数据背后的规律。显然,在online learning场景下我们没有办法提供大量的数据。
  • 我觉得深度学习还是可以用来做投资的,而非交易。
    • 我觉得可以。最起码可以做交易员的辅助交易。因为有些隐规则是人自身没有发现的,但是机器可能会发现,一个好的高频预测模型是可以做出来的,因为短期内环境不会有大的变化,就可以预测。如果深度学习能够学习其中的隐规则,并且使用模型输出人能够理解的信息形式,就是一个很好的预测模型
  • 市场追求的不是博弈,而是共识。 同样2020年3月为例,绝对的利空,造成统一的救市共识,然后才挽救了股市。放在1927年、2000年,市场在救与不救之间徘徊不定无法达成共识,造成了灾难性后果。
  • 深度学习肯定是可以用在股票市场的,比如针对某只股票的新闻情感分析等。但是不能用来预测市场走向!!!

人工智能基础课,最优化

求解无约束优化问题最常用的方法是梯度下降法(gradient descent)。直观地说,梯度下降法就是沿着目标函数值下降最快的方向寻找最小值,就像爬山时要沿着坡度最陡的路径寻找山顶一样。在数学上,梯度的方向是目标函数导数(derivative)的反方向。

当函数的输入为向量时,目标函数的图象就变成了高维空间上的曲面,这时的梯度就是垂直于曲面等高线并指向高度增加方向的向量,也就携带了高维空间中关于方向的信息。而要让目标函数以最快的速度下降,就需要让自变量在负梯度的方向上移动。这个结论翻译成数学语言就是“多元函数沿其负梯度方向下降最快”,这也是梯度下降法的理论依据。

遗憾的是,梯度下降法无法获知关于导数的变化信息,也就不知道应该探索导数长期为负的方向。由于不具备观察目标函数的全局视角,在使用中梯度下降法就会走出一些弯路,导致收敛速度变慢。而二阶导数所包含的全局信息能够为梯度下降的方向提供指导,进而获得更优的收敛性。

如果将二阶导数引入优化过程,得到的典型方法就是牛顿法(Newton’s method)。在牛顿法中,目标函数首先被泰勒展开,写成二阶近似的形式(相比之下,梯度下降法只保留了目标函数的一阶近似)。此时再对二阶近似后的目标函数求导,并令其导数等于 0,得到的向量表示的就是下降最快的方向。相比于梯度下降法,牛顿法的收敛速度更快。

群蚁算法、遗传算法、模拟退火算法,禁忌搜索算法等通俗详解
https://blog.51cto.com/u_13682052/2981273

单只蚂蚁的行为及其简单,行为数量在10种以内,但成千上万只蚂蚁组成的蚁群却能拥有巨大的智慧,这离不开它们信息传递的方式——信息素。蚂蚁在行走过程中会释放一种称为“信息素”的物质,用来标识自己的行走路径。在寻找食物的过程中,根据信息素的浓度选择行走的方向,并最终到达食物所在的地方。信息素会随着时间的推移而逐渐挥发。在一开始的时候,由于地面上没有信息素,因此蚂蚁们的行走路径是随机的。蚂蚁们在行走的过程中会不断释放信息素,标识自己的行走路径。随着时间的推移,有若干只蚂蚁找到了食物,此时便存在若干条从洞穴到食物的路径。由于蚂蚁的行为轨迹是随机分布的,因此在单位时间内,短路径上的蚂蚁数量比长路径上的蚂蚁数量要多,从而蚂蚁留下的信息素浓度也就越高。这为后面的蚂蚁们提供了强有力的方向指引,越来越多的蚂蚁聚集到最短的路径上去。

继续考虑寻找f(x)最大值的问题,爬山算法搜索到A点时就会停止搜索,原因是A点左右的值均小于A点的值。模拟退火算法采用的解决办法是以一定的概率选择A两边的点,尽管A两边的点并不是局部最优解,这样就有一定的概率搜索到D点,从而搜索到B点,最终获得了全局最优解。上文中的一定概率来自于固体退火原理:当固体温度较高时,物质内能较大,固体内部分子运动剧烈;当温度逐渐降低时,物体内能也随之降低,分子运动趋于平稳;当固体温度降到常温时,固体内部分子运动最终平稳。根据Metropolis准则,粒子在温度T时趋于平衡的概率为e^(-ΔE/(kT)),其中E为温度T时的内能,ΔE为其改变量,k为Boltzmann常数。

TODO: numpy实现朴素贝叶斯模型(高斯分布)
https://www.jianshu.com/p/efa980944235

import numpy as np


class GaussianNB():

    def fit(self, X, y):
        """模型拟合"""
        self.y_prior = [round(sum(y == i) / len(y), 6) for i in sorted(set(y))]
        self.features_param = []

        for i in sorted(set(y)):
            pos = np.where(y == i)
            features_data = X[pos]
            features_mean = np.mean(features_data, axis=0)
            features_std = np.std(features_data, axis=0)

            param = [(round(avg, 6), round(std, 6)) for avg, std in zip(features_mean, features_std)]
            self.features_param.append(param)

    def predict(self, x):
        """模型预测"""
        result = []
        for i in range(x.shape[0]):
            bayes_prob = []

            for j in range(len(self.y_prior)):
                x_param = self.features_param[j]
                y_param = self.y_prior[j]
                xi_conditional_prob = 1

                for k in range(len(x_param)):
                    xi_conditional_prob *= self.gauss_pro(x[i][k], x_param[k][0], x_param[k][1])
                bayes_prob.append(round(y_param * xi_conditional_prob, 6))
            result.append(np.where(bayes_prob == np.max(bayes_prob))[0][0])

        return np.array(result)

    def gauss_pro(self, v, miu, sigma):
        """高斯分布概率密度计算"""
        part1 = 1 / (sigma * np.sqrt(2 * np.pi))
        part2 = np.exp(-1 * (v - miu) ** 2 / (2 * sigma ** 2))
        return round(part1 * part2, 6)


if __name__ == '__main__':
    from sklearn import datasets

    iris = datasets.load_iris()
    X = iris.data
    y = iris.target

    gnb = GaussianNB()
    gnb.fit(X, y)

    res = gnb.predict(X)
    print(res)

Neo4j

neo4j使用文档
https://www.cnblogs.com/naimao/p/13497046.html

  • 它是一个嵌入式的、基于磁盘的、具备完全的事务特性的Java持久化引擎,
  • 它将结构化数据存储在网络(从数学角度叫做图)上而不是表中。
  • 图形数据库数据模型的主要构建块是:节点、关系、属性
  • neo4j主要存储节点和关系,其中关系必须为有向关系,描述节点和关系的数据以属性的形式存储,节点和关系上都能放键值对的属性。不同类型的节点和关系通过标签Label来区别,不同标签的节点代表不同类型节点,不同标签关系代表不同类型关系

创建一个标签为Person的节点,其有属性 name 和age:

create (:Person{name:'小红',age:21});

查询一个节点:

match (m:Person{name:'小红',age:21}) return n;

删除一个节点:

match (m:Person{name:'小红',age:21}) delete n;

创建关系:

create (a:Person{name:"a"}),(b:Person{name:"b"}) with a,b create (a)-[r:Friend]->(b);

查询关系:

match (a:Person{name:"a"})-[r:Friend]->(b:Person{name:"b"}) return r;

删除关系:

match p=(a:Person{name:"a"})-[r:Friend]->(b:Person{name:"b"}) delete p;

linux

Linux–网络通信命令(给其它用户发送广播消息)
https://blog.csdn.net/qq_42119367/article/details/123427804

wall Happy New Year

http://ipcmen.com/nano

nano 是一个字符终端的文本编辑器,有点像 DOS 下的 editor 程序。它比 vi/vim 要简单得多,比较适合Linux初学者使用。

  • 移动光标:使用用方向键移动。
  • 复制一整行:Alt+6
  • 剪贴一整行:Ctrl+K
  • 粘贴:Ctrl+U
  • 如果需要复制/剪贴多行或者一行中的一部分
    • 先将光标移动到需要复制/剪贴的文本的开头
    • 按 Ctrl+6(或者 Alt+A )做标记
    • 然后移动光标到 待复制/剪贴的文本末尾。这时选定的文本会反白
    • 用 Alt+6 来复制,Ctrl+K 来剪贴。
    • 若在选择文本过程中要取消,只需要再按一次 Ctrl+6。
  • 退出: Ctrl+X: 如
    • 果你修改了文件,下面会询问你是否需要保存修改。
    • 输入Y确认保存,输入N不保存,
    • 按 Ctrl+C 取消返回。
    • 如果输入了Y,下一步会让你输入想要保存的文件名。
      • 如果不需要修改文件名直接回车就行;
      • 若想要保存成别的名字(也就是另存为)则输入新名称然后确定。
      • 这个时候也可用 Ctrl+C 来取消返回。
  • 撤销:Alt+U
  • 重做: Alt+E

Linux visudo配置详解
http://t.zoukankan.com/wutao1935-p-10045809.html

sudo的工作过程如下:

  • 当用户执行 sudo 时,系统会主动寻找 /etc/sudoers 文件,判断该用户是否有执行 sudo 的权限
  • 确认用户具有可执行 sudo 的权限后,让用户输入用户自己的密码确认
  • 若密码输入成功,则开始执行 sudo 后续的命令
  • root 执行 sudo 时不需要输入密码 (sudoers 文件中有配置 root ALL=(ALL) ALL这样一条规则)
  • 若欲切换的身份与执行者的身份相同,也不需要输入密码

visudo 使用 vi 打开 /etc/sudoers文件,但是在保存退出时,visudo 会检查内部语法,避免用户输入错误信息

# 允许 user1 用户执行任意路径下的任意命令
user1 ALL=(ALL) ALL
# 允许 user1 用户不输入该用户的密码的情况下使用所有命令
user1 ALL=(ALL) NOPASSWD: ALL
# 允许 user1 用户执行特定命令
user1 ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom

量化

从零入门量化交易系列(十二)Black-Litterman模型及python实现
https://zhuanlan.zhihu.com/p/363540266

这里还要再说一个重要的假设就是共轭分布,千万别被共轭(conjugate)这个词吓到,它几乎是整个Black-Litterman模型在形式上的核心。原因在于一个正态分布乘以另一个正态分布结果还依然是正态分布。这就是为什么模型不仅要假设\mu服从正态分布,连投资者的观点也要假设为正态分布的原因。这两个正态分布都在分子上,相乘后结果仍为正态分布,而分母上的积分为常数,并不影响新的正态分布的均值和方差。也就是说先验和后验同属于正态分布,两者共轭,因此后验分布的均值方差都可以根据公式快速得到。这也就方便我们得到后验分布的均值,也就是我们想要的期望收益率。

【量化模型】Black-Litterman模型介绍
https://zhuanlan.zhihu.com/p/25041459

Markowitz的MPT模型:给定风险水平下的预期收益最大化,也可以是其对偶命题,给定预期收益 水平下的风险最小化。

  • 缺点:
    • 假设不成立:MPT理论假设为投资者一致且理性(即投资者对预期收益、标准差和风险资产相关性具有一致预测;投资者行为遵循最优化原则,即投资者理性)。现实中显然不成立。
    • 无仓位限制:在无卖空限制条件下,MPT模型经常导致在一些资产上有很大的空头头寸,而实际上大量投资者具有卖空约束。中国市场对卖空进行限制,模型经常导致在某些资产上权重为零,而在另一些资产上权重过大,即出现资产配置过于集中的现象。
    • 参数敏感:对输入参数如预期收益率作小幅度变化,可能导致模型结果发生剧烈变化。
  • 改进:
    • 高盛的Fisher Black和Robert Litterman在研究中发现,对组合中德国债券预期报酬率做0.1%小幅修正后,竟然该类资产的投资比例由原来的10.0%提高至55.0%。
    • 做法:加入投资者自己的观点,而且有一定的置信水平。二人提出了BL模型:使用Bayes定理(条件概率),构建收益时通过一定方式对市场隐含收益率与主观预期收益的加权平均。

Black-Litterman模型是基于MPT基础上的资产配置理论。BL模型在隐含市场收益率和分析师主观预测信息的基础上,成功解决了MPT模型中假设条件不成立,参数敏感等问题。

  • BL优化后确实战胜市场均衡配置;
  • BL模型同样也存在模型上的缺陷,需要继续改进。历史数据计算出来的协方差矩阵在长期内可能不能良好刻画出短期关系,需要动态调整;分析师主观预期(看法)信心水平的设定具有很大的主观 随意性,在方法上还存在众多分歧;
  • BL模型比较符合目前国内基金投资真实市场环境,如关注分析师主观预期,存在投资仓位上下限规定等;
  • BL模型适用于行业资产配置,而一般不配置具体的投资,倾向区分大类资产;但有的地方也说可以用在个股组合中;
  • 达里奥桥水基金的全球配置更关注风险因子,而非大类。股票中的能源股和部分大宗商品息息相关,从而分配到相同的一类中。是不同于MPT和BL的资产配置理论

大奖章基金
https://baijiahao.baidu.com/s?id=1664399262080636944&wfr=spider&for=pc

  • 该基金的收费比较高,管理费为 5%,业绩分成比例为 36%。
  • 奖章基金的管理规模在 100 亿美金左右,折合人民币约 700 亿。
  • 二十年年化收益率近 70%

【矩阵分析】Condition Number
https://zhuanlan.zhihu.com/p/81053589

  • 我们在衡量某个函数敏感度与稳定性时,常使用的一种方法是求导。即观察导数[公式] 的大小。
  • 然而对于一个矩阵而言,所谓的导数似乎就不是那么显著,在此我们就介绍一个常用的指标矩阵敏感度指标:Condition Number。

TODO: 因子分析的数学基础
https://zhuanlan.zhihu.com/p/348566335

  • 1.1 方差
  • 1.2 标准差
  • 1.3 均方误差
  • 1.4 python实现
  • 1.5 协方差
  • 1.6 相关系数
  • 1.7 特征值和特征向量
  • 1.8 使用Python求解特征值和特征向量
  • 1.9逆矩阵和转置矩阵
  • 1.10 矩阵的迹和行列式

多元函数泰勒级数展开_用Python学微积分(4)—泰勒级数
https://blog.csdn.net/weixin_39906358/article/details/111639431


WaveFunctionCollapse
https://github.com/mxgmn/WaveFunctionCollapse

动态生成迷宫


shell

查看 json 压缩文件里倒数第 2 行的 id, 因为有可能是个末尾损坏的压缩包,所以跳过倒数第一条数据

zcat ./out_000000168373001.gz 2>/dev/null | tail -n2 | head -n1| jq -r '.id'

https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-source-field.html

Think before disabling the _source field
Users often disable the _source field without thinking about the consequences, and then live to regret it. If the _source field isn’t available then a number of features are not supported:

  • The update, update_by_query, and reindex APIs.
  • On the fly highlighting.
  • The ability to reindex from one Elasticsearch index to another, either to change mappings or analysis, or to upgrade an index to a new major version.
  • The ability to debug queries or aggregations by viewing the original document used at index time.
  • Potentially in the future, the ability to repair index corruption automatically.

https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-id-field.html

  • Each document has an _id that uniquely identifies it, which is indexed so that documents can be looked up either with the GET API or the ids query.
  • The _id can either be assigned at indexing time, or a unique _id can be generated by Elasticsearch.
  • This field is not configurable in the mappings.

https://www.517712.com/gupiao/94304.html

美元加息对黄金影响的三种情况:

1、美元加息利好黄金:美元加息,但货币并未成功回流流回银行系统,而企业贷款利率上涨,贷款困难,就会出现流动性危机,美元会被看空,对黄金就是利好。
2、美元加息利空黄金:美元加息,存款利率上涨,货币顺利回流银行系统,美元升值,对黄金就是利空。
3、美国加息,美元升值,但同时出现地区性动荡、石油危机等情况影响正常经济发展,对黄金有利好作用,就是美元和黄金同时上涨。

国际现货黄金是以美元来定价的,因此美元和黄金价格呈现一定的负相关关系,换句话说当美元上涨时,黄金价格大概率是下跌,而当美元下跌时,黄金价格大概率是上涨。


NGINX Proxy to wordpress website
https://stackoverflow.com/questions/38205743/nginx-proxy-to-wordpress-website

location ^~ /blog/ {
  proxy_pass http://127.0.0.1:8080/;
  proxy_set_header Host $http_host;
  proxy_set_header X-Forwarded-Host $http_host;
  proxy_set_header X-Real-IP $remote_addr;
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  proxy_set_header X-Forwarded-Proto $scheme;
}

/** set the site URL */
define('WP_HOME','http://www.example.com/blog');
define('WP_SITEURL','http://www.example.com/blog');

/** Fix to get the dashboard working with the reverse proxy.*/
$_SERVER['REQUEST_URI'] = str_replace("/wp-admin/", "/blog/wp-admin/",  $_SERVER['REQUEST_URI']);

Gutenberg breaks completely if site URL is not the same as wordpress URL
https://github.com/WordPress/gutenberg/issues/1761


反射放大攻击
https://baijiahao.baidu.com/s?id=1730701810134759899

所谓的反射放大攻击是非常常见的DDoS攻击手法,其基本原理非常简单:攻击者通过控制僵尸网络伪造靶机IP向特定的公网服务器发送请求,公网服务器收到请求后会向靶机发送更大的应答报文,从而实现攻击流量放大。

这里的公网服务器是指对外开放某些可被利用作反射放大的协议端口的服务器,比较常见的协议有DNS、NTP、SNMP、Memcached等,这些协议一般基于UDP,并且协议本身存在缺陷,没有校验来源IP的真实性,且存在应答报文远大于请求报文等特点。这种反射放大手法简单、有效,一直深受黑客喜爱,所以很长一段时间内UDP反射就是反射放大攻击的别称。

早在2018年就出现利用公网服务器开放的TCP端口进行反射攻击的手法,相比UDP反射放大攻击,此类利用TCP协议栈的反射攻击实际并无太明显的流量放大效果,因为请求的来源IP是伪造的,无法与TCP服务器完成TCP三次握手建立连接,所以无法得到应用层的应答报文。但是这种攻击利用了TCP的协议栈特性,使靶机看到攻击流量具备协议栈行为,而且成份复杂(synack、ack、rst等混合流量),导致反向挑战、协议栈行为校验等传统的TCP防护算法无法防护,大大增加了防护难度,所以这种TCP反射诞生后很快成为DDoS攻击的主流攻击手法。

放大系数可以理解为流量的放大倍数,计算方法非常简单,就是response总长度/query总长度。传统的UDP反射攻击的放大系数与具体的协议实现相关,所以放大系数是一个相对固定的值:除了Memcached反射攻击以外,其他UDP反射放大系数不超过600,而且以200以内为主。


nginx

A Guide to Caching with NGINX and NGINX Plus
https://www.nginx.com/blog/nginx-caching-guide/

docker

docker数据卷与数据卷容器以及备份与恢复
https://blog.csdn.net/m0_60360828/article/details/122641289

创建容器

docker run -it -v /opt --name test_1 centos:7 /bin/bash

    echo "123321" > /opt/1.txt

备份

docker run -it --volumes-from test_1 -v /mnt:/mnt centos:7 tar cvf /mnt/opt.tar /opt
  • --volumes-from test_1 :指定数据卷容器所在
  • -v /mnt:/mnt:共享该容器中mnt目录到主机的mnt
  • tar cvf /mnt/opt.tar /opt:这个较为绕,mnt是该容器跟主机之间共享的一个目录。所以将备份后的数据放到这个文件中,好备份之后直接导到主机。
  • 后面跟随的备份目标路径,则是该容器与数据卷容器之间的共享目录,因为要对数据卷容器进行备份,所以则是需要备份该目录

查看备份

ls /mnt/
tar xvf opt.tar
cat ./opt/1.txt

恢复

#创建数据卷容器,并且共享opt目录
docker run -it -v /opt --name test_2 nginx:1.12 /bin/bash

#创建一个容器,作用是从主机中获取文件,并且将该文件传输给数据卷容器
docker run -itd --volumes-from test_2 -v /mnt:/mnt nginx:1.12 tar xvf /mnt/opt.tar -C /opt/

cd opt/ && ls
cat ./opt/1.txt

elasticsearch

Field data typesedit
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html

Each field has a field data type, or field type. This type indicates the kind of data the field contains, such as strings or boolean values, and its intended use. For example, you can index strings to both text and keyword fields. However, text field values are analyzed for full-text search while keyword strings are left as-is for filtering and sorting.

pandas

设置时间索引

data['time_key'] = pd.to_datetime(data['time_key'])
data.set_index('time_key', inplace=True)

设置图表默认大小

from matplotlib import pyplot as plt 
plt.rcParams['figure.figsize'] = (16, 8)

两个指标各用一个坐标轴

data[['close','volume']].plot(secondary_y=['volume'])

两个指标各用一个子图

fre[['fre','cumsum']].plot(subplots=True)

分成 10 段,显示每个段的数量

data['real_vol_22'].hist(bins=10)

pandas数据可视化原来也这么厉害
https://baijiahao.baidu.com/s?id=1684407979428084767&wfr=spider&for=pc

pandas 区间间隔 pd.Interval
https://www.gairuo.com/p/pandas-interval


理财

无风险数字货币套利之三角套利
https://zhuanlan.zhihu.com/p/394421805

三角套利,是指交易者利用三种不同的数字货币的价格不匹配的过程。 通过买卖这些特定货币,交易者获得了无风险的利润。 这种失配通常只会持续几秒钟,因为有大量的交易员正在积极寻找这样的机会,因此三角套利主要是通过程序化的量化交易来完成的。

以btc、eth和usdt三种数字货币来说,而交易所存在eth/btc、eth/eos、btc/eos三个交易对,同时三个交易对之间存在价差,那么首先可以使用价值400元的eth购买对应份额的eos,而后在使用这些的eos兑换成btc,最后可以将兑换btc兑换成eth,那么最终结果就是你净赚10元,同时又由于这些交易都是瞬时完成的,也就可以近似认为是无风险套利了,其中唯一的风险就是别人比你的交易速度更快。

三角套利是利用交叉汇率定价错误进行的套利。套利使得实际交叉汇率与理论交叉汇率保持一致。在国际市场上,几乎所有的货币兑美元都有一个兑换率。两个非美国国家之间的理论汇率可以从它们与美元之间的汇率中推断出来,这种套算出来的汇率称为理论交叉汇率。在现实世界中,很少会出现根据交易商对美元汇率报价计算出的理论交叉汇率不同于交易商报出的实际交叉汇率的情况。如果差异大到足以与购买及出售货币的交易成本相比,就出现了无风险套利机会。

平稳(非平稳)时间序列
https://zhuanlan.zhihu.com/p/425684691

金融时间序列分析——对收益率序列平稳化处理
https://blog.csdn.net/m0_37876745/article/details/108994950

谈谈时间序列的平稳性
https://blog.csdn.net/TimeFuture/article/details/120690021

  • 时间序列分析中的许多预测和分析方法,如 ARMA、Granger 因果检验等,都要求输入序列是平稳的。
  • 大多数时间序列都是非平稳的,比如一些股票的收盘价数据就是非平稳的。
  • 如果时间序列包含明显的趋势和季节性,会影响算法准确预测时间序列的能力。
  • 一般可以通过差分、取对数等方法转化成平稳时间序列。
    • 一步的差分其实就是今天的价格和昨天的价格相减再除以昨天的价格:df['Close'] - df['Close'].shift(1)
    • 对原始数据取对数然后再差分:np.log(df['Close']) - np.log(df['Close'].shift(1)
  • 对转换后的数据集运行 Augmented Dicker-Fuller 测试,以确保平稳性

安装 ta-lib

sudo apt install build-essential wget -y
wget https://artiya4u.keybase.pub/TA-lib/ta-lib-0.4.0-src.tar.gz
tar -xvf ta-lib-0.4.0-src.tar.gz
cd ta-lib/
./configure --prefix=/usr
make
sudo make install

pip install TA-Lib

backtrader绘图运行出matplotlib错的原因
https://www.jianshu.com/p/2dc8a671ab7a

backtrader与matplot 3.3不兼容,要降级到3.2,运行如下命令可降级:

pip uninstall matplotlib
pip install matplotlib==3.2.2

pip uninstall pyfolio
pip install git+https://github.com/quantopian/pyfolio

Pyfolio一行代码实现专业量化回测图表
https://zhuanlan.zhihu.com/p/376954470

pyfolio 是全球最大量化网站Quantopian开发的量化“三剑客”之一,另外两个分别是alphalens(用于多因子分析)和zipline(类似backtrader的回测框架)。pyfolio非常适合用于金融投资组合性能和风险分析,包括与Zipline和alphalens结合,输出专业的量化指标和图表分析结果。

Python量化策略风险指标

不显示 warnings
import warnings
warnings.filterwarnings(‘ignore’)

PEG指标
https://baike.baidu.com/item/PEG指标/10904043

  • 背景:
    • 投资者普遍习惯于使用市盈率来评估股票的价值,但是,当遇到一些极端情况时,市盈率的可操作性就有局限,比如市场上有许多远高于股市平均市盈率水平,甚至高达上百倍市盈率的股票,此时就无法用市盈率来评估这类股票的价值。
    • 但如果将市盈率和公司业绩成长性相对比,那些超高市盈率的股票看上去就有合理性了,投资者就不会觉得风险太大了,这就是PEG估值法。
  • 定义:
    • PEG 指标(市盈率相对盈利增长比率)是用公司的市盈率除以公司的盈利增长速度。
    • 所谓 PEG,是用公司的市盈率(PE)除以公司未来 3 或 5 年的(每股收益复合增长率*100)。
    • 它由股票的未来市盈率除以每股盈余(EPS)的未来增长率预估值得出。
    • 它是在 PE 估值的基础上发展起来的,它弥补了 PE 对企业动态成长性估计的不足。
    • PE 仅仅反映了某股票当前价值,PEG 则把股票当前的价值和该股未来的成长联系了起来 。
  • 特点
    • 通常成长型股票的 PEG 都会高于 1,甚至在 2 以上,投资者愿意给予其高估值,表明这家公司未来很有可能会保持业绩的快速增长,这样的股票就容易有超出想象的市盈率估值。
    • 通常价值型股票的 PEG 都会低于 1,以反映低业绩增长的预期。当 PEG 小于 1 时,要么是市场低估了这只股票的价值,要么是市场认为其业绩成长性可能比预期的要差。
  • 使用
    • 粗略而言,PEG 值越低,股价遭低估的可能性越大。
    • 选股的时候选那些市盈率较低,同时它们的增长速度又是比较高的公司,这些公司有一个典型特点就是 PEG 会非常低。
    • PEG 始终是主导股票运行的重要因素,所以寻找并持有低 PEG 的优质股票是获利的重要手段。
    • 当然,也不能够机械的单以 PEG 论估值,还必须结合国际市场、宏观经济、国家的产业政策、行业景气、资本市场阶段热点、股市的不同区域、上市公司盈利增长的持续性以及上市公司的其他内部情况等等多种因素来综合评价。
  • 缺点
    • 须注意的是,PEG值的分子与分母均涉及对未来盈利增长的预测,出错的可能较大。
    • 计算 PEG 值所需的预估值,一般取市场平均预估(consensus estimates),即追踪公司业绩的机构收集多位分析师的预测所得到的预估平均值或中值。

详解PE与PEG估值法
https://zhuanlan.zhihu.com/p/353770859

如何评价纳西姆·塔勒布的《反脆弱》?该书都有哪些优劣之处?
https://www.zhihu.com/question/24684650/answer/1174590096

本书的核心观点是:事物的发展从来都是非线性发展,一切事物都会从波动中获得收益或遭受损失,反脆弱就是能在波动性和不确定性中带来收益。

最好应对风险的方法是“以毒攻毒”,设计一个“反脆弱结构”。这里就是反脆弱概念,让自己经常暴露在风险中,提高自己生活的“波动性”,利用“波动性”平衡风险,并伺机利用风险获利。

通过非线性理论让我们知道,机遇某种程度比能力更重要,不能指望人生是线性发展,也并非“一分耕耘一分收获”,能力提高就能升职加薪。现实中,确定性事件和不确定性事件至少同样多。为了实现收入指数性增长而非线性增长,必须寻找新的增长点。

https://baijiahao.baidu.com/s?id=1732327796243580868&wfr=spider&for=pc

  • 书中提出的应对不确定性的策略是杠铃策略——极端保守+极端投机的策略。其核心思想是为了避开中间地带,首要的是降低不利因素,而不是增加有利因素。
  • 对于脆弱的系统而言,其他任何“增加效率、增加成功”的行为在“实现生存”这一需求面前都是不重要的。因此极端保守的策略显得如此重要。
  • 同时,为了获得收益,又需要搭配极端投机策略。在投资中就体现为“现金+投机资产”或股票投资中的“高确定性标的+高投机性标的”的组合。
  • 总结一下,反脆弱的杠铃策略在投资中的实践就是:先活下来,不要亏钱,再寻求收益。
  • 脆弱的系统往往在大多数时候给予人们较好的体验,但在不确定性来临时不堪一击,其核心问题是不确定性来临时无法生存。

https://baijiahao.baidu.com/s?id=1698275248230462135&wfr=spider&for=pc

  • 脆弱的事物依赖稳定环境,比如一个没有任何保护的股票多头策略,一旦市场大幅下跌将很可能会损失惨重。
  • 强韧的事物不太依赖环境,环境怎么变它都不太会变。但是强韧不等于反脆弱,因为它无法从不确定性中获益。
  • 反脆弱不是坚强,而是越挫越勇。外界环境越波动、随机、混乱越不会受伤,反而利用波动环境茁壮成长。就像人类的免疫系统,受到的冲击越多越坚强。
  • 90%的现金和10%的期权就是一个比较典型的杠铃策略。一侧是极端的风险厌恶,一侧是极端的风险偏好,不走中间道路。当然,风险端的投资也要判断尽量有很高胜算才能参与,不能把期权当成赌大小的骰子。

钱:7步创造终身收入 笔记
https://book.douban.com/review/10111467/

重新认识风险

  • 传统观点是收益和风险成长比,其实未然。
  • 投资大师寻找风险小收益大的投资机会。
  • 高风险并不一定都带来高收益,高收益也不一定都要高风险。
  • 结构化票据、市场联动大额存单、固定指数年金等都是低风险高收益的投资对象。
  • 投资还有运气成分,完全相同的策略,如果开始的年份不同,可能后面结果完全不同。

量化理财目标: 量化实现目标所需的财富水平,设定个人的理财目标:

  • 财务安全:解决住房、水电、吃饭、交通、保险等问题
  • 财务活力:财务安全 + 着装、娱乐、美食等额外需求
  • 财务独立:现有生活水平
  • 财务自由:相对有品质的生活
  • 财务绝对自由:非常有品质的生活

采取行动

  • 开源
    • 通过提升技能,增加收入。
    • 通过创业创新,增加收入。
  • 节流
    • 改变生活方式以减少开支。
    • 压缩不必要的,或者低效的开支。
    • 提前偿还部分房贷本金,从而减少利息支出。
    • 为了压缩开支,减少税赋,搬家也是值得的。
  • 储蓄
    • 建立储蓄账户、养老账户。
    • 拿出收入的固定比例,自动存入账户,建立「财务自由投资基金」。

达利欧组合

  1. 达利欧在哈里·马科维茨(现代投资组合理论之父)的基础上创立了全天候投资策略。

  2. 达利欧总结出 4 种不同的经济环境(经济季节),匹配四种不同的投资组合。

  3. 达利欧全天候投资策略拥有高收益、高安全、低波动的特点。

  4. 简化版的达利欧组合包括:

    • 长期国债:40%
    • 股票:30%
    • 中期国债:15%
    • 黄金:7.5%
    • 大宗商品:7.5%
  5. 净利润: 净利润是一个企业经营的最终成果,净利润多,企业的经营效果好。

    • 第 1 步:计算销售净额,也就是营业收入,是指销售总额减销货退回与折让,以及销售税金后的余额;
    • 第 2 步:计算销售毛利,即销售净额减销售成本后的余额;
    • 第 3 步:计算销售利润,即销售毛利减销售费用、管理费用、财务费用等期间费用后的余额;
    • 第 4 步:计算营业利润,即销售利润加上其他业务利润后的余额;
    • 第 5 步:计算利润总额,即营业利润加营业外收支后的余额;
    • 第 6 步:计算所得税后的净利润,即利润总额减应计所得税(支出)后的余额。
  6. 归母净利润:归属于母公司所有者的净利润才是投资人真正要关心的数字,它是由净利润扣除掉 “少数股东损益”得到。

    • 假设:甲上市公司旗下只有一家子公司 A,并且持其 70% 的股份。
    • 如果 2017 年,A 公司的净利润是 1 亿,且甲和 A 之间没有任何关联关系。
    • 上市公司在制定合并利润表时,在净利润科目中,增加不是 7000万 而是 1 亿。
    • 但真正属于上市公司股东,也就是所有股民的净利润要把另外 3000 万扣除掉。
    • 持有 A 公司 30% 股份的那些股东就被称之为少数股东,而这个 3000 万就叫作“少数股东权益”。
  7. 扣非归母净利润:“归母净利润” 减去“非经常性损益”,即扣掉公司正常经营损益之外的一次性或者偶发性损失

    • 处置长期股权投资、固定资产、在建工程、无形资产、其他长期资产产生的损益;
    • 越权审批或无正式批准文件的税收返还、减免;
    • 各种形式的政府补贴;
    • 因不可抗力因素,如遭受自然灾害而计提的各项资产减值准备;

链接:https://wenku.baidu.com/view/02399cd5cbd376eeaeaad1f34693daef5ef71365.html

利润概念:

  • 毛利润 = 主营业务净收入-主营业务支出-主营业务税金及附加
  • 利润总额 = 主营业务净收入-主营业务支出-主营业务税金及附加+其他业务利润-营业费用-管理费用-财务费用+投资收益+营业外收入-营业务支出
  • 净利润 = 利润总额-所得税
  • 息税前利润 = 利润总额+利息支出
  • 税前利润 = 利润总额
  • 税后利润 = 净利润
  • 归母净利润 = 净利润 - 少数股东损益(母公司未持有子公司股权部分的收益)
  • 扣非归母净利润 = 归母净利润 - 非经常性损益(公司正常经营损益之外的一次性或者偶发性损失)

息税前利润通俗地说就是不扣除利息也不扣除所得税的利润, 顾名思义,是指不支付利息和所得税之前的利润.

毛利率高:说明行业好,业务模式好,竞争不激烈,有钱赚。
毛利率低:说明是夕阳行业,没钱赚,或者竞争太大,打价格战。
净利率高:说明管理水平高,成本和费用控制的好。
净利率低:说明运营效率低,管理水平差,公司不行。
俩都高:说明行业好,公司牛。

这样理解的对不?

12种底部形态特征
https://www.zhihu.com/question/280125504/answer/2228221734

钱:7步创造终身收入
https://book.douban.com/subject/27667390/

7步创造终身收入:

  1. 多存钱 (花小钱,存大钱)
  2. 少上当(只投正路,不被骗钱)
  3. 做规划(这辈子目标要赚到多少钱,需要多久,算下来年化收益目标是多少)
  4. 做资产配置(三个水桶:一 安全安心水桶 只买固定收益,本金安全 二 风险成长水桶 做股票投资房地产投资 三 梦想水桶 追逐梦想)
  5. 稳收入(强烈推荐保险年金)
  6. 学大师(巴菲特达利欧邓普顿等)
  7. 大财富(前面6步都只是小财富,人最大的财富就是健康,活的更爽和更久最重要,最带来幸福感的不是得到,而是付出和给予。不是物质而是激情,不是过去而是未来。

分享下《钱》的完整笔记
https://book.douban.com/review/10111467/


mysql

部署MySQL延迟从库的几个好处
https://blog.51cto.com/imysql/3170546
https://dev.mysql.com/doc/refman/8.0/en/replication-delayed.html

MySQL延迟从库的好处主要有几点:

  • 误删除时,能更快恢复数据。 有时候手抖了,把线上数据给误删除了,或者误删除库、表、其他对象,或不加WHERE条件的更新、删除,都可以让延迟从库在误操作前的时间点停下,然后进行恢复。
  • 把延迟从库作为专用的备份节点。虽然有一定的延迟,但并不影响利用该节点作为备份角色,也不影响生产节点数据库库。
  • 还可以把延迟从库当做一些问题、案例研究的对象。个别时候,可能有些binlog event在普通从库上会有问题(例如早期版本中无主键会导致从库更新非常慢的经典问题),这时就有时间在延迟从库上慢慢琢磨研究了。

php

How do I create a copy of an object in PHP?
https://stackoverflow.com/questions/185934/how-do-i-create-a-copy-of-an-object-in-php

$objectB = clone $objectA;


linux

rc.local

printf '%s\n' '[Install]' 'WantedBy=multi-user.target' 'Alias=rc-local.service' | sudo tee -a /usr/lib/systemd/system/rc-local.service

echo "
[Install]
WantedBy=multi-user.target
Alias=rc-local.service
" >> /usr/lib/systemd/system/rc-local.service

tail /usr/lib/systemd/system/rc-local.service
echo '#!/bin/bash' > /etc/rc.local
chmod +x /etc/rc.local
systemctl enable rc-local
systemctl start rc-local
systemctl status rc-local

iptables

iptables -A INPUT  -i eth0 -p tcp -s 140.143.1.1--dport 8080 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 8080 -j DROP
iptables -L -n
iptables-save >/etc/iptables-script
cat /etc/iptables-script
iptables-restore </etc/iptables-script
echo '/sbin/iptables-restore </etc/iptables-script' >>/etc/rc.local

linux命令:iptables、modprobe装载模块、网络防火墙服务
https://blog.51cto.com/woyaoxuelinux/1906316

  • iptables 的前身叫ipfirewall (内核1.x时代),这是一个作者从freeBSD上移植过来的,能够工作在内核当中的,对数据包进行检测的一款简易访问控制工具。但是ipfirewall工作功能极其有限(它需要将所有的规则都放进内核当中,这样规则才能够运行起来,而放进内核,这个做法一般是极其困难的)。
  • 当内核发展到2.x系列的时候,软件更名为 ipchains,它可以定义多条规则,将他们串起来,共同发挥作用,
  • 而现在,它叫做iptables,可以将规则组成一个列表,实现绝对详细的访问控制功能。
  • 他们都是工作在用户空间中,定义规则的工具,本身并不算是防火墙。
  • 而放入内核的地方必须要是特定的位置,必须是 tcp/ip 的协议栈经过的地方,叫做 netfilter.(网络过滤器)

postgree

PostgreSQL 生成随机数字、字符串、日期、验证码以及 UUID
https://blog.csdn.net/horses/article/details/109215148

生成 0 到 1 之间的随机数

SELECT random();

任意两个数字之间的随机数

low + RANDOM() * (high - low)

elasticsearch

Elasticsearch性能调优之磁盘读写性能优化
https://blog.csdn.net/lm324114/article/details/105029393/

  • 禁用不需要的功能
    • 聚合:doc values
    • 搜索:倒排索引,index
    • 评分:norms
    • 近似匹配:index_options(freqs)
  • 不要用默认的动态 string 类型映射
    • 默认的动态 string 类型映射会将 string 类型的 field 同时映射为 text 类型以及 keyword 类型,这会浪费磁盘空间,因为我们不一定两种都需要。
  • 禁止_all field:
    • _all field会将document中所有field的值都合并在一起进行索引,很耗费空空间,如果不需要一次性对所有的field都进行搜索,那么最好禁用_all field。
  • 使用 best_compression
    • _source field 和其他 field 都很耗费磁盘空间,最好是对其使用 best_compression 进行压缩。
  • 用最小的最合适的数字类型
    • es 支持 4 种数字类型,byte,short,integer,long。如果最小的类型就合适,那么就用最小的类型。

如果我们有一个叫做 foo 的数字类型 field,我们要对这个字段运行 histograms aggr 聚合操作,但是可能我们并不需要对这个字段进行搜索,那么就可以禁止为这个字段生成倒排索引,只需要 doc value 正排索引即可。

"foo": {
    "type": "integer",
    "index": false
}

text 类型的 field 会存储 norm 值,用来计算 doc 的相关度分数,如果我们需要对一个 text field 进行搜索,但是不关心这个 field的分数,那么可以禁用 norm 值。

"foo": {
    "type": "text",
    "norms": false
}

text field 还会存储出现频率以及位置,出现频率也是用来计算相关度分数的,位置是用来进行 phrase query 这种近似匹配操作的,如果我们不需要执行 phrase query 近似匹配,那么可以禁用位置这个属性:

"foo": {
    "type": "text",
    "index_options": "freqs"
}

如果我们不关心相关度频分,我们可以配置 es 仅仅为每个 term 索引对应的 document,我们可以对这个 field 进行搜索,但是 phrase query 这种近似匹配会报错,而且相关度评分会不准确。

"foo": {
    "type": "text",
    "norms": false,
    "index_options": "freqs"
}

基金知识整理

真的是,跌的越多就涨的越好吗?

https://mp.weixin.qq.com/s/aBYGwKIN9mJEUfTF1M1hJw

在熊市期间回撤控制能力强的基金,后面也涨的更好,而熊市期间回撤幅度最大,后市仍然是表现最差的那部分基金,并没有表现出蹲得越深,跳得越高的特征。


基金规模会影响反弹收益吗

规模较小的基金在熊市阶段控制回撤能力方面略有优势,这可能得益于小规模基金具备更灵活的操作的条件,而规模过大的基金则显得尾大不掉,尤其是在遭遇长时间熊市环境,大规模基金在回撤控制方面整体不如规模较小基金;

不论是熊市底部以来的绝对收益还是相对性价比指标来看,50亿以下基金整体表现都更优,尤其是2-10亿与10-50亿两个规模区间的基金表现最为优异,适中偏低规模的基金可能更适合作为底部布局的选项。


什么类型的基金更适合底部布局?

整体而言,指增基金在两轮熊市底部以来的行情中表现都是比较优秀的,是一款性价比较优的布局工具。


我们认为一个比较适合当下进行底部布局的基金或许具有以下组合特征:

适中的规模(2-50亿)+ 最低回撤的一批基金 + 指增基金

中国互联网

中庚基金的丘栋荣在最近的一次直播中提到了互联网行业的机会,他说现在中国互联网行业满足了他投资体系中三个重要的标准:低风险、低估值、高成长性。

跟踪中国互联网行业的被动指数主要有三个:中国互联网30、中国互联网50、恒生科技。

二者最大的区别就是成分股的权重不同,中国互联网50指数更侧重于阿里和腾讯两家巨头企业,两家合计占到了53%的权重。而中国互联网30指数就更加的均衡一些,阿里和腾讯的占比在31%左右,其他的几家互联网公司就获得了更多的占比,比如京东、网易、百度等等。

恒生科技不同于上面的两个指数,恒生科技只有港股,并且也不只有互联网行业,还包括其它在港股市场上市的高科技公司,覆盖的行业更广泛一些。

在具体的投资方式上,目前比较推荐大家采取“底仓+定投”的方式。对于风险承受能力偏低的投资者们,底仓可以选择20%-30%左右,就是如果打算在互联网行业总共投入1万元的话,底仓建立应该用2000至3000元左右,然后再坚持定投。对于风险承受能力较高的投资者,底仓可以选择30%-50%左右。


沪深 300 最大回撤

认清楚市场的本质并摆正心态是长期投资中非常重要的一环,在市场大跌的时候不慌乱,帮助我们拿得住牛基。如果能在克服了自己心魔的情况下,再勇敢的迈出一步,在市场下跌很深的情况下选择加仓,那么最后获取的收益也就更高。

长期来看,伴随着市场每一次深度回调的,就是一次又一次猛烈的上涨。其中,反弹幅度最大的一次是2012年12月4日到2015年6月12日,偏股混合型基金指数累计上涨182.39%,区间年化收益达52.92%。

买在半山腰怎么办?

在自己拥有充裕的可投资资金的情况下,可以选择加仓。还是要根据自己的风险承受能力和仓位管理来做是否加仓的决定,投资过程尽可能的平滑舒适才是最重要的。

我们其实活在一个“运动中平衡”的世界,没有只涨不跌的市场,也没有只跌不涨的市场。投资过程中,最重要的是认清市场和波动的本质,让自己保持一个较为积极的心态,尽可能的摒弃一蹴而就和精确抄底的思维。

我们总说长期投资这里好那里好,其实不是我们多么热衷于放弃资金的流动性,买在一个资产里很多年不动。而是大多数情况下,只有长期投资才能收获更高的回报。长期投资不是目的,而是手段。


基金止盈止损

https://mp.weixin.qq.com/s/PoAdTpH2lscjjVG1KlXA_g

一般主动管理基金,只要基金本身没问题,就建议长期持有,因为长期看净值会持续向上。

高位止盈的方法:

  1. 根据股债利差做大的择时,当股票性价比很低的时候卖出,性价比很高的时候买入。
  2. 估值法。低估(估值百分位低于20%)买入,高估(估值百分位高于80%)卖出。行业基金参考对应行业指数的估值,均衡型基金可以参考大盘指数的估值,或者基金主要布局行业的估值。
  3. 目标收益法。偏股基金的长期年化回报是15%左右,其实想想,我们每年能获得15%的收益已经很不错了,所以在投资的时候也可以保持一份理性和克制,给自己设定一个目标,达到年化15%就收手。在定投的情况下,不能说,我才投了两个月达到15%的回报就卖出,这时你的筹码还太少,止盈没有意义,至少要定投了半年后再考虑止盈的事。
  4. 最大回撤法止盈。这个是目标收益法的升级版,如果市场很好,确实很难做到赚15%就撤,那可以考虑继续持有,但一旦出现回撤就该卖出。比如,赚15%的时候先不卖,如果净值继续上涨,赚20%之后出现回撤,那么可以考虑回撤3%卖出。卖出时也可以灵活采用一次性卖出或者分批卖出。

这四种方法都比较好操作,其他还有一些方法,比如利用均线偏离度等技术指标判进行择时,通过投资者参与热度判断市场位置等,操作起来有些难度,就不多介绍了。

低位止损就是割肉,割在地板上就太亏了,所以一般投资止盈不止损。但以下几种情况要考虑止损。

  1. 基金基本面变差。比如,基金规模暴涨后,基金经理的投资策略、风格发生漂移,业绩变差。或者债券基金经理踩雷,净值出现暴跌等。
  2. 基金经理更换。倒不是说一经更换就立马换,还是要先观察一下,至少一个季度吧,看看接任基金经理的风格、业绩,同时了解一下ta的过往经验,如果与自己想要的风格和目标不符,就要考虑更换了。
  3. 买了不符合自己风险承受能力的基金。如果基金的波动和亏损情况让自己焦虑了,不能很好的生活了,那这项投资不要也罢。
  4. 基金清盘。当基金发布了清盘公告,不论赚钱还是亏钱,都应该及时卖出。

202205

GTP-3算法是一种“暴力美学”的胜利: https://blog.csdn.net/mujie2015/article/details/115472443

李志飞把 GPT-3 形容为“一位科科都是高分的全才”。更让人激动的是,这么一个优秀的学生在学习过程中居然是无监督、完全自主驱动的,也就是学习过程它不需要人们提供有答案的练习题来复习测验(微调模型),只要给他无限多的文本序列,就能自动从文本里学到各种知识。

GPT-3 几乎是把整个互联网的浩瀚内容全部读完了。它总共阅读了大约 5000 亿词,模型大概有 1750 亿参数。系统有上万个 CPU/GPU 在 24 小时不间断地“阅读”任何领域的信息,半个月即可读完整个互联网的内容。猛灌数据量,是这个 AI 模型的“暴力”所在。

这个 GPT-3 这么神奇,他都能干什么?他其实可以做很多事情。比如他可以写作文,你给他开一个头,然后他就可以把整个文章写出来。而且他写出的文章句子非常通顺,更关键的是他段落之间逻辑也非常自洽。

网上有人把 GPT-3 写出来的文章和人类写出的文章给另外一个人判断,到底哪些机器写的,哪些是人类写的,其实人已经很难分出来了,所以他基本上可以以假乱真。


Gitlab Handbook
https://about.gitlab.com/handbook/


最近一周的数据

WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)  AND created_at <=  CURDATE()

statsd

https://github.com/statsd/statsd/blob/master/docs/metric_types.md

statsd 的 Timing mertic 不错,能自动统计周期内数据的分位值,均值,累积,标准差等。

glork:320|ms|@0.1

The glork took 320ms to complete this time. StatsD figures out percentiles, average (mean), standard deviation, sum, lower and upper bounds for the flush interval.

https://blog.csdn.net/liuxiao723846/article/details/109036280

percentThreshold

对于timer数据,除了正常的统计之外还会计算一个百分比的数据(过滤掉峰值数据),默认是90%。可以通过percentThreshold修改这个值或配置多个值。例如在config.js中配置:

//分别计算50%和80%的相关值
percentThreshold: [50, 80]

对于百分数相关的数据需要解释一下。以90为例,statsd会把一个flush期间上报的数据,去掉10%的峰值,即按大小取cnt*90%(四舍五入)个值来计算百分值。假如10s内上报以下10个值:

1,3,5,7,13,9,11,2,4,8

则只取10*90%=9个值,则去掉13。百分值即按剩下的9个值来计算。

$KEY.mean_90   // (1+3+5+7+9+2+11+4+8)/9
$KEY.upper_90  // 11
$KEY.lower_90  // 1

注:没有p99等指标。


分析过程:我们调取了 2021 年全年,好买基金 APP 上全部用户自建基金组合的收益表现情况与公募 FOF 的收益情况进行比较发现:

  • 胜率方面: 2021 年实现正收益的自建基金组合占比为 50.9%,同期 95.83% 的 FOF 基金在 2021 年实现了正收益;
  • 盈利能力方面:正收益的自建基金组合中,超 9 成收益集 中在 5% 以内,收益超过 5% 的自建组合占比仅为 3.66%; 同期,有 49.31% 的 FOF 基金收益在 5% 以内,有 45.83% 的FOF基金实现了 5% 以上的收益。

大家怎么看公墓FOF和现在流行的投顾服务,感觉比自己瞎买基金靠谱很多呀,专业的事让专业的人做,选股,择时,仓位管理,止盈止损,再平衡,都不需要自己操心。


一个类 Handler 有 3 个子类 AHandler, BHandler, CHandler 都有个 handle 方法。本来好好的,但突然 AHandler 支持批量操作了,有了一个 handleMany 方法。

下面哪个方案更好一些?

方案 A:

Class Handler                                  方案 B:
    abstract def handleMany(items)
                                                   Class Handler
Class AHandler extend Handler                          abstract handleMany(items): void
    def handleMany(self, items):                       abstract handle(item): void
        for item in items:                             abstract supportMany(): bool
            self.handle(item)
                                                   def main():
    def handle(item)                                   items = getItems()
        # call one by one api                          handler = getHandler()
                                                       if handler.supportMany():
Class BHandler extend Handler                              handler.handleMany(items)
    def handleMany(items):                             else:
        # call bulk api                                    for item in items:
                                                               handler.handle(item)
def main():
    items = getItems();
    handler = getHandler();
    handler.handleMany(items)

在线预览 office 文件, ppt, word, excel

git clone  https://gitee.com/kekingcn/file-online-preview.git
cd file-online-preview
mvn clean package -DskipTests -Prelease
docker build -t keking/kkfileview .
# 修改样式
https://gitee.com/kekingcn/file-online-preview/blob/master/server/src/main/resources/web/ppt.ftl

docker run -it -p 0.0.0.0:8012:8012 keking/kkfileview

Reddit算法分析 https://blog.csdn.net/yzllz001/article/details/54969248

这种算法的一个问题是,对于那些有争议的文章(赞成票和反对票非常接近),它们不可能排到前列。假定同一时间有两个帖子发表,文章A有1张赞成票(发帖人投的)、0张反对票,文章B有1000张赞成票、1000张反对票,那么A的排名会高于B,这显然不合理。

结论就是,Reddit的排名,基本上由发帖时间决定,超级受欢迎的文章会排在最前面,一般性受欢迎的文章、有争议的文章都不会很靠前。这决定了Reddit是一个符合大众口味的社区,不是一个很激进、可以展示少数派想法的地方。


Snowflake 雪花算法 https://zhuanlan.zhihu.com/p/142123673

分布式系统中ID生成方案,比较简单的是UUID(Universally Unique Identifier,通用唯一识别码),但是其存在两个明显的弊端:

  • 一、UUID是128位的,长度过长;
  • 二、UUID是完全随机的,无法生成递增有序的UUID。

Snowflake 雪花算法,由Twitter提出并开源,可在分布式环境下用于生成唯一ID的算法。该算法生成的是一个64位的ID,故在Java下正好可以通过8字节的long类型存放。

Snowflake 雪花算法生成的ID不是随机的,而是按时间顺序升序排列的;且可以保证在分布式高并发环境下生成的ID不会发生重复


How can I get past a “Repository is not signed…” message when attempting to upgrade Kali Linux from a mounted disk image?
https://superuser.com/questions/1331936/how-can-i-get-past-a-repository-is-not-signed-message-when-attempting-to-upgr

apt-get install 报错

apt-get update --allow-unauthenticated
apt-get update --allow-insecure-repositories

deb [trusted=yes] file:/media/cdrom0 kali-rolling main contrib non-free

彻底弄懂Redis的内存淘汰策略 https://zhuanlan.zhihu.com/p/105587132

Redis中的内存淘汰策略和过期删除策略 https://www.cnblogs.com/xiaowangbangzhu/p/16159367.html

有人往 redis 里放了大量的内容,还设置了永久不过期,需要设置内存淘汰策略,永久 key 也清理。

Redis中共有下面八种内存淘汰策略:

  • volatile-lru:设置了过期时间的key使用LRU算法淘汰;
  • allkeys-lru:所有key使用LRU算法淘汰;
  • volatile-lfu:设置了过期时间的key使用LFU算法淘汰;
  • allkeys-lfu:所有key使用LFU算法淘汰;
  • volatile-random:设置了过期时间的key使用随机淘汰;
  • allkeys-random:所有key使用随机淘汰;
  • volatile-ttl:设置了过期时间的key根据过期时间淘汰,越早过期越早淘汰;
  • noeviction:默认策略,当内存达到设置的最大值时,所有申请内存的操作都会报错(如set,lpush等),只读操作如get命令可以正常执行;

https://github.com/hexojs/hexo-renderer-markdown-it

hexo 默认的 markdown 解析器,不支持标题自动加锚点,可以用这个插件来解决。

$ npm un hexo-renderer-marked --save
$ npm i hexo-renderer-markdown-it --save

配置如下, 要启用 permalink ,在标题左边会加一个链接,分享这个链接,别人打开后可以直接定位到具体的位置。 另外 level: 2 表示二级标题才会生成链接,一级标题不会。

markdown:
  preset: 'default'
  render:
    html: true
    xhtmlOut: false
    langPrefix: 'language-'
    breaks: true
    linkify: true
    typographer: true
    quotes: '“”‘’'
  enable_rules:
  disable_rules:
  plugins:
  anchors:
    level: 2
    collisionSuffix: ''
    permalink: true 
    permalinkClass: 'header-anchor'
    permalinkSide: 'left'
    permalinkSymbol: '¶'
    case: 0
    separator: '-'

CloudWatch Logs Insights query syntax
https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_QuerySyntax.html

cloudwatch 查询语法中的几个常用指标聚合函数

  • avg(fieldName: NumericLogField): The average of the values in the specified field.
  • count_distinct(fieldName: LogField): Returns the number of unique values for the field. If the field has very high cardinality (contains many unique values), the value returned by count_distinct is just an approximation.
  • pct(fieldName: LogFieldValue, percent: number): A percentile indicates the relative standing of a value in a dataset. For example, pct(@duration, 95) returns the @duration value at which 95 percent of the values of @duration are lower than this value, and 5 percent are higher than this value.
  • stddev(fieldName: NumericLogField): The standard deviation of the values in the specified field.

查看 mysql 的数据目录

mysql> show variables like '%datadir%';
+---------------+---------------------------+
| Variable_name | Value                     |
+---------------+---------------------------+
| datadir       | /data_xxx/mysql_data_dir/ |
+---------------+---------------------------+
1 row in set (0.00 sec)

自建博客图床
https://blog.csdn.net/dysonya/article/details/123569457

PicGo
https://github.com/Molunerfinn/PicGo/releases
https://picgo.github.io/PicGo-Doc/zh/guide/config.html

可以用阿里云 OSS 或 腾讯云 COS 做存储。配置腾讯云 COS 后,如果提示下面的错误,可尝试切换下 API 的版本,默认是 V5,切换到 V4 就能解决。

StatusCodeError: 403 - "You do not have permission to get URL 'xxx' from this server."

有一点不太好的地方就是 PicGo 帮助文档里写的是使用全局的 SecreId 和 SccreKey,权限上给的有点大,应该新建一个 CAM 子账户,设置只能访问某个对象存储的桶,并生成一对密钥访问 API 更安全一些。

测试一张图片


word count

mysql 里如何统计一个字符串里某个字符出现的次数呢?
https://bookofzeus.com/articles/mysql/count-the-number-of-occurrences-of-a-char-in-mysql/

mysql> select `id`, `url`, LENGTH(`url`) - LENGTH(REPLACE(`url`, '/', '')) as `number` from `url`;
+----+-------------------------------+--------+
| id | url                           | number |
+----+-------------------------------+--------+
|  1 | http://www.thesunrisepost.com |      2 |
+----+-------------------------------+--------+

统计一个文本里单词个数

mysql> set @text=' aa bbb  cccc   ddddd ';select length(REGEXP_REPLACE(TRIM(@text), ' +', ' '))-length(REPLACE(REGEXP_REPLACE(TRIM(@text), ' +', ' '),' ','')) +1 word_count;
Query OK, 0 rows affected (0.00 sec)

+------------+
| word_count |
+------------+
|          4 |
+------------+
1 row in set (0.00 sec)

mysql regex replace

How to do a regular expression replace in MySQL?
https://stackoverflow.com/questions/986826/how-to-do-a-regular-expression-replace-in-mysql

# for mariadb
SELECT REGEXP_REPLACE("stackoverflow", "(stack)(over)(flow)", '\\2 - \\1 - \\3')
over - stack - flow

# for mysql 8.0
mysql> SELECT REGEXP_REPLACE("stackoverflow", "(stack)(over)(flow)", '$2 - $1 - $3');
+------------------------------------------------------------------------+
| REGEXP_REPLACE("stackoverflow", "(stack)(over)(flow)", '$2 - $1 - $3') |
+------------------------------------------------------------------------+
| over - stack - flow                                                    |
+------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1');
+--------------------------------------------+
| IF('ABC1' REGEXP 'ABC[0-9]$','ABC','ABC1') |
+--------------------------------------------+
| ABC                                        |
+--------------------------------------------+

mysqldump -u user -p database table > dump.sql
find /path/to/dump.sql -type f -exec sed -i 's/old_string/new_string/g' {} \;
mysqlimport -u user -p database table < dump.sql

你可能在一个人面前,一文不值;却在另一个人面前,是无价之宝。做你自己,爱你的人,自然爱你。谨记自己的价值所在,这就是,人活着的道理。

—— 杨绛

投资中不要去追求完美,追求完美的人就算告诉你什么时候买卖你都会失败,因为你总想买在最低卖在最高,结果导致你不是踏空就是坐过山车!退而求其次方为可把握的正道。买在次低位,卖在次高位,我很满足,方可持续。

别人本质上是没办法让你自卑的。让你自卑的是你的想法或内在的自我攻击。

“少研究别人,多提升自己,不是成功来的慢,是你努力的不够狠,努力只能及格,拼命才能优秀。”

其实,大多数餐饮店,顾客根本不在意你装修啥样,弄那么多花样,根本不加分。吃的东西弄干净一点,桌子椅子方便就行,又不是当皇上来了,弄个死沉死沉的太师椅干啥啊?傻乎乎的。

人和人之间最大的差距,不是智商的差距,而是目标清晰度的差距。如果整天不知道自己想要什么,五迷三道,那么实际上是丧失了对生活的热忱。麻木僵硬,行尸走肉;虽然活着,但已经死了。简称:活死人。

我看过90年代的下岗潮、房地产泡沫、感受过08年股灾,从来没有看到过,像现在这么大的裁员、那么多店关闭,以及,今天又看到,这么多银行沦陷。从来没有。

形式很不好了,大家要保全实力:
1、不要贷款
2、不要高消费
3、好好工作
4、积极锻炼
5、好好吃饭、好好睡觉
6、不要借钱给别人
7、不要和别人(包括同事)发生争执
8、多读书、考证、练技能

想的时间越长,就越不想去干。 我猜是大脑对此太熟悉,就以为自己已经干过了。

每个人都有自己的长处,这句话小时候都听过吧?这句话的正确理解是,你总能找到一个方向,让你饿不死能混口饭吃,而不是你踢球不行换了体操就能打进世锦赛奥运会争金牌了。

你的孩子病了,你陷入了繁重的债务。接下来是家里的事,你的另一半花光了所有积蓄,留下孩子和一堆账单离开了你。就别再提什么去夜校学习了。在评价别人之前,要记住努力并不代表所有,而且每个人的努力也并非建立在同样公平的前提之上。——卡罗尔·德韦克《终身成长》


java hello world

Java包的定义及使用
https://www.jianshu.com/p/c798a019f2ec

编码

$ vi Hello.java
package com.ihuhao.demo;

public class Hello {
    public static void main(String args[]) {
        System.out.println("Hello world !");
    }
}

编译执行

$ javac -d . Hello.java
$ tree
.
├── com
│   └── ihuhao
│       └── demo
│           └── Hello.class
├── Hello.java

$ java com.ihuhao.demo.Hello

打包执行

$ jar -cvf my.jar com
$ rm com -rf
$ java -classpath './my.jar' com.ihuhao.demo.Hello

java 使用第三方库

Maven Repository 网站搜索需要的 jar 包: https://mvnrepository.com/artifact/com.google.code.gson/gson

$ mkdir lib
$ cd lib
$ wget https://repo1.maven.org/maven2/com/google/code/gson/gson/2.9.0/gson-2.9.0.jar
$ cd ..

$ vi GsonTest.java
package com.ihuhao.demo;

import java.util.HashMap;
import java.util.Arrays;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class GsonTest {
    public static void main(String args[]) {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();

        HashMap<String, Object> map = new HashMap<>();
        map.put("name", "wawa");
        map.put("age", 18);
        map.put("skills", Arrays.asList("吃饭", "睡觉", "打豆豆"));

        String json  = gson.toJson(map);
        System.err.println(json);
    }
}

$ javac  -classpath './lib/gson-2.9.0.jar' -d . GsonTest.java
$ java -classpath '.:./lib/gson-2.9.0.jar' com.ihuhao.demo.GsonTest
{
  "skills": [
    "吃饭",
    "睡觉",
    "打豆豆"
  ],
  "name": "wawa",
  "age": 18
}

本地编译的 java 程序,依赖的 JDK 库和编译时用的 java 编译器,都要和生产环境一致,否则运行时会报错。
本地的 Tomcat 版本和 生成环境也要一致。


java arrays

import java.util.Arrays;

public class ArraysTest {
    public static void main(String[] args) {
        int[][] nums = {{1,2},{3,4}};
        System.out.println(Arrays.deepToString(nums));

        int a[] = new int[] { 18, 62, 68, 82, 65, 9 };
        Arrays.sort(a);
        System.out.println(Arrays.toString(a));
        System.out.println("数字 62出现的位置:"+Arrays.binarySearch(a, 62));
    }
}

vim 开发 java

常见的代码块快捷键:.vim/plugged/vim-snippets/snippets/java.snippets

im
    import java.util.; 
cl
    public class ArraysTest {

    }
main
    public static void main(String[] args) {

    }
sout 
    System.out.println(); 
d.al     
    List<Object> list = new ArrayList<Object>();
d.hm
    Map<Object, Object> map = new HashMap<Object, Object>();

设置 F5 编译运行

$ vim ~/.vimrc
" 当前文件为 java 时 F5 自动编译运行
autocmd FileType java nnoremap <buffer> <F5> :!javac %&&java %:r<CR>

vim 开发 java 最精简配置,写点测试代码,算法代码很方便。


vim 映射

Vimscript 基本映射 https://www.w3cschool.cn/vim/mh1uyozt.html

" 映射普通键
:map - x
" 映射空格
:map <space> viw
" 映射 ctrl + d
:map <c-d> dd

Vimscript 模式映射 https://www.w3cschool.cn/vim/n41ghozt.html

你可以使用nmap、vmap和imap命令分别指定映射仅在normal、visual、insert模式有效。

Vimscript 精确映射 https://www.w3cschool.cn/vim/sxjqcozt.html

Vim提供另一组映射命令,这些命令创建的映射在运行时 不会 进行递归。

:nmap x dd
:nnoremap \ x

每一个map系列的命令都有个对应的noremap命令,包括:noremap/nnoremap、 vnoremap和inoremap。这些命令将不递归解释映射的内容。

该何时使用这些非递归的映射命令呢? 答案是: 任何时候 。

Vimscript Leaders https://www.w3cschool.cn/vim/8y7cnozt.html

:let mapleader = "-"
:nnoremap <leader>d dd

快捷键映射

:nnoremap          <leader>d dd
:nnoremap <buffer> <leader>x dd

表示只在定义它的那个缓冲区中有效。


vim 命令大全

https://www.w3cschool.cn/vim/cjtr1pu3.html


使用Zerotier+Moon结点内网穿透
https://blog.csdn.net/it_LiChengwei/article/details/120934792

zerotier定义了几个专业名词:
PLANET 行星级的服务器,zerotier各地的根服务器,有日本、新加坡等地。
MOON 卫星级服务器,用户自建的私有根服务器,起到中转加速的作用。
LEAF 相当于各个枝叶,就是每台连接到该网络的机器节点。

使用VPS免费搭建Zerotier Moon
https://zhuanlan.zhihu.com/p/405979685

Zerotier可以组建P2P直连虚拟局域网,你可以在公司使用微软自带的远程连接直连自己公司的电脑,访问共享远程控制等。想要P2P访问必须先通过一个中继服务器握手或者转发流量,官方节点速度很慢,所以最好自己搭建Moon节点中继。

Moon节点要求不能DDNS,所以家里公网IP也没法搭,而且由于P2P不成功的话,必需通过Moon中继流量,所以最好使用国内的VPS。


jetty

Jetty 使用教程

Jetty 是一个提供 HTTP 服务器、HTTP 客户端和 javax.servlet 容器的开源项目。

export JETTY_HOME="/home/ubuntu/download/jetty-distribution-9.4.46.v20220331"
cd $JETTY_HOME/demo-base/
java -jar $JETTY_HOME/start.jar
java -jar $JETTY_HOME/start.jar --list-modules
java -jar %JETTY_HOME/start.jar --list-config

JETTY_BASE=/tmp/mybase
mkdir $JETTY_BASE
java -jar $JETTY_HOME/start.jar --add-to-startd=http,deploy
cp $JETTY_HOME/demo-base/webapps/async-rest.war webapps/ROOT.war
java -jar $JETTY_HOME/start.jar

jetty、jetty原理、jetty与tomcat区别

jetty特点

  • jetty是异步的,支持更高的并发量
  • jetty更灵活,更加轻量,更容易定制,更高的资源利用率
  • Jetty 默认采用的 NIO 模型,jetty能很好支持长链接
  • 集成简单,应用只要集成jetty,应用就可以快速支持 http 服务

jetty与tomcat区别

  • Jetty 比 Tomcat 架构更加简单。
    • jetty的所有组件都是基于 Handler 来实现,它的主要功能扩展都可以用 Handler 来实现;
    • Tomcat 的整体设计上很复杂,tomcat是基于容器的架构,开发者要想扩展tomcat功能就需要了解tomcat架构,遵循tomcat的规范。
  • jetty比较容易扩展第三方框架,所以也跟容易定制
  • jetty更加轻量可以节省内存
  • tomcat更加稳定、更加成熟,在企业级中占有率很大

C 语言计时

https://blog.csdn.net/fz_ywj/article/details/8109368

  • time_t time(time_t * timer):
    • C 标准库中的函数,可移植性最好,性能也很稳定,但精度太低,只能精确到秒,对于一般的事件计时还算够用,而对运算时间的计时就明显不够用了。
    • 用 difftime 函数可以计算两个 time_t 类型的时间的差值,可以用于计时。用 difftime(t2,t1) 要比 t2-t1 更准确,因为 C 标准中并没有规定 time_t 的单位一定是秒,而 difftime 会根据机器进行转换,更可靠。
  • clock_t clock(void):
    • 该函数返回值是硬件滴答数,要换算成秒,需要除以 CLOCKS_PER_SEC。
    • 可以精确到毫秒,适合一般场合的使用。
  • int gettimeofday(struct timeval *tv,struct timezone *tz);
    • 其参数tv是保存获取时间结果的结构体,参数tz用于保存时区结果(若不使用则传入NULL即可)。
    • 使用这种方式计时,精度可达微秒。经验证,在arm+linux的环境下此函数仍可使用。推荐。

code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <time.h>
#include <stdio.h>
#include <math.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
time_t start1, end1;
start1 = time(NULL);
for (int i = 0; i < 300000000; ++i) sqrt(i);
end1 = time(NULL);
printf("time=%f\n", difftime(end1, start1));

clock_t start2, end2;
start2 = clock();
for (int i = 0; i < 300000000; ++i) sqrt(i);
end2 = clock();
printf("time2=%f\n",(double)(end2-start2)/CLOCKS_PER_SEC);

struct timeval start3, end3;
gettimeofday(&start3, NULL );
for (int i = 0; i < 300000000; ++i) sqrt(i);
gettimeofday(&end3, NULL );
long timeuse =1000000 * (end3.tv_sec - start3.tv_sec ) + end3.tv_usec - start3.tv_usec;
printf("time3=%f\n",timeuse /1000000.0);

return 0;
}

$ gcc 042.c -lm && ./a.out
time=3.000000
time2=2.407064
time3=2.460698

把这句翻译成英文:这是小明做的我们和其它公司收入的对比结果。

  • youdao: This is the result of comparing our revenue with that of other companies made by Xiaoming.
  • youdao2: This is xiao Ming do we and other comparison results of the company’s revenues.
  • baidu: This is the result of Xiaoming’s comparison of our income with that of other companies.
  • deepl: This is the result of the comparison of our revenue with other companies made by Xiaoming.
  • google:This is Xiao Ming’s comparison of our revenue with other companies.
  • bing:This is the result of Bob’s comparison of our revenue with other companies.
  • a: This is a revenue comparison made by Xiaoming between our company and other companies.
  • b: this is the result of compare of our and other companies on revenue which is by xiaoming.

大家觉得哪个翻译的好一些。


Nix 会超越 Docker 吗?https://www.163.com/dy/article/H5QCFQGO0511FQO9.html

  • Docker 镜像只是 Docker 提供的一小部分,Docker 为整个容器生态系统提供了工具。 而 Nix 的设计旨在构建可重现的包和环境。
  • 如果你的目的是构建可重现的开发环境,则选用 Nix 更合适。
  • 如果你希望寻找一种方法来构建、打包和部署自己的服务,则 Docker 提供的更丰富的工具更适合你。毕竟,容器乃是如今部署 Web 服务的标准方式。

Nix从0到0.1(神奇的包管理工具)https://zhuanlan.zhihu.com/p/392711598

  • Nix作为一个包管理工具,不仅仅完成了管理包的职能,还兼具了快速搭建环境、创建不同版本开发环境的职能,对于需要同一开发工具的同学来说也算是一个很有用的地方吧。
  • 对同一环境会有对应的历史记录,支持版本回滚。
  • Nix支持环境配置文件的编写,在任何一台装有Nix的机器上面都可以实现环境的完美复原,对外部的依赖只有Nix,而且对本身系统所安装的东西影响几乎为零,在我看来安全性也是有所保证的。

Postgresql关于wal日志总结,一文搞清楚它的所有概念和相关操作
https://blog.csdn.net/lusklusklusk/article/details/123603833

简单地说,WAL的核心概念是,对数据文件(表和索引所在的地方)的更改必须在写入了日志文件后这些更改之后才可以写入数据文件,也就是说,描述更改的日志记录被刷新到永久存储之后才可以写数据文件。

使用WAL可以显著减少磁盘写操作的数量,因为只需要将日志文件刷新到磁盘以确保提交事务,而不是事务更改的每个数据文件。日志文件是按顺序写入的,因此同步日志的成本要比刷新数据页的成本低得多。

备注:数据库将脏数据刷到数据文件上,这个动作是随机I/O,性能比写日志的顺序I/O差太多

总结

  • WAL即Write Ahead Log预写式日志,简称wal日志,相当于oracle中的redo日志。只是oracle中redo是固定几个redo日志文件,然后轮着切换去写入。pg中wal日志是动态切换,单个wal日志写满继续写下一个wal日志,连续不断生成wal日志。
  • 单个WAL文件的大小,默认为16MB,参数是wal_segment_size,可以理解为PG把Wal日志存储到N个大小为16M(默认值)的WAL segment file,一般不做更改
  • 如果使用了 WAL 归档,旧的段在被归档之前不能被不能删除或回收,直到它们被归档。如果WAL归档跟不上WAL生成的速度,或者archive_command重复失败,旧的WAL文件将在pg_wal中累积,直到问题解决。
  • 如果max_wal_size和wal_keep_segments没起作用导致wal_pg目录下面的wal日志文件不自动删除从而越来越多,原因主要是负载过重、archive_command失败或wal_keep_segments设置过高
  • 正常情况下pg_wal目录下的wal文件为在线WAL日志,不能删除,删除后如果遇到数据库重启则会丢失数据
  • pg_wal日志没有设置保留周期的参数,即没有类似mysql的参数expire_logs_days,在检查点之后,当旧的wal日志文件不再需要时,它们将被删除或回收(按编号顺序重命名为将来的段)。
  • PostgreSQL在写入频繁的场景中,会产生大量的WAL日志,而且WAL日志量会远远超过实际更新的数据量,这就叫做“WAL写放大”,产生的原因主要有以下两点。说个题外话当年Uber也是这个原因之一把pg切换成了mysql,参见https://eng.uber.com/postgres-to-mysql-migration/
    • full page writes,PostgreSQL会在一个checkpoint检查点之后的页面的第一次修改期间将每个页面的全部内容写到Wal文件
    • update时如果新记录位置发生变更,索引记录也要相应变更,这个变更也要记入WAL。而索引记录的变更又有可能导致索引页的全页写,进一步加剧了把内容写到Wal文件。

PostgreSQL之wal_keep_segments参数
https://blog.csdn.net/qq_35462323/article/details/115381735


what does %WCPU column mean in TOP output ?
https://community.hpe.com/t5/HP-UX-General/what-does-WCPU-column-mean-in-TOP-output/td-p/3011779

%WCPU is “Weighted CPU (central processing unit) percentage”

%CPU is “Raw CPU percentage. This field is used to sort the top processes”.

The %WCPU is just a ‘forecast’ value for the process. It really has no real world value. It’s value is totally controlled by the scheduler.

The man page for top(1) indicates that %CPU is the “Raw CPU percentage. This field is used to sort the top processes”.

Well, the %CPU is the total percentage without the ‘forecast’ factor built-in, such as a ‘raw value.’


PostgreSQL 如何查找TOP SQL (例如IO消耗最高的SQL)
https://blog.csdn.net/weixin_34102807/article/details/90588528

资源分为多个维度,CPU,内存,IO等。如何能了解各个维度层面的TOP SQL呢?

pg_stat_statements插件可以用于统计数据库的资源开销,分析TOP SQL。


一分钟抓一次耗费CPU最高的进程

1
2
3
4
5
6
7
8
9
10
11
$ cat cron_cpu_stat.sh
date
ps -Ao pid,pcpu,pmem,cmd --sort=-pcpu | head -n 10
echo '==================='

$ sudo touch /var/log/cpu_stat.log
$ sudo chown $USER /var/log/cpu_stat.log
$ ls -l /var/log/cpu_stat.log
$ crontab -l
* * * * * cd /home/ubuntu && bash cron_cpu_stat.sh >> /var/log/cpu_stat.log 2>&1
$ tail -f /var/log/cpu_stat.log

How to Check Cron Logs on Ubuntu 18.04
https://linoxide.com/check-cron-logs-ubuntu/

ubuntu 上单独查看 crontab 的日志

sudo vi  /etc/rsyslog.d/50-default.conf

    cron.* /var/log/cron.log

sudo systemctl restart rsyslog

tail -f /var/log/cron.log

一组语料,如何提取出现频率最高的短语,而不是单词,比如

good morning Sir.
good morning teacher.
good morning class.
good afternoon Sir.
good afternoon teacher.

我要得到出现次数最多的 top 2 的短语 “good morning” 和 “good afternoon”
而不是出现次数最多的 top 2 的单词 “good” 和 “morning”

算法复杂度大概是多少?


计算一组数据的分散程度

How to Calculate the Coefficient of Variation in Python
https://www.statology.org/coefficient-of-variation-in-python/

Python统计学(四)——离散性测度
https://zhuanlan.zhihu.com/p/344919136

  • 极差的概念很容易理解,一个样本中最大与最小观测值之间的差异称为极差(range)
  • 平均离差就是样本中全部数值与它们均值变动的平均数量来度量离散程度。
  • 分位数也叫百分位数,最常使用的有四分位数(25,50,75),五分位数(20,40,60,80)和百分位数(10,20,30,…,90)。
  • 方差和标准差是日常统计中应用非常广泛而且频繁的指标之一
  • 方差的量纲是原数据量纲的平方,标准差的量纲跟原数据的量纲是一样的,这就是为什么标准差运用得比方差更广泛。但是,在不同量纲的数据之间做比较时,标准差就不能使用了,因为单位都不一样,不用简单作比较。这个时候变异系数(coefficient of variation, CV)就派上用场了。变异系数就是标准差除以均值的百分比,变异系数是一个无量纲的值。
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> np.std([2,2,2,2,2])
0.0
>>> np.std([8,2,0,0,0])
3.0983866769659336
>>> np.median([2,2,2,2,2])
2.0
>>> np.median([8,2,0,0,0])
0.0
>>> cv = lambda x: np.std(x, ddof=1) / np.mean(x) * 100
>>> cv([2,2,2,2,2])
0.0
>>> cv([8,2,0,0,0])
173.20508075688772

Python统计学(三)——位置测度
https://zhuanlan.zhihu.com/p/344780317

  • 样本均值(算术平均数)
  • 加权平均数是算术平均数的一种特殊情形。当有几个相同数值的观测值时,算术平均数就会变成加权平均数。
  • 中位数:将一组数据从最小到最大、或者从最大到最小排序以后,位于中点的数值。
  • 众数:在一个样本的所有观察值中,发生频率最大的一个值称为样本的众数。
  • 几何平均数在商业、工业、金融当中应用非常广泛,特别是涉及到随时间推移的平均变动时,几何平均数就派上用场。比如计算营业额增长率、复利、GDP等。
  • 调和平均数仅适合于有限数量的应用情形,比如计算股票的平均成本等。它是对于观测值的倒数进行求和后再求平均,最后将平均值求倒数后得到。

Python统计学(五)——切比雪夫、偏度及峰度
https://zhuanlan.zhihu.com/p/346810231

  • 当得知样本观察值呈正态分布时,可以用前面的正态经验法则来评估数据大约有多大比例集中在什么范围内;当然,如果不清楚数据分布情况,或者数据分布不是正态分布,那么我们可以利用切比雪夫定理来做评估。
  • 一个分布如果不对称,则被称为偏度。分布有对称、正偏(右偏)、负偏(左偏)。正偏的分布表现出右侧长尾,负偏的分布具有左侧长尾。正偏的单峰分布,其众数要小于中位数,而中位数又小于均值;负偏的单峰分布刚好相反。
  • 一个分布如果不对称,则被称为偏度。分布有对称、正偏(右偏)、负偏(左偏)。正偏的分布表现出右侧长尾,负偏的分布具有左侧长尾。正偏的单峰分布,其众数要小于中位数,而中位数又小于均值;负偏的单峰分布刚好相反。
  • 峰度是一个统计度量指标,它告诉我们一个分布的峰值比正态分布更高还是更低。标准差越小,曲线越陡;标准差越大,曲线越平缓。
  • 一个分布的峰值如果比正态分布要大,称其为尖峰的(leptokurtic),一个分布的峰度如果等于正态分布,称其为中峰的(mesokurtic),一个分布的峰度如果比正态分布要小,称其为低峰的(platykurtic)。
  • 对于所有正态分布来说峰度等于3,许多统计软件会给出超额峰度(excess kurtosis),也就是峰度减去3之后的值。一个正态分布或者其他中峰分布的超额峰度为0, 一个尖峰分布的超额峰度大于0,一个低峰分布的超额峰度小于0。
  • 标准差会影响正态分布曲线的高度,值均的不同会让曲线进行左右平移。

Statsmodels 统计包之 OLS 回归
https://blog.csdn.net/qq_17119267/article/details/79108333

jupyter 里输出表格

1
2
3
4
5
6
7
from IPython.display import HTML, display
import tabulate
table = [["Sun",696000,1989100000],
["Earth",6371,5973.6],
["Moon",1737,73.5],
["Mars",3390,641.85]]
display(HTML(tabulate.tabulate(table, tablefmt='html')))

How do I output lists as a table in Jupyter notebook?
https://newbedev.com/how-do-i-output-lists-as-a-table-in-jupyter-notebook

tabulate:在 Python 中可如此优雅地创建表格
https://zhuanlan.zhihu.com/p/485136394


How we improved DNS record build speed by more than 4,000x
https://blog.cloudflare.com/dns-build-improvement/


python matplotlib 双y轴图像实现
https://blog.csdn.net/weixin_48964486/article/details/124134584

其中第一个坐标系正常创建,第二个坐标系则使用专有的 twinx() 方法创建。因为有了两个 y 轴,如果再简单地使用 plt.ylabel() 等方法,则只能操作到左轴,而影响不到右轴。

data1 = [random.randint(1,50) for x in range(10)]
data2 = [random.randint(1,1000) for x in range(10)]

fig = plt.figure(figsize=(10, 8))

ax1 = fig.add_subplot(111)
ax1.set_ylabel('左 Y 轴')
ax1.plot(data1)

ax2 = ax1.twinx()
ax2.plot(data2, color='#3399ff', linestyle='--', marker='o', linewidth=2)
ax2.set_ylabel('右 Y 轴')

plt.show()

数学

实践线性规划:使用 Python 进行优化
https://bbs.huaweicloud.com/blogs/317032

线性规划是数学规划中使用的一组技术,有时称为数学优化,用于求解线性方程组和不等式系统,同时最大化或最小化某些线性函数。它在科学计算、经济学、技术科学、制造、运输、军事、管理、能源等领域很重要。

用python解决线性规划
https://bbs.huaweicloud.com/blogs/317032

Numpy中np.dot与np.matmul的区别
https://blog.csdn.net/ACTerminate/article/details/96151132

python实现最小二乘法
https://www.csdn.net/tags/MtTaIg1sMDc5MTQtYmxvZwO0O0OO0O0O.html

Python最小二乘法拟合与作图
https://www.jianshu.com/p/8850b94ec61c

线性代数下的最小二乘法及numpy运算案例
https://zhuanlan.zhihu.com/p/369173593

def least_squares(x,y):
    ones = np.ones((len(x)))
    A = np.c_[ones,x]
    ATA = A.T.dot(A)
    ATb = A.T.dot(y)
    inv_ATA = np.linalg.inv(ATA)
    solution = inv_ATA.dot(ATb)
    return solution

Python手工实现朴素贝叶斯分类及预测
https://zhuanlan.zhihu.com/p/486313053

简洁高斯朴素贝叶斯分类原理及python实现
https://blog.csdn.net/qq_45656248/article/details/118796503
https://baijiahao.baidu.com/s?id=1691227678810779479&wfr=spider&for=pc

这是每个数据科学职业生涯开始时的经典:朴素贝叶斯分类器。或者更应该说是朴素贝叶斯分类器家族,因为它们有很多种风格例如,有多项式朴素贝叶斯,伯努利朴素贝叶斯,还有高斯朴素贝叶斯分类器,每个分类器在一个小细节上都不同,我们会发现:朴素贝叶斯算法在设计上非常简单,但在许多复杂的实际情况下被证明是有用的。

Numpy实现NaiveBayes(朴素贝叶斯)
https://blog.csdn.net/hhhhhhhhhhwwwwwwwwww/article/details/121558563

numpy实现朴素贝叶斯模型(高斯分布)
https://www.jianshu.com/p/efa980944235

数值分析-雅克比迭代法
https://blog.csdn.net/ITGGU/article/details/122169136


postgree 的终端工具 psql 里输入 \x on 可以让输出结果按列显示,相当于 mysql client里的 \G


蒙特卡洛模拟股票曲线,设置均值,标准差,以及跳空高开和跳空低开的概率
https://github.com/boyac/pyOptionPricing

用python动手实践与学习大数定律与中心极限定理
https://zhuanlan.zhihu.com/p/394395551

各种分布的随机数生成器
https://numpy.org/doc/stable/reference/random/generator.html#distributions
https://blog.csdn.net/weixin_42029738/article/details/81977492

离散分布的相关对象,每个对象有概率质量函数,累计分布函数,百分位函数,分布描述这些
https://docs.scipy.org/doc/scipy/reference/stats.html#discrete-distributions

  • rvs(n, p, loc=0, size=1, random_state=None) Random variates.
  • pmf(k, n, p, loc=0) Probability mass function.
  • cdf(k, n, p, loc=0) Cumulative distribution function.
  • ppf(q, n, p, loc=0) Percent point function (inverse of cdf — percentiles).
  • stats(n, p, loc=0, moments=’mv’) Mean(‘m’), variance(‘v’), skew(‘s’), and/or kurtosis(‘k’).

给博客启用HTTPS证书

开启443端口

1
2
3
# iptables -A INPUT -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
# iptables -A OUTPUT -p tcp --sport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
# service iptables save

申请证书

生成用户标识私钥和域名证书私钥

1
2
3
4
mkdir -p /data/ssl
cd /data/ssl
openssl genrsa 4096 > account.key
openssl genrsa 4096 > domain.key

生成证书请求文件

openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:ihuhao.com,DNS:www.ihuhao.com,DNS:app.ihuhao.com")) > domain.csr

使用acme-tiny脚本到Let's Encrypt 申请证书, 下载acme_tiny脚本

wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

创建一个目录用于存放证书验证过程中的临时文件

mkdir  /data/www/challenges/

设置nginx, 以blog.ihuhao.com为例, 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
server {
listen 80;
listen 443 ssl;
server_name blog.ihuhao.com;

ssl_certificate /data/ssl/chained.pem;
ssl_certificate_key /data/ssl/domain.key;

ssl_prefer_server_ciphers on;
ssl_dhparam /data/ssl/dhparam.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
keepalive_timeout 70;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;

add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

location ^~ /.well-known/acme-challenge/ {
alias /data/www/challenges/;
autoindex on;
}

location / {
alias /home/wawa/src/onlytiancai.github.io/;
expires 1h;
autoindex on;
}

}

执行脚本,申请证书

python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /data/www/challenges/ > ./signed.crt

脚本执行过程中,会在/data/www/challenges目录下生成一个随机文件,然后Let's Encrypt会访问http://blog.ihuhao.com/.well-known/acme-challenge/下的文件用于验证域名,所以上面的nginx配置要配置好,整个脚本才能执行成功。

下载中间证书,并和上一步生成的crt粘合在一起,生成nginx使用的证书。

1
2
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem

nginx配置,上面已经贴过了,证书路径,证书私钥路径,证书参数配置等都配好了,刷新下nginx配置,网站就可以用https访问了。

/usr/local/nginx/sbin/nginx -s reload

hexo改动

因为上面的nginx配置开启了HSTS, 但hexo的yilia模版里有的地方强引用了http的脚本,所以要做适当的修改,目前主要有如下两个路径

./themes/yilia/layout/_partial/after-footer.ejs
./themes/yilia/layout/_partial/mathjax.ejs

http://xxx改成//xxx,然后hexo generate生成一下博客就可以了

参考链接

腾讯云主机迁移

以前在广州区买的共享核主机,不能续费了,官方给发了代金券,免费升级到独立核的1核1G主机,所以就重新买了北京机房的云主机,要把以前的数据全部导过来。

安装好Centos6.5 64bit,安全组选了开放所有端口,然后自己用iptables做安全限制就行。

先用vnc以root登录,密码在邮件发给你了,新建wawa用户,设置密码,用visudo设置允许无密码sudo,配置sshd config把root的ssh登录关了,端口换成非22端口, 允许ssh登录,允许密码登录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
useradd wawa
passwd wawa

visudo

wawa ALL=(ALL) NOPASSWD: ALL

vi /etc/ssh/sshd_config

Port 36000
PermitRootLogin no
AllowUsers wawa
PasswordAuthentication yes
ChallengeResponseAuthentication yes

service sshd reload

然后就可以用putty登录wawa账户了。

旧机器上把要迁移的数据打包, 主要有Let’s Encrypt的脚本,.vim, .vimrc,.bashrc,.bash_profile,crontab, rc.local, nginx配置,.ssh等

1
2
3
4
5
6
7
tar zcfv bk.tar.gz \
/usr/local/nginx/conf/nginx.conf \
/var/spool/cron/root \
/etc/rc.d/rc.local \
/data/ssl/ \
.vimrc .vim .gitconfig .bashrc .bash_profile .ssh/ \
scripts/ src/ readme

打包了,想办法下周到新机器上,解压,大多文件放home目录就可以了,nginx配置,rc.local, crontab, let’s encrypt得重新对一遍。

安装必备环境,git, nginx, python, node。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
sudo yum gcc
sudo yum install gcc-c++
sudo yum install make
sudo yum install sqlite-devel
sudo yum install zlib-devel
sudo yum install readline-devel
sudo yum install bzip2-devel
sudo yum install git
sudo yum install pcre pcre-devel
sudo yum install openssl-devel
yum install mysql-devel

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
nvm install 5.0

wget https://www.python.org/ftp/python/2.7.7/Python-2.7.7.tgz --no-check-certificate
tar xf Python-2.7.7.tgz
cd Python-2.7.7
./configure --prefix=/usr/local
make
sudo make install
/usr/local/bin/python -V

wget http://nginx.org/download/nginx-1.9.12.tar.gz
tar xf nginx-1.9.12.tar.gz
cd nginx-1.9.12
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-http_stub_status_module
make
sudo make install
sudo /usr/local/nginx/sbin/nginx

防火墙设置下, 只允许ssh端口,80,443链接,把其它的端口都关了,再把本机访问本机打开,允许本机向外的访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
iptables -L -n
iptables -A INPUT -p tcp --dport 36000 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 36000 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --sport 443 -m state --state NEW,ESTABLISHED -j ACCEPT

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

iptables -A OUTPUT -j ACCEPT

service iptables save

基本能用了。