2021/02/22
I don’t remember how many times I’ve done Tokio’s tutorial (probably more than five times), but I gave it another try over the weekend. Async/await APIs don’t stick in my head because I rarely have a chance to use them.
The current version of the tutorial is really good. I like the tutorial describes not only how but why.
Specifically, I found a blog post linked from the tutorial helpful.
I’m bad at understanding generic concepts. It took me a whole day to read the article even though it says “30 minute read” and shows plenty of code. It was worth spending time. I learnt a lot from the article.
I found the misconception 2 the most useful and I liked the misconception 10 the most.
Every language has gotchas.
Using idioms - 2021/02/15
Learning a language ever lasts. Here are two phrases I learnt over the last weekend.
- X is the new black → X is the current trend.
- It feels like preaching to the choir → Needless to say.
These phrases come from an article which describes io_uring.
I enjoyed reading the article. The article helped me to get an overview of what io_uring is trying to solve. But on the other hand I felt that using these phrases makes the article difficult to understand unnecessary for people who use English as a second language. Is it a reasonable expectation for people who want to understand technical things also need to understand these phrases?
I’d say no.
ダークモードを試す
このところ左目の飛蚊症に悩まされている。ディスプレイで文章を読むときに背景が白地だと気になる。
そういえば少し前にダークモードが流行っていたと思い出し、おもむろに OS やらスマホやらをダークモードに切り替えてみた。良い感じだ。気が散らない。
自分のブログもダークモードに対応させておこう。
Reducing Audio Glitches on Chrome for Android for my SPC player
My SNES SPC player is built on top of WebAssembly + AudioWorklet. It works well with Chrome/Firefox on my desktop/laptop but produces audio glitches with Chrome on my phone (Pixel 4a). An interesting thing is that the player doesn’t produce audio glitches when it runs with Firefox on my phone.
I had a guess. I didn’t think the cause of glitches was the player was too slow to generate samples. The player’s CPU usage was quite low on desktop/laptop (<1% according to Windows Task Manager). I thought that there might be a task scheduling problem in Chrome for Android.
I used chrome://inspect/#devices to see if my guess was right.
First, let’s take a look at how much time it took to generate audio samples.
It took <1ms for each AudioWorkletProcessor#process() call. AudioWorkletProcessor#process() asks 128 samples per call (As of Feb 2021). Since the S-SMP generates a sample at 32kHz, the AudioContext’s sampleRate was set up 32000 for the player. Generating 128 samples within 1ms seems to be fast enough (128 / 32000 = 0.04 = 4ms is the hard deadline).
Zoom out to get an overview of what’s going on.
“Idle” is dominant. I couldn’t think of my player’s bad behavior to be blocked, as it doesn’t allocate any memory and doesn’t perform any IO. These findings support my guess – there seems to be a problem in the audio scheduler of Chrome for Android.
The next step is to find a solution. I searched on crbug.com to see if anyone else had the same issue. I found https://crbug.com/1014614. It looks like a similar issue but it’s the opposite.
My interpretation of the discussion is: On a low-latency path, the audio task scheduler posts tasks to generate samples more frequently and each task is asked to generate less samples. For my player the behavior doesn’t seem to work well as intended.
Then how do I get my problem fixed? The crbug.com issue mentioned latencyHint. My player doesn’t require interaction so increasing latency seems a good compromise. Setting a large latencyHint
like 0.05 solves the problem. I don’t hear audio glitches anymore, yay!
I hope that I can get rid of the workaround in the future.
Rust: An easy way to count memory allocations
Real time waits for nothing. That’s why avoiding memory allocations while generating audio samples is important. Today I implemented a quick hack to make sure my SNES SPC player does not allocate memory after the initial setup is done.
use std::alloc::{GlobalAlloc, Layout, System};
use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
struct CheckAlloc;
static ALLOCATED: AtomicUsize = AtomicUsize::new(0);
unsafe impl GlobalAlloc for CheckAlloc {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
ALLOCATED.fetch_add(1, SeqCst);
System.alloc(layout)
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
System.dealloc(ptr, layout);
}
}
#[global_allocator]
static A: CheckAlloc = CheckAlloc;
#[test]
fn test_no_allocation_while_running() {
let mut synth = Synth::new();
synth.init();
let before_count = ALLOCATED.load(SeqCst);
synth.generate_samples(NUM_SAMPLES_TO_GENERATE);
let after_count = ALLOCATED.load(SeqCst);
assert_eq!(before_count, after_count);
}
The idea is simple. Create a custom allocator which wraps the System allocator and counts the number of allocations. After the initial setup, the number of allocations should be the same. I borrowed the idea from a blog post from redislabs.
やれることをやる - 2021/01/19
shinh さんが Message Passing に登場している!いちファンとして嬉しい。
一方で心がざわつく話題でもあった。ハイテクなこと、10 年以上プログラマとして働いているのに一度もやれたことがない。理由は自明で、単にやれる能力がないから。仕事に限らず趣味コードでも技術的にすごいものを書けたためしがない。ワナビーとしてハイテクには憧れるけれど、できないことをやろうとしてもストレスが溜まるだけなので、自分は自分のできることでほそぼそとやっていこうと言い聞かせている。
葛藤といえば最近偶然見かけたある Ph.D. thesis の個人的な振り返りが印象に残っている。冗長で繰り返しも多い。でもその分思いが詰まっていて読ませる文章だった。やれることはやったから、と誇りを持っている姿勢に共感している。(この貢献が研究と呼べるのか、という問いについて思うところはある。けれど本文をちゃんと読んでいないし、著者が解さないと思われる日本語で言及するのはフェアじゃないので止めておく)
Starting 2D sculpting
One of my 2021 resolutions is to be creative.
I’ve been actively developing my own retro game console emulators. That’s fun and I still enjoy it, but I also feel that I’m just reiterating what other people do.
Playing retro games on my emulator motivated me to draw my own pixel art. Learning to draw seems like a good activity to be creative. Around last fall, I bought a tutorial book, Pixel Logic, and took a quick look at it. It was so good. I had (still have) no idea about drawing but it gave me a nice overview on how to develop pixel art skills.
I don’t think I can draw good pixel arts like we can find in r/PixelArt. Still I think I could be able to draw icons for my private tools/softwares like the emulator.
Message Passing が面白い
Message Passing - はなしをふったりふられたりが面白い。コラムを読んでいるよう。次の話題がささやかな楽しみになるような、そんな感じ。
雑多に反応を書いてみる。バグや言語の話にも反応しようかなと思ったけれど、ちょっと重くなりそうなので別の機会があれば。
エディタ
自分は仕事では Emacs を使いそれ以外の趣味コードやブログ書きには VSCode を使っている。パンデミックが始まってすぐは VSCode の remote development でコードを書いていたが、自分が触るコードベースで使うには富豪的すぎる感じがして使うのをやめてしまった。ちょこっと変更しただけで、裏で数十 GB のメモリを使い 64 コアをぶん回しているのを見ると、なんとなくエコじゃないな、と。
Emacs 使うのやめたかったので仕事以外で Emacs を捨てられたのは大変良かった。Emacs を捨てられなかった主な要因は ripgrep + wgrep だったのだけど、 一年くらい前に入った Search Editors とそのキーバインドを設定できる変更が入ったおかげでほぼ同等のことができるようになった。
VSCode 基本的には満足しているのだが VSCode を使うようになってマウスを頻繁に使うようになってしまったのをどうにかしたいと思っている。キーボードだけで操作を完結させたいのだけど、まだやり方を模索している。
Vim と Emacs はたまにネタにされるけれど、Google トレンドを見れば両者の趨勢は 10 年ぐらい前には決まっているのが分かる。Vim はその独自の価値から今後も一定のユーザが居続けるだろうけど、 Emacs は(ずっと生き残るだろうけれど)新しい人は入ってこないだろうし利用の推奨もされないだろうな、と自分は理解している。
読み物
仕事で親しんでいるのもあって自分はやっぱり Applications のセクションに興味が向く。RAIL が参照されているけれど、以後、さまざまな試行錯誤を経て今は Web Vitals という指標を掲げている。Web Vitals ユーザ視点でレイテンシに着目した指標になっていて、かつ計測可能という点で良い指標なんじゃないかと思っている。記事の推奨レイテンシの上限と FID の目安が共に 100 ms になっているのは偶然じゃないんだろうな、と思った。
ディスプレイの遅延については、表示遅延と応答速度って違うんだよ、と解説している記事をふと思い出した。自分には差を認識できる気がしないが、ゲーマーの人たちにはある程度影響するのかもしれない。
以前の版を電子版で購入して読んだ記憶がある。Jonathan Levin の本は編集を通していればもっと良い本になるんじゃないかな。ちょっと記憶があやふやだけど、初版とかは出版社経由で出していたはずで、その版は良く書けていた印象がある。
本の付録?としていろんなツールが提供されていて、特に procexp は以前メモリ周りの仕事をしているときに参考にさせてもらった。MacOS の memory pressure handing が workaround だらけで辛かった記憶が思い出される。
みなさん読んでいて感想もそれぞれ微妙に違うのが面白い。自分は最初のいくつかの章を読んで止まっているので、ざっと目を通しておきたい。
こういうプログラマが書いたコラム的な文書を見かける機会が減った気がする。
技術の話題を中心にしつつ、なんらかの情緒を感じられる、心が乗っている文章が自分は好きなんだな、と思った。
ふと思い出したようにBK ノートを読み直す。
2021年 正月休み
帰省することが叶わなかったので令和三年の年明けは自宅でのんびりと過ごす。正月に帰省しなかったのは人生で初めてだったのでやや寂しい。
近所のスーパーで正月っぽい食べ物を買ってきて雰囲気を出す。黒豆は自分で煮てみたのだけど、ちゃんと美味しく煮ることができた。
技術書典 10 で同人誌を二冊買ったのでざっと目を通した。
一冊目は「DAW・シーケンサーエンジンを支える技術」の第二版。音源のエミュレーションをするのに役立つ知識があるかな、と思って買ってみた。ニッチな話題を扱っているけど、初めに対象読者が明確に定義されているから書き手と読み手の期待値がずれることはなさそう。自分は VST などのプラグインどころか DAW も触ったことがないので明らかに対象読者ではなかった。実際出てくる固有名詞がほとんど分からない、といった感じだったけれど、概念的なところは意外と理解できる部分が多かった。エミュレータを実装する過程で苦労した部分と本質的に重なる部分が多かったからかもしれない。逆に言えば、ある程度コードを書くなりして苦労した経験がないと本書の内容を読み進めるのは難しい気もする。全体的には知らない世界への俯瞰的な見方を与えてくれた一冊で満足度が高かった。
二冊目は「3D グラフィクス API Vulkan を出来るだけやさしく解説する本」。こちらは頑張って中ほどまで読み進めたが途中で止まってしまっている。これは自分の、Vulkan から 3D グラフィックスに入門しよう、という見通しが甘かっただけで、本書に非はない。むしろ本書は良く書かれていて、予備知識をあまり必要としないし、個々の API がなぜ存在するのかといったあたりも軽く触れられていたりする。この手の本、とくに和書は「どうやって」は説明するけど「なぜ」を説明しない本が多いのだけど、この本にはそういった不満を覚えなかった。一方 Vulkan に対しては複雑な印象を持った。自分は API の本質を、抽象化を通して「出来ることを制限すること」で「有用な概念を提供すること」だと思っている。Vulkan はそれを諦めているように思えてしまった。低レベルな API なのは過去の反省を踏まえた意図的なものであると本書の冒頭にも説明があるし、実際その通りなのかもしれない、とは感じたが、自分みたいに 3D グラフィクス全く分からない勢としては素直に OpenGL を勉強したほうがいい気がした。
2020年の振り返り
世の中的には大変な一年だった。個人的にも停滞したなあ、というぼんやりとした感覚が残る一年だった。12 月に入ってからは原因が分からない無気力状態に陥ってしまい、何もできなかったのもあって余計にそう感じるのかもしれない。
趣味コーディング
相変わらず晩酌をしながらコードを書く時間が一番楽しい。すぐに気が散ってしまって込み入った思考ができないことが多く、今年は思ったような出力ができなかった。それでも可処分時間の大部分をコードを書くのに使っているのでやったことをつらつらと書いてみる。
今年は主に NES エミュレータの完成度を上げていた。対応マッパーを増やしたり、VRC6とかの拡張音源をサポートしたりしていた。ステートセーブやエミュレーション速度変更などの機能も実装したので普通に遊べるレベルのものができた。自作のエミュレータで FF3 や悪魔城伝説をクリアできたのは良い思い出になった。副作用としてスーパーポテト秋葉原店に足繁く通うようになった。
minimp3 を Emscripten 依存無しで Wasm 化したりもしていた。これを使ってポッドキャスト再生 Web アプリを作ろうと思っていたけれど、作り始める前に WebCodecs が使えるようになってお役御免になるかもしれない。
去年作った Chrome Mojo IDL の Language Server を書き直して公開した。時間が取れたら async/await ベースで書き直すのと、最近追加された Semantic Tokens 対応をしたい。
ここ 1,2 か月はスーパーファミコンの音源を AudioWorklet として実装している。全く動かない日々が続いてしんどかったけれど、ようやくある程度音が出るようになった。Desktop PWA 化して作業中の BGM プレーヤとして使えるようにしたい。
最近の趣味コードはほとんど Rust で書いていて、だいぶ手になじんできた感じがある。
読書
去年の振り返りで読書量を増やしたいと書いていたけれど、今年もそんなに読めなかった。特に物語を読む時間をとるようにしたいなあ。
Snippets
日々の記録を取るのは継続できている。こうやって振り返りを書くときに便利だ。来年以降も続けていきたい。
仕事
三月の中旬ぐらいまでは会社へ行っていた。それ以後はずっと家からリモートワークしている。朝、昼、夕の決まった時間に散歩をするのを継続したので生活のリズムを保つことができた。これは良く機能したと思う。パッチ数や書いた design document の数といった出力だけみると生産性に大きな変化は無かったようだ。最初はかなり抵抗があったけれど、時間を柔軟に使えるし家から働くのもそんなに悪くないかもしれないと最近は思っている。ただでもオフィスが開いたら自分は出社するかな。家にずっといると retreat できる場所がなくて、それが結構ストレスになっている。年末に燃え尽きたのはこれが原因かもしれない。
仕事のやり方も変えていかないといけないなと感じているがこちらは上手くいっていない。これまでみたくオフラインでの議論は難しい。質問や分からないことがあったら、チャットを飛ばして即興の VC を始める、ぐらいのフットワークの軽さが必要だ。来年はここを改善したい。
春から夏にかけてインターンのホストをした。時間を無限に吸われて大変だったが、とても良い経験だった。自分のたどたどしい英語をインターンの学生さんが根気よく聞いてくれたおかげで、技術的に込み入った内容も少し説明できるようになってきた。付き合わせてしまった学生さんには申し訳ない気持ちもあるけれど、自分も学生さんの成長に少しは手助けできたかな、とも思っている。
プロジェクトとしては service workers のストレージ部分を out of process 化する、というのをずっとやっていた。このプロジェクトに対して自分は銀座線の改築みたいな感覚を持っている。自明で小さな変更を少しづつ加えていきつつ、最終的には大きな改修をする、といった感じ。実践できているかどうかは分からないけれど。年内に終わらせたかったが来年に持ち越してしまった。
英語
仕事で継続して使うので最低限のレベルは維持している。意思疎通するという意味では去年より上手くなったと思う。一方、昔覚えたけどあまり使わない単語や文法を忘れているのを実感することが多くなった。純粋な英語力は下がりつつあるけど運用や workaround でカバーしている感じ。
思えば 2018 年に通っていた英会話のレッスンは英語力向上にすごく役立った。あのときの反復練習で得た蓄積でやりくりしている実感がある。英会話レッスン、再開しようと思いつつ、腰が重くて再開できていない。
散歩
去年の秋ぐらいに Fitbit を買ったので記録が取れるようになった。今年は 800 万歩ぐらい歩いたらしい。人込みを避けた結果、早朝に長距離歩くようになった。
体型を維持しなければという強迫観念が強すぎるきらいがあるので少し歩く距離を減らそうと思っている。
来年の抱負
昨年と同じく細々としたものはやっているものの、難しいことをあんまりやれなかった一年だった。来年は難しいことを理解して出力することに時間を充てたい。