独钓寒江雪

用C++的优雅,驯服Windows的狂野

在C++98时代,我们经常会遇到这样的性能瓶颈:当需要返回或传递大型对象(如字符串、向量或自定义资源管理类)时,不得不进行昂贵的深拷贝操作。即使我们知道某些对象即将被销毁,也无法避免这种拷贝开销。

C++11引入的右值引用和移动语义彻底改变了这一局面,让C++程序员能够写出更高效、更现代的代码。

阅读全文 »

C++从C++11开始引入了智能指针(std::unique_ptr、std::shared_ptr、std::weak_ptr),并后面的各个版本中对智能指针进行了改进。

阅读全文 »

使用Qt静态库违背了Qt的免费使用协议!

编译

编译Qt源码需要提前安装如下工具:

  • nasm
  • perl
  • gperf
  • win_flex_bison
  • llvm
  • python2
  • openssl
阅读全文 »

同一个DLL文件可以被多个进程加载。当不同的进程将DLL映射到自己的内存空间时,系统会为DLL中的全局和静态变量创建不同的实例,而不会共享同一个变量实例。

那我们如何实现在进程间共享DLL全局变量呢?
我们可以在DLL中使用如下语句来创建一个段,用来存放那些需要共享的变量:

1
2
3
4
#pragma data_seg("AnyName")  // 开始
// 声明变量
// ....
#pragma data_seg() // 结束

共享的变量需要被初始化,并且还要设置链接器开关,使该段在所有映射DLL的进程中成为共享读写属性:

1
2
// 共享读写
#pragma comment(linker,"/SECTION:AnyName,RWS")

经过上述操作,共享的变量就可以跨不同进程进行读写操作了。

exit命令

exit命令用于退出当前的批处理脚本,并返回一个退出代码ExitCode(即返回值)。退出代码通常是一个整数,用于指示脚本执行的状态,例如成功(0)或失败(非零值)。

exit命令的语法为:

1
exit [/b] [exitCode]

其中 /b 选项表示仅退出当前批处理脚本的执行,而不会影响调用脚本的父进程。如果不使用 /b 选项,则 exit 命令会终止当前整个的命令处理器进程(CMD.EXE),并返回退出代码给调用者。

exitCode 是一个可选参数,用于指定退出代码。如果未指定退出代码,则默认返回上一个命令的退出代码。

阅读全文 »

Qt 虽然提供了诸如 Qt::FramelessWindowHint 之类的属性可以移除窗体的边框,但是移除边框之后,窗体的一些默认行为同时也被移除了,如鼠标拖动改变大小、双击标题栏最大化等,这些行为需要开发者自己来实现。

本文主要介绍实现无边框窗体的几种方案,并在最后分享了作者实现的方案。

笔者认为,一个完美的无边框窗体解决方案需要支持如下功能:

  1. 支持通过使用鼠标拖拽来改变窗体位置和大小;
  2. 支持双击标题栏最大化窗体和还原窗体;
  3. 支持 Windows Areo Snap 特性;
  4. 支持系统阴影;
  5. 支持跨不同 DPI 的屏幕拖拽;
  6. 适应分辨率和 DPI 改变;
阅读全文 »

Hexo是一个快速、简洁且高效的博客框架,使用Hexo可以快速地生成静态博客框架。在框架生成完成后,可以使用任意文本编辑器语法书写博客。我们可以使用Markdown语法书写博客,Hexo在生成博客时会自动将Markdown解析成Html静态页面。

Hexo官网:https://hexo.io/zh-cn/
Hexo中文文档:https://hexo.io/zh-cn/docs/

一、玩法说明

使用Hexo写博客的大致流程如下:

  1. 生成博客框架
  2. 配置博客
  3. 选择自己喜欢的主题
  4. 配置博客和主题
  5. 写文章
  6. 生成博客
  7. 发布博客到服务器

其中,第1~4步为前置操作,只需要执行一次。

Hexo只负责生成静态的HTML文件,不提供服务器。如需对外发布博客,我们还需将HTML文件部署到服务器上,可以选择如下的方式:

  • Github Pages、GitLab Pages,免费,访问速度较慢。
  • Gitee Pages,收费。
  • 对象存储服务,如阿里云OSS、腾讯云COS、七牛云OSS等。当访问量大时,需搭配CDN使用,避免因数据回源产生巨额流量费用。
  • 自己购买服务器使用Nginx搭建Web服务器。当访问量大时,服务器出口带宽要求较高,此时仍然需要搭配对象存储服务和CDN使用。
阅读全文 »

慢日志设置

1
2
3
4
# 当命令耗时超过5毫秒时,记录慢日志
CONFIG SET slowlog-log-slower-than 5000
# 只保留最近500条慢日志
CONFIG SET slowlog-max-len 500

查看慢日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
127.0.0.1:6379> SLOWLOG get 5
1) 1) (integer) 32693 # 慢日志ID
2) (integer) 1593763337 # 执行时间戳
3) (integer) 5299 # 执行耗时(微秒)
4) 1) "LRANGE" # 具体执行的命令和参数
2) "user_list:2000"
3) "0"
4) "-1"
2) 1) (integer) 32692
2) (integer) 1593763337
3) (integer) 5044
4) 1) "GET"
2) "user_info:1000"
...

BigKey

如果查询慢日志发现,并不是复杂度过高的命令导致的,而都是 SET / DEL 这种简单命令出现在慢日志中,此时需要考虑实例否写入了 BigKey。

BigKey 俗称“大 key”,Redis 是 key-value 的存储方式,当一个 Key 所对应的存储数值过长时,就会出现大 key 的情况。

Redis 在写入数据时,需要为新的数据分配内存,相对应的当从 Redis 中删除数据时,也会释放对应的内存空间。BigKey 会导致分配和释放内存的耗时都比较长。

可以使用下面命令扫描 Redis 中的 BigKey:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01

...
-------- summary -------

Sampled 829675 keys in the keyspace!
Total key length in bytes is 10059825 (avg len 12.13)

Biggest string found 'key:291880' has 10 bytes
Biggest list found 'mylist:004' has 40 items
Biggest set found 'myset:2386' has 38 members
Biggest hash found 'myhash:3574' has 37 fields
Biggest zset found 'myzset:2704' has 42 members

36313 strings with 363130 bytes (04.38% of keys, avg size 10.00)
787393 lists with 896540 items (94.90% of keys, avg size 1.14)
1994 sets with 40052 members (00.24% of keys, avg size 20.09)
1990 hashs with 39632 fields (00.24% of keys, avg size 19.92)
1985 zsets with 39750 members (00.24% of keys, avg size 20.03)

对线上实例进行 bigkey 扫描时,Redis 的 OPS 会突增,为了降低扫描过程中对 Redis 的影响,需要控制扫描的频率,指定 -i 参数即可,它表示扫描过程中每次扫描后休息的时间间隔,单位是秒。

0%