Here I want share some strengths of FILCO MINILA, especially the 2nd generation MINILA-R Convertible. So, basically these points are main considerations when I choosing a mechanical keyboard.
Layout & Built-in shortcuts
For me these are the most important consideration. It has direct impact on productivity, when it used by programmer, this effective comes double. I believe less finger move bring faster strike, that’s why I prefer compact keyboards. But not just the layout, the built-in shortcuts must came help for the arrow and other feature keys.
The MNILA-R Convertible inherit most shortcuts from last gen and imporve the built-in shortcuts support for Mac, like volume, screen brightness. Wow!
The DIP Switch, for me, I setup as the above picture. The most useful switch for me is replace CapsLock with Ctrl key. Before I switch it ON, I cannot figure why there is such thing. I turned it ON at one day four years ago, that feeling just hit me from deep mind. I’ve realized that I barely use CapsLock for all the time, more over, it set my little finger free, no longer to touch left corner for Ctrl key.
The Fn key position, it have two Fn key beside the Space key, very convenient for many shortcuts. That’s why I prefer it to HHKB. Here is the original description of Fn key by FILCO:
The world’s first double function keyboard!
Majestouch MINILA is the Mini layout version of Majestouch and we’ve made it as compact as possible by sharing Function keys with other keys. It has the same key pitch as our famous Majestouch keyboards.
The most striking feature of MINILA is the “Double Function keys” located each side of the spacebar. We focused on less frequently used finger, the thumb, and let it work with Function keys. Just keep your thumbs busy and you get a lot of work done much easier than a normal keyboard! You can use whichever thumb you want. This keyboard can work well for anybody! Professionals, intermediate or even beginner class!Once you get used to typing on MINILA, you will not want to go back typing on normal keyboards!
[You can use MINILA even more conveniently with FN keys]
You can type cursor keys with a combination of FN key.
Pressing FN key and E/S/D/F simultaneously corresponds to ↑/←/↓/→ respectively.
With this solution, you can keep your home position and still you get to type arrows very easily.
Pressing FN key plus [:;] key simultaneously functions as backspace.
This will allow you to command backspace without changing your home position.
Those combinations will offer you a faster typing environment.
Keycap
The MINILA-Air’s keycap is what attracted me in first place. It is made by ABS, but the sense of touch is a icy feeling and smoothly. To keep that feeling I keep clean the keycap surface before it come to greasy. Then I tried to replace them by PBT keycap. After a few month, I change back to original keycap, miss that feeling.
The MINILA-R Convertible keycap is a so called ‘Patch Keycap’ made by PBT. So the touch area is a litter smaller than MINILA-Air. It doesn’t like other frosted feeling PBT stuff, keep the glossy surface from last generation. It still be greasy after years using, but much slower.
Battery
If someone around you used FILCO, then you’ve must heard of its battery life. Just load the AA batteries in, then forget it. For years I can’t believe it’s powered by AA batteries and I don’t know how it accomplish that. It seems have nothing to do with bluetooth version(1st: v3, 2nd: v5.1). In contrast, some keyboard with lithium battery pack(Niz Keyboard), only stand for few months, and I have to plugged it in frequently, finally it becomes a USB cable keyboard.
Multiple Connections
I switch devices often, it was a pain suffer. MINILA-R Convertible had done a great of that by just add 4 devices key, and moreover, it had a USB 2.0 connection!
The 1st Gen MNILA Air had some connection issue every time reconnect to a device(Chances, especially hit Cmd key during connection initialization, key comes to Alt code). The issue is gone on MINILA-R Convertible and more smoothly.
Appearance
I like simple color, my first mechanical keyboard is MINILA-Air in black, then the white. In 2020 MINILA-R Convertible came out with Sky Gray/Black/ASAGI color, the ASAGI color is a kind of blue, looks better than two. FILCO seems like mod colors. Unitl the MINILA-R Convertible anniversary, the white color finally came out(above picture). The white part like some kinde of baked paint, shining and beauty.
It was fortunate that no light in MINILA. RGB lights are totaly not necessary for keyboard.
Switch
This is the most trivial part, because many mechanical keyboard manufacturers do use the Cherry MX Switch. MINILA-R Convertible add MX SILENT Red switch, which became my favorite one. Before that is MX Red switch, but the new MINILA-R Convertible’s red switch distance of strike is clearly shorter than MINILA-Air.
These are my share review of FILCO MINILA, hope you can find your best mechanical keyboard.😀
]]>“If code paths vanish completely in the second profile, then there’s nothing to color blue.”
For me there is another issue.
The width of frame doesn’t present the REAL difference between two flame graphs.
Let’s see an example🌰.
Assume we have two folded files like below:
1 | before.folded |
To get a clear view for function changes, we can put it in a table like below:
Name | Before | After | Delta |
---|---|---|---|
func1 | 5 | 0 | -5 |
func2 | 10 | 35 | +25 |
func3 | 8 | 18 | +10 |
func4 | 25 | 0 | -25 |
func5 | 6 | 20 | +14 |
func6 | 15 | 5 | -10 |
func7 | 0 | 7 | +7 |
Total | 69 | 86 | |96| |
func1
was totally lost. Although we can use Negation to get another differential flame graph.
func3
have +10 delta and func4
have down to zero with -25 delta. But they share the SAME frame width because the diff-graph is just based on after.folded
.
I changed the way calculate diff-frame width which is based on Delta
column in the above table, cause it’s REAL differentials. Here is the screenshot.
The width of frame is based on delta, not any one of samples. So the width percentage is stand for: How much does it effects in all changes. Now, func1
shows up and func4
has outstanding optimization from the view.
The frame color is calculated by its OWN delta. So it means: How does the frame’s SELF samples(time) changes.
You can try the improved differential flame graph at my fork from the Rust🦀 version of flame graph toolkit inferno(which is 💥20x faster than Perl version).
]]>这本书虽然不厚, 但是花了很长时间才读完. 本书的作者也是是C++ STL的作者.他本人也是拥有者殿堂级的履历!
这本书印象最深的是贯穿整本书的数学历史. 对于程序员来说, 里面的数学知识可能不是非常实用,但是前几章里展现的利用数学知识进行代码性能优化的技术令人佩服. 除此之外, 这本书简直可以称作一本数学历史书, 最好奇的是作者提到的人类历史中, 有一千多年的数学空白, 几乎没有什么数学成果.
如果程序员希望从这本书中了解到什么奇技淫巧, 那可能会失望🤦♂️. 看到第十章的标题是“编程的基本概念”, 你以为他终于开始给你讲编程了,结果一上来又给你上了节历史课,真香!到最后, 把贯穿全书的素数结合其应用非对称加密算法来作为收尾, 终于有种感觉这本书没白看. 以后这就是我的数学历史参考书.
这本书翻译过来的中文名太花哨了, 英文名只是《ETF Investment Strategies》, 译者加上“大师”两个字可能会比较好卖吧. 作者是非常的务实, 介绍了ETF的方方面面, 我并不期望从这类书中能够学到什么投资金手指, 我的目的是就是扫盲. 作者把ETF的各种敞口讲得很清晰, 以及各种交易敞口适合什么样的投资者, 都可以对号入座. 还结合了很多大公司的投资案例. 看完这本书的时候, ETF已经是我定投的重仓产品了, 涵盖了不同的行业. 对于种散户来说, ETF真的是合适不过了.
]]>推荐度: 3.5分
这本书很早就躺在了电子书里, 也是最近疫情, 想起来看的. 今天刚看完. 书的一开始, 完全没搞明白什么是灰犀牛? 和大概率危机有啥关系? 后面才慢慢明白.
其实, 自己生活中有好多这样的事情在一步步逼近. 怎样才能利用这些大的趋势呢? 就像我在推特上聊到的一点:“设想一下,假如Rust这门语言像现在Java一样大规模使用起来会发生什么变化?用户体验提升,会淘汰掉性能差的产品么? 对企业来说,会节省下非常多的算力,或者说同等资源下企业或硬件可以做更多的计算.下一代编程语言的出现应该是大概率事件,可以说是正向我们冲来的灰犀牛,如何利用这个趋势?”
像这样的情况很多, 书里提到一点也是让我觉得很有意思: 对水资源保护节约相当重视的不仅有政府和公益组织, 还有大型的食品商业公司, 这些关乎他们的利益和成本. 其实如果从类似这样的角度去看待危机, 那么我相信很多人都愿意展开行动.
唯一不变的是变化, 来~拥抱个变化😂.
]]>这本书强烈推荐, 薄薄的一本, 专注在分治算法上. 从整数乘法到排序, 慢慢地引出了分治算法的核心主方法. 穿插在书中的小思考题也很简单. 边学边练, 很容易把主方法掌握. 这才知道分治算法的评估原来有这些门道.
最后几章从QuickSort开始, 揭示了为什么随机化QuickSort也有O(nlogn)
的效率. 再从这里引申到RSelect
和DSelect
算法上, 感觉非常巧妙, 直观上我以为是完全两个算法题(只能说自己太弱了😂), 没想到QuickSort的思想完全可以使用在后面的两个算法上.
而DSelect
的思路很好, 但仅仅因为需要管理额外的内存空间, 导致了被弃用, 可见算法和实际的性能工程还是有一些取舍的.
这个系列原名是《 Algorithms Illuminated》, 总共有三卷, 没看的书太多了, 等到刷完了手上的书再考虑后面两卷吧. 买书如山倒, 读书如抽丝是真的.
]]>推荐度: 2.0分
怎么说呢? 这本书几乎就没有谈任何Rust高性能的编程技巧, 反而大部分都是一些Rust方面的“最佳实践”. 比如使用Clippy、Criterion.
唯一一个印象比较深刻的就是: 不要在for循环中使用vec[]
下标索引的方式迭代访问元素, 这是其它语言经常做的事情, 而在Rust中, 下标访问会进行运行时检查, 如果越界则会panic, 这种检查会损耗性能. 更好的方式是应该用迭代器方法iter()
这个点是在书的开头前两章提到的, 然后整本书就没有再谈任何的Rust高性能编程技巧了. 倒不如《Rust Programming》来得实在. 写这篇文章的目的让大家不要踩坑了.
]]>这本书带读者从一个人力资源的视角来看奈飞文化. 书的英文名是《Powerful: Building a Culture of Freedom and Responsibility》, 不知道为什么不好好翻译.
![img](images/s29923776.jpg)这本书给我两个印象比较深刻的点.
一. 只招成年人. 这个看似简单, 实际评价的标准却因人而异. 整本书描述的文化前提就是在这样的一群人中才得以推广的文化. 认同公司的价值观, 能够有自驱力去为公司做正确的事.
二. 让人事也深入理解公司业务. 这个概念是我以前没有听说过的, 也让我想起来曾经看过一个HR为了找到好的程序员, 创建自己的GitHub账号, 开Repo, 甚至有自己的个人站. 作者这里说的不仅仅是融入技术文化, 而是参与到公司的业务中去, 深入了解公司需要什么样的人才.
除了上面两点之外的理念可以在《精益创业》和《富人思维》里看到一些类似的观点. 其实最难实践的可能就是透明度了, 在国内这种公司氛围下, 不996就算是幸福的了.
]]>推荐度: 4.0分
这本书英文名是《Think Stats》, 作者 [[美] Allen B. Downey](https://book.douban.com/search/Allen B. Downey)还写了一本是《Think Bayes》.
这本书读完一个多月, 到现在比较有印象的就是分布累计函数(CDF), 从这个角度可以发现出很多有意思的模型. 比如, 一个程序malloc
的size大小, 就很像指数分布的累积分布函数(我一开始以为是). 但实际上准确说应该是反卡方分布的累积分布函数. 这一点我也是在glibc的benchtests中发现的.
此外, 还有假设检验等等流程. 让程序员可以知道如何准确地表述出一个数据指标(虽然实际运用中不会这么去检验…).
]]>如果不算早些年读的《货币战争》, 这应该是从象牙塔里出来后读的第一本历史书了. 没有特意挑哪本书, 随意在亚马逊上看到就读了. 感受还是不一样的.
这本书前半本都感觉非常好, 从金融角度看世界的变革, 去寻找中国近代史的裂变的根因. 时间轴很清晰, 循序渐进, 看到近代中国一出不可避免的悲剧正上演. 可能和作者论文主题就是这个时代的关系, 过了这个时代, 也就是下半本书感觉不出作者想表达什么样的主题, 东捡一部分历史说说, 西挑一个人物讲讲, 时间线比较混乱. 当然我本身的金融水平和作者相比有天壤之别, 或许无法理解一些近现代金融衍生物的术语. 豆瓣上有些评论针对作者的图片引用, 由于本身是CS出身的原因, 的确发现作者引用的图片很少有版权出处说明, 不过作者的目的是达到了, 用很多图片讲述了历史性的产物.
换个角度看历史, 这才是我去了解历史的最大动力. 学校里的历史全部都是围绕着xxx主义来描述, 而学生完全不知道背后究竟发生了什么?真正的原因又是什么?所有的历史变革都逃不开金钱和权力, 亦商亦政都关乎这些. 我将来给孩子讲历史, 一定是围绕着这些实的东西变革来叙述.
历史总是惊人的相似, 有太多可以借鉴了, 从历史中找到经验和答案来给现代的自己避坑. 就像作者副标题所说的:“正视历史, 是对未来最好的馈赠.”
最后, 感谢作者李弘🙏!
]]>最刁的应该就是ripgrep了, 名称也起得很调皮: R.I.P grep
, 意图很明显了, 就是取代grep的, 且实际性能碾压grep. 作者在他的文章中列举了很多benchmark. 截取一个感受一下:
Tool | Command | Line count | Time |
---|---|---|---|
ripgrep | rg -L -u -tc -n -w '[A-Z]+_SUSPEND' | 404 | 0.079s |
ucg | ucg --type=cc -w '[A-Z]+_SUSPEND' | 390 | 0.163s |
GNU grep | egrep -R -n --include='*.c' --include='*.h' -w '[A-Z]+_SUSPEND' | 404 | 0.611s |
不过, 我用得最多的并不是rg
命令, 而是在vim中的LeaderF插件的模糊匹配, 速度也是贼快.
inferno这个工具很多人不常用, 但是对我的帮助是最大的. 几乎秒生成🔥火焰图的工具, 和原版FlameGraph相比, 速度快了18~20倍.
贴一个作者的benchmark:
1 | collapse/dtrace/1 time: [8.2767 ms 8.2817 ms 8.2878 ms] |
感受一下对比:
还在用tree
命令吗? 试试broot吧! 交互式的树形结构查找, 一目了然, 关键是毫秒级的查询响应.
dua (-> Disk Usage Analyzer) , 类似du
命令, 但是提供交互式的查看方式.
du + rust = dust. 更直观的方式显示du命令. 不过不是常规的树型结构, 而是倒树型.
dutree, du
命令+tree
命令, 提供 files-only 功能.
上面三个工具, 由于dua-cli
不包含树型等复杂的图形, 所以在统计上速度最快(以--depth 1
测试). 各有千秋, 大家可以自选.
这个bat不是我们想的BAT. 目的是取代cat
(cat with wings -> bat). 以前一直认为cat就是打印到终端, 用来查看文件而已, 直到看到了bat:
自动根据文件类型做语法高亮, 好看多了. 还有其它的命令参数, 甚至有一个和ripgrep
结合的命令: batgrep
, 带高亮地打印前者的输出.
如果要查看二进制文件内容怎么办? bat只能打印出来告诉你是 <BINARY>. 这时候需要hexyl, 非常友好的二进制查看工具, 曾经还在苦苦寻找好用GUI工具.
当然还支持很多参数, 自定义查看方式.
除了查看文件内容或者二进制数据外, 我们通常还会计算文件哈希值或者一些其它的文件常见操作, 而dtool这个工具就像一个开发者的小型瑞士军刀, 提供了开发者很多常见命令操作, 如计算哈希值、编码转换等等常见操作.
convert a string to base64
1 | $ echo -n abc | dtool s2h | dtool h2b64 |
convert a encoded timestamp to date
1 | $ echo -n 2c28e75d | dtool nd -tu32 | dtool ts2d |
convert a jpeg to base64
1 | $ cat pic.jpg | dtool b2h | dtool h2b64 |
calculate file md5
1 | $ cat pic.jpg | dtool b2h | dtool hash -a md5 |
常用的htop
命令也有一个Rust的版本, 叫ytop, 样子也是很酷炫.
曾经也是各种记ps命令的参数, 后来用htop
. 现在有了procs, 功能上虽不如htop
丰富, 但是能够查看docker容器的状态.
后面再分享两个比较fancy的工具.
lsd看名称就是替代ls
的, 加了各种icon和高亮, 需要安装nerd
字体
光看logo和名字就知道很fancy了, 以模块的哲学来定义shell终端展示.
还有另外一个叫nushell, 用终端制表的方式打印输出, 和上面几个相比就没有高亮了.
最后祭出tui-rs, 是一个Rust的终端GUI library, 提供各种Widget, 可以用来DIY自己的神器. 包括上面的ytop
也是基于tui-rs开发的.
感谢各位作者和Rust, 给大家带来的这些高效工具, 欢迎推荐👏.
开了一个仓库用来记录和存放:https://github.com/unpluggedcoder/awesome-rust-tools,不定期更新中。
]]>以assert_eq!
为例, 来解释下Macro的模式匹配:
assert_eq
是Macro的名称, 后面紧随的delimiter没有强制要求是大括号, 甚至可以是小括号或者中括号. 调用时也是一样, 下面的都是合法的:
1 | assert_eq!(gcd(6, 10), 2); |
⇒
符号左边的叫MacroMatcher
, 简单地说可以理解为pattern, 即模式匹配. 它的匹配规则是以token
为导向的, 这点和正则匹配不同(以字符为导向的匹配). 因此在pattern里加入空格或者注释都是允许的.
每个pattern由一对$name:designator
(代号)组成, 前者是代号的变量名, 后者代号指示这个变量将按哪种类型规则来匹配.
常见的有:
item
: an item, such as a function, a struct, a module, etc.block
: a block (i.e. a block of statements and/or an expression, surrounded by braces)stmt
: a statementpat
: a patternexpr
: an expressionty
: a typeident
: an identifierpath
: a path (e.g. foo
, ::std::mem::replace
, transmute::<_, int>
, …)meta
: a meta item; the things that go inside #[...]
and #![...]
attributestt
: a single token tree比较难理解的是多重匹配, 格式如下:
中间的部分和单个pattern一样, 不同的是多了一对$()
和 ,*
, *
号代表前面$(...)
内的内容会出现0或多次, 和正则一样. 而逗号,
只是一个分隔符, 甚至不要求是逗号.
编译(展开)宏的时候, 重复pattern的内容用法也和上面基本类似, 多的也只是一个$(...)*
符号, 用下面的比较好理解:
对于每一对出现对$key
和$value
, 都将用$(...)*
内的hm.insert(...);
语句替换.
有的时候不知道自己写的macro最终被扩展成什么样子, 这时候有两种方法来打印出rustc
扩展后的代码:
直接调用rustc
编译器(需要nightly版本):
1 | cargo +nightly rustc --profile=check -- -Zunstable-options --pretty=expanded |
用第三方库cargo-expand , 它有个优点就是打印出来的是格式化且带语法高亮的代码, 可读性非常好.
1 | cargo expand |
最后, 发现一篇对macro解释非常好的文章, 可以参考:
A Beginner’s Guide to Rust Macros ✨
推荐度: 4.5分
推荐度: 3.5分
这是看博多·舍费尔的第二本书, 这本书可以说是把《财务自由之路》的经验总结成了非常好理解的儿童财商培养故事.
这本书就不推荐了, 副标题是“发掘和培养孩子的优秀品格”. 感觉倒不如用这个做书名. 非常牵强的情节, 主题不再是小狗, 也不是钱, 满满的鸡汤, 干就完了.
]]>推荐分:3.5
这书名怎么说呢,字面翻译过来应该是《一位走进妓院的经济学家》😂
作者在前八章都没有谈“对冲”这个词,一直在讨论风险这个概念。作为一位经济学家,并没有大谈金融领域的对冲操作,而是列举了生活中很多高风险职业管理风险的方法,进而引申到金融领域。比如,书名中的妓院,还有狗仔队、电影行业、种马、魔术等。
个人感觉对冲并不是整本书的主题。相比于对冲操作本身,感觉作者更希望读者清楚自己的目标, 以及如何处理需要面临的风险。首先,要清楚自己的目标,不要盲目的追求高风险,这和《低风险,高回报》一书的作者一样,对大多数人来说,高风险不是什么好事,有很多低风险的选择。其次,风险有系统风险和特殊风险。前者是整个经济发展的趋势风险,后者可以理解为个体的风险因素。不同风险有不同的管理策略。再次,面对风险,理性很重要。赌徒心态是很大的忌讳。
这些是我认为作者总结出的面对风险的宏观原则,而作者在书后半部提到的对冲和保险是管理风险的手段。看到么,对冲只是手段之一,相比保险解决下跌风险的手段,对冲缩小了风险影响的同时也减少了收益的上限(切断了风险上下端)。应该合理的利用对冲,把它当成降低风险的工具,而不是冒险追求高回报的手段。
最后,任何风险管理策略都无法应对所有情况,面对不确定性不仅需要靠经验总结, 心态更重要, 让我想起:“唯一不变的就是变化”😂, 僵化的惯性思维会让自己处于被动的状态. 主动去迎接未知的未知, 面对风险的套路始终不变: 定义目标, 找到完成目标的最佳方式, 同时最小化下跌风险.
]]>推荐度: 2.5
当时在推上看到的这本书, 从标题上看很有吸引力, 一直想要读, 后来亚马逊打折, 只要RMB14.99, 现在长期是13.99.
或许期望太高, 也或许价格反应出了价值… 其实应该把副标题翻译出来: 如何用经济学来解释我们的育儿方式. 这个角度非常有意思, 怕读者以为是育儿书, 作者上来就说: 这不是一本教你如何育儿的书. 的确, 作者例举了很多实验数据来验证不同教养方式背后的动机, 所以, 一页就能讲明白的道理, 愣是摆事实讲道理说了好几页.
回到书的内容上, 首先根据对孩子的干预程度不同, 作者一上来先和读者拉通四个教养方式的共识.
这四种教养方式大致是下面这几个意思:
当然, 从上到下, 孩子的平均成绩表现(注意, 是成绩)是逐层递增. 在某些发达国家忽视型的父母可能已经触犯法律; 而大多北欧国家采取放任型; 意大利和某些宗教国偏向专断型; 中国、美国父母大多归为权威型.
作者从经济学角度的动机来说明父母采取这些不同教养方式背后的动机. 结合了不同时代、社会环境、教育政策、性别、生育政策、宗教等等各方面因素反复论证. 国外的作者大都比较严谨, 这本书和《贫穷的本质》很像, 都是用了许多不同角度的随机对照数据来说明问题.
不过这本书背后的道理比《贫穷的本质》更简单一些, 简单地说: 绝大多数父母对孩子的教养方式差异的背后动机是出于对孩子将来的顾虑. 听上去像是废话, 那换个方式说就是教育的投资回报率.
在社会不平等程度较低的北欧发达国家, 大部分人将来的就业都比较稳定, 学校也基本不考核, 老师的地位很高(优秀的人才更愿意投入到教育事业中), 因此父母都更加重视孩子的创造力、独立性而非成绩.
而在工业时代, 发达国家也曾经经历过专断型, 那时候社会阶层分明, 不努力就没有出路, 因此父母对孩子体罚, 甚至让孩子参加工作. 相比教育的投资回报率, 直接当童工对家庭更有利.
而现在的中国和美国, 通过教育可以很大程度上改变一个人的命运, 因此兴起了“直升机”父母. 盘旋在孩子上头, 各种早教、补习班都是为了将来的某个考试. 孩子的创造力和独立性被大大降低.
国外是否像书里说的那样我也不知道, 但是国内的确如此.
我的感觉是未来孩子的教育方式仍然会发生变化, 权威型教养也不再适用. 因为很多职业将被机器取代, 剩下的职业则是更具有创造性或者对教育要求门槛越高的职业. 人从生来就要不停地学习, 但学习的目的不是学习知识, 而是要尽快学习怎么做自己, 怎么在社会做一个自己想成为的人.
]]>推荐度: 4.5分
推荐理由
main
函数结束, 则程序退出, 即使仍然有线程在运行;spawn
返回的handle.join()来等待线程结束, 但是有一点不一样, Rust线程崩溃(panic)不会影响到其它线程, 因此程序可以很容易从某个错误状态下恢复.std::sync::Arc
智能指针, 并调用它的clone()
方法.std::sync::mpsc::channel()
返回一个Sender和Receiver, 分别调用send(item)
和 recv()
方法发送和接收数据, 后者会block住线程. Rust会根据上下文推断Channel操作的数据类型.
Rust的Channel比Unix的pipe机制更快, 数据移动而非拷贝. 例如发送一个String
, 实际成本只发送了三个机器字(machine word): length, capacity and pointer.
send
和recv
两个调用只会在另一个被dropped的时候失败. 换句话说就是如果Receiver被drop了, 那send
会失败, 反之亦然. 因此, 如果存在一个Sender, 那么下面这个循环recv就会在Sender销毁时正常终止结束:
1 | while let Ok(text) = receiver.recv() { |
Receiver支持迭代, 因此更优雅的写法是(二者等价):
1 | for text in receiver { |
Channel是std::sync::mpsc模块里的, 全称是multi-producer, single-consumer. 这种操作在编程中很常见. 因此Sender<T>
实现里Clone trait. 可以拷贝出多个, 然后在不同的线程里send. 当然, 由于是single-consumer, Receiver<T>
不能clone.
Rust Channel高性能的原因在于有几种不同的实现:
由于Rust Channel的高性能, 通常会引起问题的就是发送数据的速度大于Receiver处理的速度. 可以使用sync_channel
, 当发送的队列达到指定数量后, send
操作会被阻塞.
1 | use std::sync::mpsc::sync_channel; |
上面谈到的在线程间传递和共享数据的能力来自于两个trait: std::marker::Send
和 std::marker::Sync
Send
的类型可以安全地move给其它线程.Sync
的类型可以在线程间进行non-mut reference共享, 同时要求该类型的引用类型&T实现Send
trait.如下图:
Rc<String>
, 做为一个带引用计数的智能指针, 当两个线程都拥有它时, 同时对引用计数操作就会引起data race.大部分可以看文档, 和其它语言的互斥锁类似.
有一个细节值得注意:
1 | /// All threads have shared access to this big context struct. |
这个函数对waiting_list进行了修改, 而函数签名是immutable 的 &self
. 其实这里需要重新理解Rust中的mut
另一层含义.
mut
意味着排他性访问(exclusive access);这里的Mutex.lock()
可以保证不会有竞争, 因此允许在即使Mutex拿到的是shared(non-mut)情况下做exclusive(mut)操作.
另外一点, Rust的Mutex是不可重入的, 同一个线程连续两次调用lock
会引起死锁.
Poisoned Mutex(名字有些夸张, 中毒锁), 是在持有锁的线程崩溃后, Rust会将这个锁标记为中毒污染状态. 后续其它线程对它的lock
请求都会返回一个PoisonError
. 因此用lock().unwrap()
会把panic传播到另一个线程.
Condvar::notify_all()
和 Condvar::wait()
两个操作;
不同的是wait操作有些不寻常
1 | while !guard.has_data() { |
wait(guard)
, 接收一个MutexGuard
的所有权, 并返回一个新的MutexGuard
. 如果用过pthread接口的话就不会对这个感到陌生. 类似pthread_cond_wait
函数, 在wait前需要先释放这个mutex, 然后在返回前重新获取, 可以理解为Mutex授权给wait操作它.
Mutex<T>
, Atomics拥有最小化开销, 性能成本极低, 通常就是一条load或store指令. 没有任何系统调用.All images are copyrighted by original authors Jim Blandy & Jason Orendorff who wrote in the book Programming Rust.
]]>std::io
的核心是Read
和Write
两个trait.std::io::Read
的所有方法都是&mut self
, 也就是必须拥有对象的mut reference.
read
方法, 函数原型:
1 | fn read(&mut self, buf: &mut [u8]) -> Result<usize> |
buf.len()
长度的字节数据.还有其它的一些read函数:
read_to_end
: 一直读到EOF为止, 最好不要调用不信任的Reader的这个方法, 比如网络数据.read_to_string
: 读到&mut string
参数中, 前提条件要是有效的UTF-8字符, 否则会报错.read_exact
: 读指定长度, 如果数据提前结尾, 那么会报错.BufRead
是带缓冲区的Reader, 类似fread(fread一次会预读一个blocksize大小的数据块). BufRead也是类似, 它提供了一个read_line函数, 读取一行, 而实际内部调用了read, 可能预读了8k的大小, 足够满足后面几百次的read_line调用请求.
从stdin
读取. 在C中, 如果多个线程同时从stdin中读数据会造成未定义的行为. 标准的做法是加锁. Rust也是一样, 唯一的区别是加锁这个动作是Rust API自带提供的.
1 | use std::io; |
从文件读取. File::open
默认返回的File
对象只实现了Read
trait, 不带BufRead
trait. 因此需要手动创建一个BufReader
struct.
1 | use std::io::BufReader; |
Write
trait, 有三个主要的方法: write
, write_all
, flush
.BufWriter
, 如果BufWriter
对象被drop, 那么缓冲区内所有的数据会被写入底层的writer中. 如果这时候写入有错误的话会被忽略.15年到18年这四年的文章数量很少, 且呈逐年递减趋势. 但这四年里发生了很多. 后面做了一段时间Python的工作, 学了很多Python的fancy stuffs. 当时的感觉可以用下面的漫画描述:
没错, 就是飞起来的感觉. 做为一个多年的C/C++开发者, 完全被Python解放了似的. 看完了几本Python书和鲶鱼书《Learning Spark: Lightning-Fast Big Data Analysis》后, 做大数据处理、可视化、Web等等各种场景张手就来, 感觉Python要火. 按现在国内的Python状况, 算是猜中了一半. 大家都说这几年Python火主要是因为机器学习带起了节奏, 我觉得估计还是要归功于“我靠这门大数据涨薪课年入百万”的营销手段, 有点扯远了. 这四年里还学了Angular、TypeScript、JavaScript, 这里的学不是看看教程, 而是每种语言都看了一本书. 但是又感觉什么都没学到. 不是前端的料.
不仅如此, 总感觉少了点什么, 只感觉到一个字: 杂. 一年前的这时候想明白了: 少了沉淀.
一年前开始进入995的生活. 和之前的节奏完全是从天上到地下, 整个低落的状态持续了一个多月吧. 由于自己之前有的健身习惯, 所以觉得就算再没时间, 也不能放弃健身. 不能让自己生活中为数不多的多巴胺消失. 渐渐地开始找到自己的节奏, 开始管理自己的时间, 开始看书. 🤭成为更好的自己……
说来也有点不可思议, 一年看了20几本书, 比四年前的状态还多. 只不过四年前看的基本全是技术类书籍. 而现在完全不一样. 如何保持独立思考? 如何坚持学习? 是否清楚自己想要什么? 很可惜这些问题在我这么多年的受教育生涯中没有悟出来.
上面是这一年看的书单. 主要分为几类:
金融类书籍: 或许对这类书籍的好奇可以从书单的标题里找到答案. 我对这个控制了社会各个方面的专业几乎一无所知. 说来也巧, 我所处的同样也是充斥在现代社会各个角落里的一个专业: IT信息行业. 因此我觉得有必要好好了解一下这个“同类”, 毕竟它的历史比二进制bit的历史要久得多. 有一次逛书城, 看到推荐书架上《战胜一切市场的人》和《原则》两本放在一起, 才发现, 我槽, 这两本书原来这么厚.
育儿类书籍: 《夏山学校》、《非暴力沟通》和《游戏力》这三本我觉得都很好, 给我的感受都很强烈. 第一次当父母, 不懂得怎么去体会孩子的需求, 不懂得怎么去处理复杂的情况, 更不懂怎么去管理自己的情绪, 却想控制孩子的情绪. 毕竟当父母都不需要考试……
技术类书籍: 开始入坑Rust, 入门失败一次了. 至于专业的方向, 在没沉淀之前还是不立flag了, 省去了将来被再次打脸的可能. 另外, 目前在做性能工程(Performance Engineering)方面的工作, 是自己钟意的一个坑.
所有String
和str
类型都保证内部持有正确的UTF-8
格式字符串. 所有的safe操作都保证这一点, 即不会引入错误格式的UTF-8
String
的内部实现其实就是Vec<u8>
str
则是borrow的String
引用. &str
不能Clone
, 因为clone(&T)
方法需要一个返回T对象, 而str
又是unsized
的. 可以通过slice.to_owned()
获取一份重新分配的拷贝.
String::new()
返回的是一个空的字符串, 还没有分配任何堆上的内存.
不能通过单个下标访问slice的某个字符(slice[i]
), 因为UTF-8的字符是不定长的. 可以通过chars()
方法返回字符的迭代器:
1 | let parenthesized = "Rust (饂)"; |
String
实现了Add<&str>
和 AddAssign<&str>
的Trait, 因此可以很自然地用+
拼接字符串. 但是有两点要注意:
左边的操作符不能是&str
, 一定要是一个String对象. 因为会consume这个对象, 获取其所有权, 且会重复利用它的buffer, 如果capacity足够大, 就不需要额外再开辟内存.
1 | let string = "partners".to_string(); |
对右边的操作符只是borrow, 也就意味着它的内容会被拷贝到前者的buffer末尾.
String
转成其它类型需要实现std::str::FromStr
Trait. 所有的基础类型都实现了这个Trait.
其它类型转成String
有三种方法:
std::fmt::Display
trait. 所有的机器数字类型都实现了这个trait, 可以直接显示. 而像Box<T>
, Rc<T>
, Arc<T>
这类智能指针类型, 只有T实现了Display trait, 这个类型才能Dispaly.std::str::ToString
trait.如果实现了上面的Display trait, 那么Rust自动帮我们实现这个trait.std::fmt::Debug
trait. 所有标准库可访问的pub 类型都实现了这个方法. 通常如果我们是库的开发者, 对外部开放的类型也都应该实现这个trait, 方便他人打印调试.如果做数据压缩之类的, 需要访问字符串内部字节数据有两种方法:
slice.as_bytes()
: borrow其内部的Vec
, 返回&[u8]
. immutable, 且需要注意生命周期.
string.into_bytes()
: 这个成本比较低, 直接consume这个String
对象, 把内部的Vec<u8>
交出来返回, 没有任何多余的成本.
1 | pub fn into_bytes(self) -> Vec<u8> { |
同样从原始的字节也可以构造String
, 有下面几种方法, 但是都要注意错误检查:
std::str::from_utf8(v: &[u8]) -> Result<&str, Utf8Error>
: 从这里可以看到, 一是会做错误检查, 如果不是有效的UTF-8
格式字节, 则会返回Err
; 二是, 返回的&str
和&[u8]
有同样的生命周期.String::from_utf8(vec: Vec<u8>) -> Result
: 一, 同样做错误检查; 二, 参数直接捕获Vec所有权, 并把它的buffer做为String内部buffer, 省去了开辟, 非常高效;