环石岩湖骑行

环石岩湖是我这几次骑行里面体验最好的,风景、租车、骑行道各方面都很不错,再加上当天天气很好,只有 22–26 度,碰巧天阴没啥大太阳。整个体验下来非常愉悦。

如果想要轻松点的,可以直接在湿地公园里面围着石岩湖骑行,没坡,风景好,难度很小。

如果决定环湖骑,整个过程大概有 1/5 的路段是在马路旁边骑的,其他都在公园内部,能看出石岩当地政府非常重视这条线路,规划好了专门的环湖骑行道。不过环湖会累一点,一直会有上下坡,很多段上坡我都是累得直接推着车走了。

整个环湖我大概骑了 29 公里,主要是路不熟,刚开始在湿地公园里面绕了好几圈,实际很多人环湖一圈就是 20–22 公里。

最后说一下租车,我在石岩湖湿地公园 P2 停车场出口处的自行车店里面租了一辆喜德盛 hacker 380,租金 10 块一小时,30 元封顶。考虑到在深圳,这个价格相当便宜了。而且令我诧异的是,押金竟然只要 50,我骑了 2 个半小时多一点,最后也没向上取整按小时算,只收了 25。

石岩湖骑行道 石岩湖骑行道
马路旁边有专门的骑行道,上面有环石岩湖骑行指示牌 马路旁边有专门的骑行道,上面有环石岩湖骑行指示牌
一路上几乎都是这样的骑行道,有些地方会窄些 一路上几乎都是这样的骑行道,有些地方会窄些
不少人会在湖边露营 不少人会在湖边露营
湖畔骑行道 湖畔骑行道
湿地公园里的水域 湿地公园里的水域

Flink keyBy 为什么要多做一次 MurmurHash?

在 Flink 中做 keyBy 的时候,内部根据 key 选择下游节点时,有这么一段逻辑,代码在 KeyGroupRangeAssignment.java#L75:

int computeKeyGroupForKeyHash(int keyHash, int maxParallelism) {
        return MathUtils.murmurHash(keyHash) % maxParallelism;
}

简单来说,就是根据 key 的 hash 值,计算出 key 的分组。这里需要注意的是,并非直接简单地根据 hash 值取模,而是经过了一次 MurmurHash。

那为什么要这么做,解决了什么问题呢?

问题简单来说就是:keyBy 之后的分组要足够均匀,而用户定义的 keyHash 未必均匀。

举个最极端的例子:M % 10,但 M 的取值全都是 10 的倍数,比如 {10, 20, 30} 等。那无论 M 的取值有多分散和随机,M % 10 都等于 0,那么最终只有分组 0 里面有数据,将会发生严重的数据倾斜。

为什么 MurmurHash 能解决这个问题?

Continue reading

大沙河生态长廊骑行

大沙河的一端在深圳湾公园,最终在深圳湾入海。从深圳湾公园出发,走右侧道路,一路上骑行道和人行道分离的都很好,路面也比之前走左侧时更宽,即使是十一假期,骑着也很舒服。

快到绿道尽头骑出来的时候,才意识到自己已经骑了很远 —— 旁边竟然就是深圳野生动物园。

返程不想打车或者地铁回去,觉得枯燥又无聊,干脆换条路一口气骑回家,最终刷新了个人骑行最远纪录:35 公里。奇妙的体验~

骑行道和人行道分开 骑行道和人行道分开
大沙河沿岸 大沙河沿岸
全程 35.73 公里 全程 35.73 公里

梅林水库绿道徒步

从长岭陂地铁站 A1 口出来,直走大概 500 米,有条左拐进山的破破的小路,路边停满各种落满了叶子的车,一度让我怀疑是不是走错路了。

一路上都是石板路,没有什么野路(不过石板缝隙挺大的, 挺容易崴脚, 骑车也不行),路面很平缓,几乎感受不到在爬升,大部分路段都被树荫覆盖。属于新手入门级的徒步线路。

不过虽然很凉快,但还是注意防晒,出发的时候忘记带防晒衣和帽子,晚上洗澡的时候发现脖子晒伤了。

路上见到不少带着负重背心越野跑的人,感慨和羡慕满满的生命力和活力!

鲲鹏径第七段路牌与线路图 鲲鹏径七段(紫涧园 — 梅林水库绿道涂鸦墙)
林荫下的绿道 林荫下的绿道
站在梅林水库大坝上拍的蓝天白云 站在梅林水库大坝上拍的蓝天白云
7.84 公里,累计爬升 222 米 7.84 公里,累计爬升 222 米

深圳湾骑行

今年开始去海边公园骑行,骑了几次,可以说是最近几年所有事情里最舒服的体验。尤其深圳湾这条线,从人才公园一路延伸到蛇口,有专门的骑行道,而且道平灯亮,慢悠悠地骑车既踏实又放松。

对面灯火璀璨的香港 对面灯火璀璨的香港
一路上道平灯亮 一路上道平灯亮

Awesome C++ Blogs

类似于必读书目的书单,那些值得反复阅读、常读常新的技术博客,也应该被系统地整理成一份精选集合。

先开个坑,后续逐步填充内容~

博客升级了~

基于 Astro,从零重新实现

Continue reading
2025

C++ 如何计算普通类型的 Hash 值:基于 gcc/clang 源码分析

当 int/long/float/指针/std::string 作为 std::unordered_map 的 key 时,C++ 底层是如何计算 hash 值的?

gcc/clang 作为使用最多的两种编译器和标准库,它们在这个问题的实现上略有差异。本文将基于二者的源码进行对比分析。

Continue reading

std::any 的性能开销:基于 libstd++ 源码分析

C++17 中引入了 std::any,可以非常方便地将任意类型的变量放到其中,做到安全的类型擦除。然而万物皆有代价,这种灵活性背后必然伴随着性能取舍。

std::any 的实现本身也并不复杂,本文将基于 libstd++ 标准库源码 深入解析其实现机制与性能开销。

Continue reading

从源码角度解读 enable_shared_from_this

我们在使用 C++ 的时候,有时会需要在类的内部获取自身的 shared_ptr,这就会用到 std::enable_shared_from_this。在实际使用过程中,std::enable_shared_from_this 有三个陷阱需要注意:

Continue reading
2024

Context 的错误使用引发 Panic 的问题复盘

我们有这么一段业务代码,在 Gin 的 API Handler 中,开了一个子 goroutine 写 DB,代码大概是这样:

Continue reading
2023

Go 1.22 可能将改变 for 循环变量的语义

几乎世界上每个 Golang 程序员都踩过一遍 for 循环变量的坑,而这个坑的解决方案已经作为实验特性加入到了 Go 1.21 中,并且有望在 Go 1.22 中完全开放。

Continue reading

剖析 Golang Bigcache 的极致性能优化

Bigcache 是用 Golang 实现的本地内存缓存的开源库,主打的就是可缓存数据量大,查询速度快。 在其官方的介绍文章 《Writing a very fast cache service with millions of entries in Go》 一文中,明确提出了 bigcache 的设计目标:

Continue reading

解读 Golang 标准库里的 varint 实现

最近发现 Golang 标准库竟然自带了 varint 的实现,代码位置在 encoding/binary/varint.go,这个跟protobuf里面的varint实现基本是一致的。刚好借助 golang 标准库的 varint 源码,我们来系统地学习和梳理下 varint。

Continue reading
2021

深度分析 Golang sync.Pool 底层原理

sync.Pool 是 Golang 内置的对象池技术,可用于缓存临时对象,以缓解因频繁建立临时对象带来的性能损耗以及对 GC 带来的压力。

Continue reading