Spinach Forest

November, 2018

/ Retiring   / NM #20 - Bazel   / MN #19 Looking at Bayer   / 煙に追われ南へ   / MN #18 - Saving RAW10   / MN #17 - Shutter Button   / MN #16 - Debugging ZSL Continues   / MN #15 - Debugging Raw ZSL   / Chaos Engineering and O'Reilly   / Book: Building Evolutionary Architectures   / NM #14 - ZSL   / MN #13 - Debugging   / MN #12 - Chores   / 空気清浄機   / MN #11 - Hardening   / MN #10 - Preview Aspect Ratio   / MN #9 - Preview   / MN #8 - Reviewing RxJava   / Toolbox App: Easily Manage JetBrains Product Updates   / MN #7 - Code   / MN #6 - Podcast Editing   / Dying Object and RxJava   / MN #5 - Code   / MN #4 - Code   / Dell Precision 5530   / MN #3 - Android App Stub   / MN #2 - Podcast Editing Continues   / logd   / MN #1   / Gaining Weight   / Understanding Android Surface   / 朝型化を考える   / What to Talk: Odd Number Episode   / ... 

Retiring

|

社内で探しものをしていたら、以前おなじチームだったプログラマが・・・リタイアしていた!FIRE とかではなく、もうちょっと普通なかんじの引退だと思われる。すなわちけっこうな年齢(推定)だった。奇妙な CPU のコンパイラの仕事をしていたことすらある、といった経歴が LinkedIn に載っていた記憶がある。コンパイラの仕事をするのが割と普通だった時代の生き残り。

そのチームは買収で入ってきた人が多く、この人もその一人だった。すごく生産性が高いというわけではなかったが、humble かつ funny で good to work with であった。彼と同じ年齢の自分には全く生産性を期待していない身として、せめて easy to work with でありたいものだと思う。

プログラマとして職業人生を全うする様を目撃する感慨って、あるよな。

NM #20 - Bazel

05:08. 一日風邪で休んだ。まだ喉が痛いが、風邪の後の喉の不調はいつも一週間くらい続くのでやむなし。

今日は C++ 環境づくり。すなわち Bazel で C++ およびなんらかの依存 (libpng とか?) をビルドできるようにする。そして png でなんか保存できるとこまでいけばなおよし。

なぜ Bazel か、というと今更 CMake に限らず C++ のビルド環境づくりとかいまいちやる気が起きないため。


BUILD を色々試しているうちに終了・・・。

  • third_party のコードを使うのは色々うんざりだが (Bazel に限った話ではなく C/C++ でなんかやる時の常として)、TensorFlow が山のように依存を持っているのでこいつらに使いたいものが含まれていればそれをコピーしてくればよい。というか何らかの Bazel-based なプロジェクトから必要な BUILD のを探してきて使うのがよい。自分でサードパーティ用に BUILD を書いてあげるのは茨すぎ。
  • コピーして持ってくる際、External dependencies の名前 (@  で始まるやつら) は気分で変えないほうが良い。なぜなら依存したライブラリが Bazel を使っている時、その依存先の BUILD ファイルは名前空間を共有しており、特定の名前で external dependency を参照する場合があるからである。なんかすごい適当につけられたっぽい名前であっても(じっさい適当につけたと思われるが)グローバルな識別子のように振る舞う。たとえば AbseilGoogletest を参照したりする。そういう入れ子参照がどちらも Bazel を使うケースはレアな気もするけれど、一方でわざわざ地雷を仕込む必要もない。
  • 一方で、色々うんざりとはいえ third_party ライブラリの使い方をビルドシステムとして既定しているのはよい気もする。他人の成果をコピペできるので。そういう意味で Bazel は third party 用の BUILD ファイルをホストすべきだな。DefinitelyTyped みたいなかんじで。
  • それにしても色々 undocumented assumptions がある気がして、他人に進める気にはならないなあ・・・。会社の中ならコードサーチで見様見真似すればなんとなく問題を解決できるが、GitHub の世界ではそうもいかない。(GitHub が悪いという話ではなく Bazel のエコシステムがしょぼいため。) 真面目に C++ やりたい人はおとなしく CMake あたりを受け入れるのが良いのではないかね。外部ライブラリを使うコンベンションみたいのも決められてるっぽいし。
  • CMake も Bazel もうんざりだけれど、それは CMake や Bazel のせいではなくC/C++ のせいなので文句はいうまいよ。

 

MN #19 Looking at Bayer

04:42. 引き続き風邪気味。仕事休むかなあ・・・。寝てろという話はあるが目が覚めてしまったのだった。

昨日ダンプした画像(のはずの何か)の中身を目で見たい。Numpy でも使うかな。

がしかし Ubuntu 18.04 にして以来 pythonbrew などの Python 環境を作っていない!今は深入りしたくないので Anaconda でも使っておこう・・・。

np.fromfile() はなんのメタデータもなしにバイナリの配列を読めて便利だね・・・。

imshow() したが予想どおりわけのわからないゴミが表示された。画像の面影すらない。コードをにらみ直しましょう・・・。

ビットシフトの向きを間違えていた。直したら絵が見えたぞ!

first-raw10

ハローにゃんこ!

  • 16 bit のうち 10 bit しか使ってないので暗い。
  • パターンが見えるのは Bayer image だから、と思われる。


この先やりたいのは、Twitter でみかけた ゼロから作るRAW現像 みたいな作業、の簡易版。ただ同じことをしても仕方がないというか自分の需要とは合わないな。

  • デモザイクは実装してみたい。教養として。
  • 簡単なホワイトバランスも実装してみたい。同じく教養として。
  • レンズの補正は・・・あまり盛り上がらないのでパス。
  • Python ではなくて C++ でアルゴリズムを書きたい。結局 CG/CV の人々は C++ で仕事してるっぽいので自分もそのへんの DSL としての C++ に馴染んでおきたい。

というかんじで次のステップは C++ の作業環境づくりです。


ところでこの RAW 現像の記事書いてるひと、妙に詳しいけどどういう経歴なのだろうなあ・・・。とおもったら LinkedIn のレジュメがリンクされていた・・・え、TI, Intel そんで今は Google / Mountain View?

めちゃ専門家でいらっしゃいました。はい。

煙に追われ南へ

|

山火事の煙による空気汚染は、結局雨が降るまで二週間続いた。一週間たったあたりで、こりゃ Thanksgiving も煙かもな、どこか行こうという決断がくだり、ゆこっぷ(おくさん)がみつけてきたのが Cambria という村。南に車で三時間くらい下ったところで、そこまでいくと大気汚染もだいぶマシそうだったため。Seattle や Hawaii も候補にあがったけど飛行機が高いのでパスとなった。

旅行の前夜に雨が振り煙は収束。とはいえ宿も取ったことだしせっかくだからでかけようと HW1  を下り南へ。夕方到着してレストランを探すも、ほとんどみんなしまっている。Thanksgiving にレストランがしまってしまうとか、ほんとにあるのか。自分の近所だとそうはいってもファストフード店などそれなりに空いているので油断していた。

なんとか空いているレストランに入ると、似たような身の上の家族、すなわち Bay Area から避難してきた Asian、がふた組。インド人と中国人。大変ですねーはははなどと挨拶する。

夜、宿の暖房を調節しわすれて風邪をひく。

翌日は Cambria はビーチが目玉だけれど雨のため宿でゴロゴロしたり 20 世紀の歴史遺産 Hearst Castle に行ってみたり。夜は少し南の Morro Bay まで下って寿司を食べてみる。日本人らしき男性が切り盛りする小さな店だった。このひと、なんで西海岸の片田舎で寿司屋しようとおもったのだろうな・・・。でも田舎の港町で寿司屋を持つのにはロマンがある気もする。

翌日帰宅。

MN #18 - Saving RAW10

04:56. 旅行から戻ってきた。宿の空調をしくじって風邪を引いてしまったため朝寝して回復しよう・・・と思ったものの普通に目が覚めた。

今日は RAW10 をファイルに保存。なのだけど、加工する前には 16bit にしたい。RAW10 で保存しつつ オフラインで 16 bit に re-pack してもいいけれど、そのコードを何で書くかという問題がある。Python は色々厳しい。Unsigned type が欲しいから Java はイヤだけど、かといってこのためだけに Golang やら C++ とかもなー。などと考えていたがふと Kotlin 1.3 には実験的に unsigned type が入っていたのを思い出す。on-device で 16 ビットにしてしまうのがラクかもしらん。Experimental feature に乗っかるのはやや怖いが、coroutine とかと比べるとそんなに moving parts もないだろうし大丈夫でしょう。

ファイルフォーマット。生の配列をバリっと保存してもよいけれど、できれば何らかのコンテナに入れてあげたい。PNG? あるいは TIFF とかなのだろうか。あと Android native のエンコーダは Bitmap クラスを使うが、これは packed RGB なんでだめ。Third party かつ pure java なエンコーダが必要。

探してみると・・・ないね。PNGJ というやつが近いけれど、Google Code shutdown あたりで朽ち果ててしまった模様。おそらく libpng を NDK で使うのが正解なのだろうけれど、いま NDK には寄り道したくないのでバイト列をガっと書き出すことにしましょう。


とりあえず何かは書けた・・・が、中身を見てみるのはまた明日。

Kotlin unsigned arithmetic types について:

  • Bit shift が unsigned short や unsigned byte に定義されていない!が、under consideration らしい。これが experimental というやつか・・・
  • そんじゃUInt つかっとくか、とうっかり byte の値を toUInt() とでもしようものながら negative number が UInt として round してしまうので、toUByte().toUInt() と書きましょう。
  • OutputStream に write(UByte) とかないので若干残念。nio の ByteBuffer も signed だし、このへん暇な若者とかの力で全部 unsigned ready になってくれないとバイトいじり言語としては今ひとつなかんじ。Java の世界でやむをえず unsigned したい今回のようなケースにはまあなあ便利だけれど。

MN #17 - Shutter Button

05:17. 子供寝かしつけを手伝うなど前夜が distruptive だったため。そして今日から二泊3日で南の方にでかけるため早めに切り上げて荷造りしないとな。山火事の大気汚染、Thanksgiving などで生活が不順になりがち。まあやむなし。射撃しつつ前進。

今日は実験のゴミを削除したのちシャッターボタンをつけて...おわりくらいかな。

MN #16 - Debugging ZSL Continues

04:55. 家庭の事情で少し就寝が遅れ、結果として少し寝坊。

今日は ZSL フレームレート出ない問題をなんとかしたい。

TEMPLATE_ZERO_SHUTTER_LAG というのを使ってみたがやはり 15fps しかでない。

Systrace をとる。cameraserver の getBuffer() が遅い。しかしこれは単に Surface で同期をして待っているから、というだけの話に思える。つまりここから先(HAL)が遅い . Camera HAL のぷロセスをみると、CAM_PREVIEW というスレッドと CAM_RAW というスレッドが別々にあるなー。なにしてるのかしらんが、なんとなく変じゃね?こういうもんだっけ?

2つのストリームの間に不整合がある? PixelFormat... は SurfaceView のデフォルトは OPAQUE だと書いてるので問題ないはず。Aspect ratio... も特に疑わしくないなあ・・・。

AOSP に古い Camera2 アプリのコードがあり、そいつが ZSL してる気配。そのコードから CaptureRequest のパラメタをコピーしてみる・・・がだめ。

Preview ストリームだけの Systrace を見ると、なんか見慣れた感じになるなあ。そしてとにかく HAL が遅いせいなのはたしかなようである。

Systrace の sched をつけわすれていた。つけてみると... わーお CAM_RAW スレッド super busy なんですけど。なにしてんのこれ。CAM_PREVIEWの圧倒的ヒマさを踏まえるになにかよからぬことが起きてるなー・・・。

ImageFormat#RAW_SENSOR がダメなのかなと RAW_PRIVATE にしてみたら・・・直った!まじかー。しかし RAW_PRIVATE 中身わからんからだめじゃん。と RAW10 を試すと、これも 30fps でるな。つまり RAW10 を使えということか・・・。しかし DngCreator は RAW_SENSOR しか受け付けない。ということは DNG を使いたいなら ZSL できなくね?なんで Google Camera は大丈夫の?というと、HDR+ が RAW10 なり RAW_PRIVATE なりをマージして RAW_SENSOR 相当の結果を返してくれるからなのだろうなあ。ZSL を実装するの、思ったより大変なのだね。


自分はオフラインで簡単な RAW の hello work をしたいとおもっていただけで、別に burst のマージとかをやりたいわけではない。ので別に ZSL でなくても良いといえば良い。一方で DNG を使わず RAW10 の画像を適当にベタっとファイルに書き出してそれをオフラインで加工してもよい。

あまり深く考えてなかったけど DNG をよむのには libraw/rawpy を使う必要があり、若干かったるそうではある。ただ DNG を書き出す hello をしておきたい気分もある。

まあ DNG は深入りすると手間取りそうだし、今はとりあえず RAW10 をダンプする路線で先にすすむとしよう。DNG しゅつ力はそのうち気が向いたら試す。ZSL のコードは、RAW_SENSOR にすると遅くなっちゃうけどせっかくなんで使いますかね。

といったところでつづきは明日。

MN #15 - Debugging Raw ZSL

04:45. 寝起きにうっかりインターネットをしてしまうと遅くなるのだった.

今日はなぜ RAW ストリームが動かないのかを調べる。やれやれ。Log をみてもまったく no clue なので サンプルを睨んで差分探しかな。


動いた!しかしやはり遅い。この SO の回答によれば RAW は吸い上げる速度を調整する必要があるげ。ふーん。つまり preview を setRepeatingRequest() しつつ RAW は適当に best effort で capture() しろということなのかな?まあ試してみるか・・・。

ところでこの SO の答え、中の人が書いてるな。質が別格。エライ。Android の中の人はどんどん SO してほしいもんです。こういう時に守秘義務とかがめんどくさくなりにくいのがオープンソースの素晴らしいところであるよ。まあカメラは HAL の下が広大なので実際は割と守秘義務あるだろうけれども。

フルサイズの request を分離してみたが・・・これだと preview 23fps, フルサイズ 6fps とかで、つまり 30fps のうちとこどろころでフルサイズになっている、というだけだな。そしてよく考えると当たり前だけどフルサイズの request によって preview の repeating request が一時的にとまってしまうね。これだと ZSL になってなくね?やはり repeating request が 30fps で吸い出してくれないと ZSL できない気がするんだけど、どうなってんの。自分の理解してないトリックがあるなあ・・・。

Chaos Engineering and O'Reilly

Chaos Engineering [Book]

Netflix の人が書いたChaos Engineering の本、昔は無料ダウンロードできたらしいが今は Safari 会員限定公開になっている。まじかよ。無料じゃなくてもいいけど Safari subscdription したくないんですけど。自分も勤務先がアレなので人のことを言えた筋ではないけれども、O'Reilly えげつないことするなあ。またひとつがっかりが深まったわ・・・。Netflix もえらい迷惑を被ったもんだね。

追記

ACM 会員は Safari にアクセスでき、ブラウザか彼らのできの悪いアプリで読める。これで我慢するか・・・。Sigh. 

Book: Building Evolutionary Architectures

|

Building Evolutionary Architectures: Support Constant Change

もうすぐ Refactoring 2ed. がでるという宣伝 Podcast のなかで Martin Fowler が言及していた Thoughtworks 勢の薄い本。

おまえらアーキテクチャレベルでもばんばんリファクタリングしていけよ、そのためには decoupling が重要だから Microservices にしとくといいよ、あとガンガン変えると非機能要件とかが失われがちだからテストとかモニタリングとか audit とか review とかで監視しとこうな (これを fit function と呼び、本書のコアコンセプトになっている)、ただ人手でチェックすると厳しいからなるべく自動化して CI/CD の pipeline に載せような、というような話だった。

読み始めたもののあまり興味がわかず、ぱらぱらっと読んで終わりにしてしまった。一つにはあまり新しい話がなく盛り上がらない。Thoughtworks シリーズで Refactoring, Continuous Delivery, Refactoring DatabasesNoSQL Distilled, Building Microservices とか色々あるのをぱらぱらっとつまみ食い用にまとめなおしたかんじがする。まあいいんだけど、もっと内容を絞ってそのぶん踏み込んだ知見を見せてほしい感じがする。

あとは例に出てくるのが Netflix だの GitHub だの Twitter だのの事例で、日経ナントカがエンタープライズのおっさん向けにインターネット・カンパニーの華々しい話をしてレガシー大変だろうけどおまえらもがんばれ、みたいに説教してる的な空気を感じてしまう。別に日経に悪意があるわけではないんだけれども、ふだんから HN とかを読んでる身としては新味がない。本書はたとえば DBA という職種をステレオタイプ化してディスっている説があるのだが、そんな SIer ディスってる退職ブログみたいな話されてもなあ・・・。同じエンタープライズ路線でも DDD とかは独自性や誇り的なものがあったじゃん。

あとは完全に個人的な話として、自分はもうアーキテクチャとか興味ないんだな、と思い知らされた。でかいプロジェクトの下っ端、アーキテクチャに口出す余地なし。ましてや組織がどうとか完全に out of control. たとえば Inverse Conway Maneuver, 最初にこの手の話を聞いたのは Twitter の microservices 移行の話だったと記憶しているが、その頃は零細でお山の大将をしていたときの感覚が残っていたので一定程度共感があった。今はもうない。

これは悲しいことだが、様々な選択の結果なので仕方ない。自分にとって actionable であったり、そうでなくてももうちょっと getting excited なものを中心に読んでいくほうがいいね。アーキテクチャとかは、こうしてたまにつまみ食いするくらいでいいでしょう。

同じアーキテクチャの話でも何年か前に読んだ Hadoop Application Architecture は一定程度楽しめたので、やはり乗っている要素技術のかっこよさは大事な気がする。RDBMS の trigger で microservices に migrate だよ、とかいわれても外野的な盛り上がりがゼロすぎる。実務家にはいいのかもだけどね。


そういえばこのあと関連する Accelerate という本も聴いた。こっちは割とよかった。いろいろな規模の会社で働く人々を相手にサーベイをしたら、やっぱし devops 的なノリで CI/CD しないと厳しいということがわかりました、という内容。まあそうっすね、という内容だが、説教ではなく調査をベースにしているのがよい。

NM #14 - ZSL

4:38. 煙のせいで外出できず、外出できないのみならずジムとか air purifier のない環境も空気が悪くてキツイため完全在宅で運動不足、脳内麻薬不足。つらい。

今日は写真をフルサイズのファイルに保存するターン。最終的には RAW にしたいがまずは JPEG から。


JPEG で ZSL してみたらフレームレートがガタっと落ちてしまった。そんじゃRAWにしてみっか・・・とおもうも動かねー。わからん。時間切れ。なんなの・・・。

MN #13 - Debugging

05:20. 昨日夜ふかししてしまったため... 本来ならスタバに行きたいが、空気がアレすぎて外出意欲なし。

バグがあるのでデバッグ。


なおった。

どうでもいいランダムな感想:

  • Git vs Hg: もやはどっちでもいい。というか Git の方がいいと思うが適応してしまうと Hg も大丈夫。しかし言ったり来たりするのがしんどい。
  • go fmt 的な code prettifier ほしい。そういうところに気を取られたくないのもあるけれど、それ以上に手動で小さな変更を revert した場合に一切の diff をなくせるという利点がある。仕事だと誰かがツールを整備してくれているのにコミット前に何らかのコマンドを叩くだけなのだが、趣味はそういうの自分で整備しないとならず、自分は今のところやりかたわかってないのだよな。これを使うとよさそうだけど、保留。そういえば CI もいちおうセットアップしたいねー・・・。
  • Viewfinder を表示するだけのコードなのでなんの工夫もしてないのに速い。しかし自社製品もガチガチに色々な機能が詰め込んである割に改めて試すとまあまあ速いね。

写真とれるようにするかなー。

 

MN #12 - Chores

5:25. 土曜日につき...

家事雑用がたまっているのでそれらをやりますわ。

空気清浄機

|

先週の wildwire による大気汚染をうけ、月曜に注文し、昨日の木曜に届いた。山火事は先週の金曜。もっと早く注文すべきだったし、届くのが木曜じゃあ火事も収まって次の wildfire 事故まで出番なしかな・・・などと思っていたらその後も悪化が進み各種教育機関が休校しだす有様。

サンフランシスコに本社のある高級空気清浄機の会社、少し前まではベイエリアの住人に対し即日配達送料無料、本社オフィスでの受取も可、と宣伝しており、今日みたら品切れで入荷まで一週間待ちとなっていた。自分たちの買った Wirecutter 推薦モデルも品切れ。この手の業者は儲かってることであろう。

空気清浄機、電源をいれると高い汚染度を示す赤いランプが灯り、しばらくまわしているうちに収まったが数秒窓を開けたらふたたび真っ赤に戻った。いかにも汚染されてる風情。

MN #11 - Hardening

4:39

昨日は案の定 viewfinder の調整だけで終わってしまった。今日はリソースの開放をさぼってるのを直して、それができたら実際に写真とるのに進みたい所存。

MN #10 - Preview Aspect Ratio

4:45.

Preview の aspect ratio が壊れているのを直す。今日はそこまでとして、次のステップは・・・写真をとる。だな。

MN #9 - Preview

|

04:32

微妙に理解できてない RxJava の挙動を確認しつつ Hello Camera2 に戻りつつ。


ようやく Preview が表示された。5 日もかかってしまった・・・。Camera2 API すごい詳しくなってる一方で Rx 素人すぎてちょう手こずってしまった。まあそんなもんです。Preview 表示されたのはういいけどタップして focus をあわせることも exposure の調整もできない。カメラ作るの割と大変。(知ってた。)

まあそうした機能は自分の hello work には必要ないのでスキップするとして、最低限もうちょっとロバストにしておかないとなあ。そして preview だしたあとに何するか深く考えてなかったので考えねばならぬ。

MN #8 - Reviewing RxJava

4:40.

コードかき。RxJava の挙動を正しく理解してない上に割と基本的なレベルで使い方を間違えている気がしてきたのでそのへんの調査と hello work に寄り道。


Hello project を用意するのは正解だな。細かい API の挙動、アプリと切り離して試せるほうがいいからね。

Toolbox App: Easily Manage JetBrains Product Updates

|

via Toolbox App: Easily Manage JetBrains Product Updates

JetBrain 製品のアップデータ。いいかも・・・と思ったが Android Studio がないな。Google 製品なので完全に言いがかりとわかりつつ、あいつのアップデートも割とかったるいので混ぜてあげて欲しい。App Store / Package Manager の類から撒くのが本来は正解なんだろうけれども。

MN #7 - Code

|

04:42. 就寝前の「翌朝起きたらやることを書き出す」というステップを忘れると睡魔や暗闇に押されがち。立て込んでいてもそういう ritual を欠かさないのが重要、なのかも。朝のコーヒー淹れをスキップし前日のコーヒーをレンチンすることでキャッチアップ。コーヒーをレンチンするの、人生を踏み外してる感じがして良い。

Podcast 編集は昨日終わらせておいたのでコード書き。

MN #6 - Podcast Editing

|

5:50. 不穏な疲れを感じたので寝坊しておいた。土曜だし、本来ならスタバにでも行きたいところだけれど、北の方の山火事による大気汚染がひどく外出したくないかんじなため諦め。まあそういう日もあります。

仕事日記がおわりしだい Podcast 編集。今週は一本だけなのでちょっとラクなはず。

 

Dying Object and RxJava

何らかの事情によって死んでしまうオブジェクトを Rx の世界で表現したい。

というと、こんなかんじか:

class FragileThingy {
  // なんとかして実装する. 死ぬ時に onError() を呼ぶ.
  val Maybe<Unit> maybeFail
}

Maybe<Error>  とかにして onSuccess() でいいかと最初はおもったが、そうするとハンドルしてないエラーが握りつぶされてしまうからだめだね。

しかし SurfaceHolder.Callback とか CameraDevice.StateCallback とか雑に生やされたコールバックは寿命を真面目に考えた世界とギャップがありすぎてマップするのが辛い。オブジェクトを(非同期に)構築するのに失敗するのと、構築したあとにエラーがおこるのは別にしといてくれや・・・。

追記

Maybe じゃなくて Completable だな。

MN #5 - Code

|

4:39. 目覚ましを付け忘れたが膀胱の力で奇跡的に目が覚めた。

日中の眠気。さほどではない。ランチの後に若干眠いが、15 分くらいうとうとするとだいたい大丈夫。午後ずっと眠いかんじではない。一方で寝不足ギリギリ手前だなとも思う。今はふつうにコードを書く仕事だからいいけど、これがバグのトリアージとかだとやばいかもしれない。まあ、そのときが来ればわかるでしょう。

もう一つの懸念は免疫力の低下すなわち風邪リスク。体調には注意を払い、不穏な気配があったら開始を1時間遅らせるなりすぱっと二時間余計に寝るなどして回復を最優先したい。

あと寝る前にスクリーンをみるとどうしても就寝が遅れがち。家事雑用などの都合でどうしても必要な場合を除き、夜のスクリーン利用はやめて紙の本などを眺めつつ寝るくらいにすべきに思える。

仕事日記をつけて hello work つづき。


コードを書いている限りは Linux も可愛いやつだよなあ。仕事で Linux workstation に不満がないのは、作業がコードを書くかブラウザでなんかしてるかの二択だからだね。

MN #4 - Code

|

4:33

今日は引き続きコードを書く。前に、仕事日記をつける。


  • この Camera2Basic というサンプルは不当に Camera2 を難しく見せているよなあ・・・。

Dell Precision 5530

速くで画面でかくてそこそこ薄くてインストールが地雷じゃない Linux laptop ないかなーと眺めていたら Dell Precision 5530 が目についた。Ubuntu pre-installed オプションがある。外観もほぼ XPS 15。いいじゃん。適当にスペックを積み増すと $2000 超えるくらい。まったく安くないというか MacBook Pro と大差ないが、まあ宗教税だと思えばいいんじゃね?XPS 13 Dev Edition 以降に Linux の選択肢が増えないと思っていたのに別のラインがあったとは。Dell 偉い。

何が良いかというとやたらとカスタマイズできる結果 NVIDIA の GPU すら外せる。一時期は CUDA の動く GPU がほしい気がしていたけれど、ドライバインストールの苦難や発熱などを考えるとなくていい気がしていた。それを見透かしたようなオプション。もう完全に Macbook Air への物欲は消えました。自分には速いCPUと広い画面が必要です。さようなら。

早起きが定着し、継続的にコードを書けそうだったらまた考えよう。

MN #3 - Android App Stub

|

早起き三日目。4:40. 選挙の結果を読んでいたらやや出遅れ。結果については特にコメントありません。

Podcast の編集はようやくおわったので今日はちょっとコードでも書きたい。といっても意味のあるプロジェクトをやれる気がしていないので要素技術の hello work など。家でコード書くとか一年ぶりくらいだわ・・・。


とりあえず stub のカメラアプリでも作るか・・・と思いプロジェクトを setup するも KTX を使おうとしたら AndroidX への依存地獄が待っていたので撤収。てか AndroidX が 1.0.0 で producdtion ready といいつつ依存先  Material Design Library がまだ beta とか、相変わらずだな・・・。しょうじき公開する予定のない pixel+P 決め打ちの testbed アプリなので appcompat とかいらないんだけど、Android Studio が生成する skeleton を直すのが面倒なのだった。

Stub だけの空アプリを書いたところで時間切れ。


ひさしぶりに家でコードを書いた感想

  • Kotlin を完全に忘れている。一年くらい真面目に使わないと身に沁みて覚えるところまで行かないのではないか。C++ とか突然書かされても問題ないというのに。
  • 一方でブラウザのタブをいっぱいひらきつつ Stackoverflow プログラミングするのたのしい。自分の日常はこれが足りてない。なんでも SO すりゃいいってもんじゃないとかいってるやつらは老害。
  • AndroidX のこりゃないわ感。
  • 仕事のせいで手が git ではなく hg と入力してしまう。
  • Gradle  遅い。Bazel/Blaze も遅いと思っていたが、Hello World みたいなライブラリでこの遅さはなあ・・・。Bazel の Android Studio 対応が upstream  されたら Gradle 捨てたい気持ち。Laptop が遅い面もある(仕事マシン比)。
  • 画面が狭い。
  • 画面の広さにしろ CPU の遅さにしろ Macbook Air とか買ってる場合ではない気がしてきた。速くてでかいやつが必要。
  • どうでもいいコードとはいえ書くとそれなりに満足し、なおさら Macbook 欲しい気持ちが薄れてくる。物欲は仕事の外でなにもしてないストレスの現れだったのかも知れない。
  • 開発用のデバイスがほしい。いまは私用デバイスに会社アカウントを紐付けており、エンタープライズ機能で Stay  Awake が殺されている。不便すぎ。

MN #2 - Podcast Editing Continues

|

朝活二日目。ちなみに必ずしも毎日つけるとは限らない。最初のうちだけです。

今日は 4:30 作業開始できた。やはりインターネットは見ないほうが良い。当たり前ですか。はい。前日の夜にインターネッツして若干寝るのが遅くなってしまった。そういう危険もある。どうでもいいガジェットのレビューとか読んでいるときほどそういう現象が起きがち。

今朝もひきつづき Podcast 編集。

logd

|

Android の logging suppression ("chatty" とマークされるやつ),  M だか N だかくらいで入った logd という daemon に実装されているらしい。それまではカーネルのバッファに直行していたのが logd を経由するようになった。

しかしひどいコードだなー特に驚くことではないとはいえ・・・。しかも std::list とかマジかよ。もうちょっとがんばってメモリアロケーションとか控えめにしてくれよ。それに色々コピーしすぎだよ・・・バッファに直に read してくれよ・・・。あなたけっこう CPU 使ってらっしゃいますのよ?

そして普通にコードきたないというかなんというか、泣ける。Pruning のロジックは LogBuffer::log あたりだけどもう興味なくなったのでどうでもいいです・・・。

コードを読むとき、自分はコードにこめられた人類の叡智のようなものを期待しているのだなあと思う。Android は読んでも大概疲弊するだけでつらい。

MN #1

|

早起きして書く日記すなわち Morning Notes.

九時就寝、四次起床。 きのうちょうど夏時間がおわったとこなので体内時計的には十時就寝、五時起床相当。

朝起きてラップトップの画面の明るさで目を覚ましつつダラダラニュースを読む、というのをやってみたがだめだね。全然ベッドから脱出できず。ようやく抜け出したらもう五時。

ベッドルームは暗くて目を覚ませない。天井に照明が欲しい。寝間着のままなんとかして台所にたどり着き、そこの照明の下でなんとかする、たとえばコーヒーを入れる、とかの方がまだ目が覚めそう。明日はもう洗顔も台所でやろう・・・。

今朝の活動は Podcast 編集。

Gaining Weight

久しぶりに体重を計ったら 70.5kg.

63kg くらいが望ましく、前回計った時は 67kg くらいだった。増えすぎ。堕落している。

風邪だなんだで運動量が減っていたのと、食事も胃腸炎を気をとられ不規則になっていたせいはあろう。引き締めていきたい。主に食事量を減らす方向で。

唯一の懸念は thyroid underactive の影響。今は処方の結果 overactive だったのが underactive になっており、これは体重増加や疲れやすさとして観測されるんだったはず。つまり堕落ではなく病気の症状の可能性がある。疲れやすさもあるのだよなあ。単に加齢かもしれないが・・・。一方で thyroid overactive の体重減少効果で食べすぎが隠蔽されていただけで現状が平常状態という可能性もある。

次の診断は月末。とりあえず食べる量を減らしつつ体重を監視しておこう。

Understanding Android Surface

|

以下の話題についてより包括的な理解をしたい人は Graphics architecture を参照されたし。


Surface というクラスがある。この名前は完全に間違っていて、実際は ImageQueue みたいな名前だと思えばよい。ここでいう Image は、たとえば GPU が処理したりできる、ART の外で確保された、プロセスを跨いでやり取りされる画像のための共有メモリである。ではなぜ Surface という名前なのか、と考えるのは時間の無駄なうえに精神衛生を危険に晒すので、十分な資産を形成し引退するまではやめておいた方がよい。

Producer / Consumer

Android のサブシステムには画像 (Image) を生成するコンポーネントと Image を消費する(受け取って処理する)コンポーネントがある。

Image を生成する Producer side には以下のようなものがある:

  • MediaCodec: 圧縮された動画ファイルをデコードし、動画のフレーム画像を Image として produce する。
  • Camera: カメラがセンサーから吸い上げた画像をproduce する。動画として次々と生成することも、写真の撮影リクエストごとにひとつの image を生成することもできる。
  • OpenGL: eglSwapBuffers() のタイミングで GL の描画結果 Image をproduce する。

これら producer side のサブコンポーネントは結果の画像を書き込む ImageQueue すなわち Surface を受け取る。例: MediaCodec#configure()

画像を受け取って処理する consumer side には以下のようなものがある:

  • ふたたび MediaCodec. 流れ込んできた画像列を動画として圧縮する。
  • SurfaceView: 流れ込んできた画像を View の一部として画面に表示する。
  • SurfaceTexture: 流れ込んできた画像を OpenGL の texture に割り当てる。

これら consumer side コンポーネントは、画像を受け取るための ImageQueue すなわち Surface を公開している。例: SurfaceView#getHolder().getSurface(). SurfaceTexture はちらっとドキュメントを眺めただけだと Surface を取り出せないようにみえるが、Surface のコンストラクタが SurfaceTexture を引数にうけとるという形で公開している。なぜそんな API デザインなのかは、やはり考えるだけ時間の無駄である(e.g. 単にゴミなだけ。)

Operating On Pixels

Surface の上を流れる画像にアプリケーションからアクセス、加工する代表的な手段は OpenGL である。すなわち画像を SurfaceTexture 経由で GL texture にマップし、GL でレンダリングがてら pixel shader などでなんかする。

GPU でなく CPU で処理したい人には ImageReader というクラスが用意されている。これは ImageQueue すなわち Surface の consumer side コンポーネントの一つ。そのコンポーネントが自ら画像をなんかするかわりに、Java のレイヤに Image というオブジェクトをとりだす API がある。この Image オブジェクトを使うと ByteBuffer ごしに画像のピクセルを読み書きできる。

CPU で処理したいユースケースの代表格はファイルへの書き出し。たとえばカメラの画像を JPEG で保存するとか。

ImageReader で読み出した画像は用が済んだら close() のうえ捨ててもいいし、ImageWriter オブジェクトを使って他の ImagQueue すなわち Surface にそのイメージを enqueue することもできる。ImageWriter は ImageReader の対, producer side のクラスである。

Image#close() するのはかったるいが、Image の実体は Java heap でなく希少な共有メモリ・そのうえサイズがでかいので、こまめに開放しないとすぐ枯渇してしまう。やむなし。

SurfaceView

SurfaceView は ImageQueue/Surface の consumer である。ではどうやってその image を consume し、画面に表示するのだろうか。

すべての Activity は最低一つの SurfaceView を持っている。以下ではこれを Root SurfaceView と呼ぶ。Root SurfaceView には持ち主のアプリが描画される。アプリが描画した画面の Image を実際に消化するのは SurfaceFlinger と呼ばれるプロセスである。これは複数のアプリの描画結果をくみあわせ最終的な画面を描画するプロセスで、他の OS だとWindow Manager とか Window System などと呼ばれるものの機能の一部である。SurfaceFinger は最終的な画面を OpenGL で描くこともあるし、可能ならより省電力で 2D 専用の composition hardware を使う。

つまりアプリの描画結果はアプリ自体のプロセスから ImageQueue/Surface を介して SurfaceFlinger に送られる。SurfaceView は画像だけでなく画像の表示場所や大きさすなわちレイアウト結果も SurfaceFlinger に伝える。(こうした位置情報の伝達は Surface と独立した API/Binder をたどる。) 

Root SurfaceView ではなく、アプリケーションが確保した SurfaceView も基本的には同じように振る舞う。すなわち、受け取った画像はレイアウト結果ともども SurfaceFlinger に送られる。

別の言い方をすると、アプリは SurfaceView をレイアウトはすれど描画はしない。たとえば OpenGLで SurfaceView に何か書き込んでもアプリ自身の描画結果には反映されない。Android が内部で確保したアプリの Root SurfaceView とアプリのコードが確保した SurfaceView はそれぞれ独立に描画され、それぞれの Image を SurfaceFlinger に送る。SurfaceFlinger はそれを重ね合わせ、辻褄のあった最終的な画面を描画する。

プロセスをまたぎ最終的な画面画像の合成プロセス (composition という) に介入する荒々しさを理解していないと, SurfaceView はすごく奇妙な振る舞いをするように見える。そういう意味で SurfaceView という名前は misleading とは言わないまでももうちょっとそういう事情を反映した名前のほうがよかった。たとえば CompositionView とか。

ところで Android は Camera や VideoCodec にも独立したプロセスがある。こうしたコンポーネントはそのプロセス内で Image を生成し、ImageQueue/Surface を介してアプリに届ける。しかし SurfaceView の実際の consumer は SurfaceFlinger プロセスなので、VideoCodec や Camera を SurfaceView に繋ぐと Image はアプリのプロセスをかすりもせず SurfaceFlinger に届く。なのでアプリの UI thread が多少もたついてもビューファインダやビデオはコマ落ちせずに再生される。この低遅延な振る舞いは SurfaceView の大きな利点である。

TextureView

TextureView は SurfaceView と同じく Surface すなわち ImageQueue を介して画像を受け取る consumer である。しかし SurfaceView と異なり、TextureView は実際にアプリのプロセスが描画する。

各アプリには RenderThread  と呼ばれるスレッドがあり、このスレッドは UI thread の作ったディスプレイリストを OpenGL で描画する。 TextureView は RenderThread に SurfaceTexture を作って画像を受けとり、RenderThread が描画する画面の一部としてそのテクスチャを描画する。これは LAYER_TYPE_HARDWARE を指定した View の振る舞いとよく似ているが、RenderThread がテクスチャの中身を描くかわりに Surface の向こうの producer からテクスチャの中身が届く点が異なる。

TextureView は普通の View と同じく RenderThread で描画されるため、レイアウトとかでややこしいことにならない。だから扱いやすい。一方で一回余計な GL の描画を挟むぶん 1 フレーム遅延があるし、電力効率も悪いし、UI thread がもたつくと巻き込まれる。利便性と性能をトレードオフしている。

TextureView も名前が悪いね。SurfaceView とは逆に実装の詳細を晒しすぎている。LayerView とか呼べばいいのに。

Pipeline

どこかの producer から 受け取った Image のストリームをどのような方法で画面に描くか、画面に書く前の加工をどうするか。Surface を中心とした一連の画像処理を pipeline と呼ぶことがある。Pipeline のデザインはメディア系アプリの性能や安定性に大きく影響する。同時に HAL や OS の都合で思わぬ制限も多い。実験しつつ良いデザインを探求する価値がある。が、世の中は割とコピペと cargo cult に支配されがちに見える。ここに書いたシステムのデザインの意図みたいのは理解しておくと少しマシな判断ができる、かもしれない。(できないかもしれない。)

朝型化を考える

|

家族の生活リズムの変化により朝に何もできなくなって久しい。結果として夜になんかやろうとしていたのだが、ダメ。夜の自由時間のはじまり、すなわちゆこっぷ(奥さん)が子供の寝かしつけに入り、自分が晩飯の片付けなどを済ませたあと、意味のある活動が全然できない。ほんとはここでシャワーを浴び、そのあと本来やるべきことをやる必要があるんだけれど、疲れていてだらだらスマホをつついているうちに夜が更けてしまう。

自分の根性のなさのせいにしてもよい(間違いではない)が、それだと問題が解決しない。やはりなんとかして活動時間を朝に戻す必要がある気がする。そういえばもともと朝にシフトした時も同じことを考えていた気がするな。

以前やっていた朝シフトは、早く起きて早く家を出て始業の前に会社でなんかする、というスタイルだった。今は早く家をでることができないためこの方法を使えない。

となると、早く起きて家でなんかするのが良いのかなあ。なんか聞いたことあるなこの話。ひげぽんか。ひげぽんにはある時この話を個人的に聞いた。「昼寝はしてない」と書いてあるが実は朝寝をしている。というのが発見だった。たしかに今読み直すと 「朝 7:15-8:00 に寝たりしている。昼寝のかわり?」と書いてるね。なぜそのタイミングで仮眠できるのか謎だが。子供に邪魔されないのだろうか・・・。

まあそんなのはディティールで、自分は普通に5 時起き可能。なぜなら今のところ子供が早寝なため、自分も 20:30-21:00 くらいには寝られるはずだから。

朝おきてすぐ家でなにかするのと、朝おきて会社に言って何かするのを比べると、やはり会社の方が色々よい。まず出勤のジョギングで目が覚めるし、会社の方が完全に自分をデタッチできるから。まあでも、なにもしないよりは何かできる方がよい気がするなあ。


どんなかんじにすればよいか。

前日夜

  • シャワーをさっさと浴びる
  • 着替えを用意する
  • 朝やることをなんらかの形で考えておく
    • ノートに書くとかだろうか。
  • とにかくさっさと寝る。 8:30 くらい目標で遅くとも 9:00.

  • 目覚ましで 4:30 くらいにダラダラ起床開始。
    • スマホでダラダラするかわりに laptop でダラダラしつつ覚醒。
  • 着替える、顔あらう。
  • ストレッチ・・・はしない。時間がかかるので、子供起床後に回す。ちょっとだけ筋トレして目を覚ますのはいいかも。
  • コーヒーのむ。
  • 作業開始。ここで遅くとも 5:30 くらいだと良いのだが。


朝の出勤後の活動が失われ始めたのが、記録によると一年半前。この頃から離乳食が始まったとあるが、それでも 7 時には出勤できている。どうすればそんなことが可能なのか今から振り返ると謎。まだ子供の夜の睡眠が不安定で、起きるのが早かったのかも知れない。今は概ね 6:00-6:30 くらいに起きてくる。あとは起床から朝食の時間が長くなっている。とかなんだかんだで当時より1時間余計にかかっているのだね。つまり一年半前より 1 時間、二年前より 1.5 時間、朝の可処分時間が減っていることがわかる。

一方で、この頃は子供の離乳食と大人の食事は別にとっており、大人の晩飯は子の就寝後だった。でも子の食事が大人に近づいてきたどこかのタイミングで、子供と大人は一緒に晩飯をとるようになっている。なので夜の可処分時間は当時より 30 分ちょっとくらい増えている。合計だと可処分時間の減少は1時間弱くらいか。減ってはいるがゼロにはなってはいないはずなので。やはり朝シフトに戻すべきだな。

今の平日の一日をかきだしてみる

  • 06:00 にめざましがなり、だらだらと 6:30 起床。洗顔など。
  • 07:00 少し前くらいから家事雑用。その後ストレッチ。
  • 07:30 くらいから子供の朝食補助。
  • 08:00 出勤
  • 17:00  ちょっとすぎ退社、18:00 帰宅。
  • 夕食、子供の相手など。
  • 19:30 家事雑用
  • 20:00 風呂、上がり次第空き時間
  • 22:00 就寝

やはり風呂の後と朝のダラダラが無駄だね。


今まで朝シフトをしてこなかったのが不思議に思えてくる。生活に変化があっとのではと振り返るに、ゆこっぷ(奥さん)が子供と添い寝をするようになったのが大きな変化に思える。ある時期から子が一人で寝るのを嫌がるようになり、父(自分)と寝るのも嫌がり、そのようになったのだった。これは必ずしも望ましい変化ではないのだが、朝シフトをするのには都合が良い。なぜなら子供が寝たあとに夫婦で会話をする、という可能性がなくなり、さっさと寝ても何も不都合がなくなったから。そして朝起きるににしてもゆこっぷを巻き添えにする必要がなくなったから。

添い寝はいつまでもするものではないから、この前提もそう遠くない将来に変わるであろう。今のうちに活用しておきたい。

What to Talk: Odd Number Episode

第40回、一回分だけあまってるのに何を話すか。

  • 撮り損ねたせいで余っている論文をむかいさんに読んでもらう。
  • フォローアップ特集。
  • どうでもいい勤務先の論文をなんか読む。
  • 読んだ本の紹介。しかし読んでないので紹介するものがない。