Home avatar

This is my blog

Potobuf 的编码

编码的作用

其实当前的数值类型 (int, short, char, …)可以理解为定长编码, 但是现实中, 我们 80% 的情况下, 只使用一些小的正整数, 还有些情况下, 使用小的负数。 这样一来我们就可以压缩信息。比如: 0000 0000 0001, 我们可以压缩为 11 个 0, 一个 1。因为信息(11 个 0, 1 个 1)是连在一起的 (还有多个信息也是连在一起的), 我们需要一种方案来区分开 11 个 0一个 1, 还有区分其他信息。可以理解为需要信息边界 (自定义的概念), 而 variant 的消息边界是"每个字节的最高位(第8位)用来表示是否有后续字节", 信息内的信息边界是, 全是 0 则不记录。信息之间的消息边界是, 最高位 (第 8 位) 为 0 时, 信息的右边界。

Test Blog

Chroma Style

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
	// hi
	fmt.Println("Hello, World!")
}

No type:

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
	// hi
	fmt.Println("Hello, World!")
}

mathjax

行内数学公式:$a^2 + b^2 = c^2$。

QT时间转换接口的加锁问题

遇到问题的场景

  • 负责旧司的后台工具, 要转换大量的 K 线文件 (一共百 GB 级别)。用到多线程转换。但是在转换过程中, CPU 占用和磁盘速度没有拉满。
  • 因为工具是在 Windows 平台运行的, 所以使用了 进程资源管理器 查看进程的运行情况。发现内核时间占用比较多。所以猜测是加锁导致的。

解决问题的思路

  • 直接使用控制变量法是最快的。因为线程池的 worker 使用最频繁的代码块是转换 K 线的各个字段的 for 代码。
  • 注释该 for 的代码。然后运行, 发现 CPU 占用和磁盘直接拉满。
  • 基本确定是该块代码加锁了。
  • 这时发现时间转换使用了 QT 的 QDateTime::fromString。我不知内部实现, 所以注释日期转换代码。发现 CPU 占用和磁盘速度也是拉满的。
  • 所以基本确定是 QDateTime::fromString 代码加锁了。
  • 最后自己根据时间字符串的分隔符取出各个时间字段 (年、月、日、时、分、秒)。

查看 QDateTime::fromString 的实现

为了满足自己的好奇心去查看了 QT 的 QDateTime::fromString 的实现:

记录一次向 AUR 提交包

配置 ssh 的公私钥

生成公私钥:

1
ssh-keygen -f ~/.ssh/aur    # 默认是 ed25519

~/.ssh/config:

1
2
3
Host aur.archlinux.org
  IdentityFile ~/.ssh/aur
  User aur

向 aur 账号添加公钥:

1
My Account -> SSH 公钥 -> 更新

创建软件包仓库并提交

1
2
# 如果仓库不存在, 则会自动创建此仓库
git clone ssh://aur@aur.archlinux.org/<your_pkg_name>.git

编写 PKGBUILD (叫 AI 帮写一个, 再修改即可)。注意: arch 不要使用 ‘any’, 有如下架构: arch=('i686' 'pentium4' 'x86_64' 'arm' 'armv7h' 'armv6h' 'aarch64')。See PKGBUILD ref

Enable_if 的用法

函数返回值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <type_traits>

template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
foo(T t) {
    std::cout << "Integer: " << t << std::endl;
    return t;
}

template <typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
foo(T t) {
    std::cout << "Floating point: " << t << std::endl;
    return t;
}

int main() {
    foo(10);
    foo(3.14);
    return 0;
}

模板的默认类型实参

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
#include <iostream>
#include <type_traits>

// 如果我只想该函数模板只接收整型
template <typename T, typename /*U (可以不写)*/ = std::enable_if_t<std::is_integral<T>::value, bool>>
void foo(T t) {     // 只有需要一个版本的 foo 的情况下。因为模板的默认实参不同的两个模板是相同的东西。
                    // 如果想要两个版本以上, 则将 enable_if 做成模板类型, 请继续向下看。
  std::cout << "Integer: " << t << std::endl;
}

int main() {
  foo(10);
  foo(10.1);    // error: no matching function for call to ‘foo(double)’
  return 0;
}

模板类型形参

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <type_traits>

/* 如果需要两个以上版本的 foo 的情况下。*/

template <typename T, std::enable_if_t<std::is_integral<T>::value, bool> /* param (形参名也可以省略) */ = true>
void foo(T t) {     
  std::cout << "Integer: " << t << std::endl;
}

template <typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
void foo(T t) {     
  std::cout << "Float: " << t << std::endl;
}

int main() {
  foo(10);
  foo(10.1);
  return 0;
}

模板的特化形参

 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
#include <iostream>
#include <type_traits>

template<typename T, typename U>
class Foo {};

template<typename T>
class Foo<T, std::enable_if_t<std::is_same_v<T, int>, T>> {
  public:
    Foo() {
      std::cout << "int" << std::endl;
    }
};

template<typename T>
class Foo<T, std::enable_if_t<std::is_same_v<T, float>, T>> {
  public:
    Foo() {
      std::cout << "float" << std::endl;
    }
};

template<typename T>
using MyFoo = Foo<T, T>;

int main() {
  MyFoo<int> foo1;
  MyFoo<float> foo2;
  return 0;
}

扩展 enable_if

IsIntegral:

0%