2015年8月26日水曜日

Take an Android Chrome tracing from laptops with small storage

./tools/profile_chrome.py is our friend to take a great tracing data from Android Chrome and Chromium. But usually it requires to check out the huge chromium repository that is too large, about 8-GB, to have it in some sorts of laptop devices. This is a note to copy small set of files from an existing checkout to run the tool on another laptop device.

desktop % tar zcvf chromium_tools.tgz \
> ./build \
> ./third_party/android_testrunner \
> ./third_party/catapult \
> ./tools


laptop % scp desktop:chromium_tools.tgz /dev/stdout | tar zxv

The expanded files still need 512-MB of your storage, but would be much better than 8-GB.

2015年8月16日日曜日

2015年6月/7月の読書

また溜めちゃったかなぁ、と思ったけど今月はまだ終わってないので2ヶ月だけだった。6月に6冊、7月に3冊の計9冊から……少ないけど、まぁいっか。

SF

天冥の標は読み続けてます。5巻でいよいよ太陽系外生命体について詳しく書かれる事になり、全ての背景設定が出揃った感じ。6巻がいよいよ三部構成で太陽系を舞台にした一大惨事の始まり。これ書いてる時点(8月)ではPART2まで読み終わってますが、今後も目が話せない感じ。

それとは別に伊藤さんのハーモニーも読みました。こっちも完璧だった。虐殺器官の頃のような文体な未熟さもなく素直に面白かった。国家の品格で言うところの近代的合理精神の限界に対する近未来で起きる1つの皮肉な解、あるいはシンギュラリタリアン的発想の人類補完計画。情報インフラってこういう怖さはあるよなぁ、と思う。まぁ、合理的な判断ってモノ自体が幻想だし。生物の進化の根源も非合理やカオスにあるのでその辺は物語として読む感じ。判断ってのは世界をどの切り口で覗きこむかで決まるもので、絶対的な真実があるわけでもないし。ニューロンだって非線形じゃないと学習できない。しかし、著者の若い死が悔やまれる。

政治・経済

こっちもシリーズで固定化しちゃったけど池上さんの4と5。追いかけるように読んでるわけだけど、近い将来として書かれた話題が、まさに今の問題になっていて、世界が大きく動いているのがわかる。読んでいて面白くないはずがない。最近、常々思うんだけど、人の一生の50-100年って言うのは人の歴史と比べてもずいぶんと長いんですね。日本の歴史で考えても、ある程度しられているのは1500年程度。その1/15程度をリアルタイムで体験するわけで、その間に歴史が動かないはずがない。

Ubuntuチューニング、良かった・悪かった

HP Stream 11向けにやったチューニング、少し時間経ったので振り返り。

swapfs

zramは状況によりけり。2GBでVMに1GB使う時なんかは、zramは切るか128MB×2くらいの構成にしておかないと使い物にならなかった。まぁ、2GB環境でVM使う事自体がアレな気もするので、普通に使う分にはzramを256MB×2くらいが良いのかなぁ、と思いました。
あと、SD Card上にswap作るのは無しかな。zramとセカンダリの内蔵ディスクが良いバランスな気がしました。Chromeからブログ書いてる今この瞬間の状況はこんな感じ。
% cat /proc/swaps
Filename       Type      Size    Used   Priority
/dev/mmcblk0p6 partition 1048572 0      -1
/dev/zram0     partition 242280  133884 5
/dev/zram1     partition 242280  133900 5
% vmstat -s
 1938276 K total memory
 1455064 K used memory
  797620 K active memory
  386564 K inactive memory
  483212 K free memory
   47152 K buffer memory
  445900 K swap cache
 1533132 K total swap
  267812 K used swap
 1265320 K free swap
(snip)

仮想記憶の設定

vm.dirty_background, vm.dirty_ratio, vm.swappinessは前回の設定(5, 10, 20)がわりと良好みたい。まぁ、この辺が原因で書き込み頻度が上がってSD Cardが書き込み寿命に達した可能性もあるんだけど。でも、どちらかというとswapに使ってたこと自体が問題だった気はする。tmpfsも使うのを止めてしまったのは以前書いた通り。メモリに余裕がない中で適切なサイズを見積もるのが難しいのと、ディスク溢れを気にするのが精神衛生上良くなさそうなのと。その一方で苦労のわりに体感的に得をしてる気がしなかった。

ドライバ周り

カーネルアップデートかかる度にWifiが不安定になって面倒。実は先のディスク復旧時に15.04も試したんだけど、そっちは安定してる。輝度調整や音量調整ボタンなんかも完璧。14.04系だとrtlwifi_newを常時置いといてアップデートかかった度にインストールが必要な感じ。Bluetoothは下手に動かすとWifiが動かなくなったりするので最近は試してない。これはBTとWifiがカニのワンチップだからですね。品番別に読ませるファームのROMが必要っぽくて、古いチップ向けには対応されてるんだけど、rtlwifi_new見てもまだ該当チップ向けのファームが含まれてない。

preload / prelink

これも効果は抜群だったんだけど、Chomeのアップデートがかかる度にコマンド打つのが面倒になってやめてしまった。これなしだとApp Launcherの起動に2秒くらいかかるので、本当は使いたいんだけど。パッケージ作り詳しい人なら、パッケージ更新時に自動的に走るように細工したりできるのかな? あと、App Launcherは手動でアレコレしなくてもChrome 44まではchrome://flags#enable-app-listで有効にできるみたい。45からさらに色々なexperimentalが追加されててフラグ良くわからない状態に……。44までで有効にしとくのが楽です、たぶん。

SD Cardが壊れた話

HP Stream 11ネタ。話題が増えてきたのでラベルHP Stream 11を追加してみた。

SD Card故障

以前セットアップしてSD Card上で動かしていたUbuntu 14.04.3なんだけど、VirtualBoxの中でWindows 7にアップデートをガシガシあててたら、なんかディスク不調に。しばらくするとrootfsがread onlyで再マウントされてしまう。当然VM内のWindows 7はディスクに書けずにアップデート異常終了。しばらく原因を調べていると、どうもSD Cardの書き込みができなくなった模様。うっかりLockの爪が……みたいな話なら良かったんだけど、その場合には書き込みはエラーするはずで、今回は成功するものの書けてない。以下、この状況で発生したオモシロ現象。当たり前なんだけど、妙に感心した。

  • SD Card上のswapにデータが入ると、予想不能の発狂モードに突入。色々なものが次々にSEGV。
  • 書き込み量が増えてくると、どこかのタイミングでジャーナリングと実データの矛盾に気づいてEXT4が悲鳴を上げる。こうなるとrootfsはerrors=remount-roでマウントされてるのでread onlyモードに落ちてしまう。
  • read onlyモードではfsckが走るので、簡単な論理故障ならfsckかけてrebootで生き返る。けど、今回は修復が走った後にジャーナリングに異常が残ってcleanにできなかった的なエラーが出ました。
  • ファイルシステム故障かと思い色々手当するも、再起動後には必ず同じ場所まで巻き戻って、同じように自動でfsckがかかり、同じinodeが修復され、同じような故障状態でbootする。
で、本当にSD Cardの故障か調べるためにやった事、いくつか。

まずは該当ディスクに対してbadblocksを-n付きで走らせてみた。見事、全ブロックが書き込み失敗。128GBのディスクだったので完走するには一晩かかりました。まぁ、走らせて寝て起きて確認しただけ。

次にやったのはファイルシステムの確認。読み出しは問題ないので別のLinux上でdd使ってSD Cardのイメージを丸ごとファイルに書き出し。これも時間かかるので注意。dd if=/dev/sda of=sda.imgみたいな感じで。細かいオプションはお気に召すままに。で、ディスクイメージはそのままマウントできないので、以前のストレージ復旧でお世話になったkpartxを使ってパーティションを/dev/mapperに配置。
% kpartx -a sda.img
ってやれば/dev/loopNにsda.imgをマウントして、中のパーティションが/dev/mappers/loopNpMって形で見えるようになる。使い終わったら-d付きでイメージファイルを渡せば開放される。今回は/dev/mappers/loop0p1がswap、/dev/mappers/loop0p2がext4のrootfs。続けてファイルシステム修復。
% fsck.ext4 -f /dev/mappers/loop0p2
で確認したところ、実デバイスで走っていた時と同じような修復が走った。けど、最終的にcleanになった点が故障デバイス上とは違った。実際、二度目を走らせたらエラーは検出されず。

復旧

この時点で一番簡単な復旧は同じメディアを用意してddでコピーする事。新しいメディアに差し替えて起動すれば今までどおりEFI経由で起動するはず。ただ128GBのメディアも安くはないので手元にあった32GBに移植する事にした。128GBでも中身はパンパンだったんだけど、KVM用のイメージだったりChromiumとHaikuのソースコードだったりが大半。こいつらを退避したら32GB以下に収まった。いつも思うけどChromeでかすぎ。で、サイズの違うメディアへのイメージ移植は多少の手間が必要なので忘れないように簡単なメモ。

  1. 小さくしたいファイルシステム内で、目標のサイズに収まるようにファイルを削除していく。パツンパツンでも運用できなくなるので、余裕をもって減らす。
  2. resize2fsを使ってファイルシステムのサイズを小さくする。
  3. パーティションテーブルを書き換えて、該当ファイルシステムのパーティションサイズをファイルシステムに一致させる(か、多少大きくても良い)。
  4. 別メディアを用意して適切なコピー先パーティションを用意する。
  5. ddで縮小した旧パーティションを別メディアの新パーティションにコピー。
  6. 新パーティション上でresize2fsを使って、確保したパーティションサイズ目一杯までファイルシステムを拡張(縮小時にピッタリ同じサイズに収めていれば、この手順は不要)。
各手順を少し補足していく。まずファイルの削減。ディスクのサイズってみんながみんなバラバラな数え方するので、とりあえずざっくり28GBを目標に削減してみた。ファイル削除自体は/dev/mappers/loop0p2をどこかにマウントして作業すれば簡単。適宜dfでサイズを確認。
% fsck.ext4 -f /dev/mappers/loop0p2
% resize2fs /dev/mappers/loop0p2 28GB
メッセージはメモとってないけど、ここで実際に何ブロックまで小さくなったか、とブロックサイズ(4KB)が表示されるはず。ブロック数×4096が実パーティションサイズになるので、次のパーティションサイズ変更の参考に。
% sudo parted /dev/loop0
(parted) unit b           # 計算のためバイト単位の表示に切り替え
(parted) p                # パーティション情報の表示
(parted) resizepart 2 XXX # 2はパーティション、XXXは下で説明
(parted) q                # 終了
pコマンドでパーティション一覧が表示される。今回は2つ目のパーティションが対象。Start、End、Sizeがバイト単位で表示されるので、このSizeがresize2fs時のブロック数×4096になるように調整すれば良い。具体的にはresizepartのXXXをStart+ブロック数×4096とする。第一引数はパーティション番号なので、適宜正しい値を使うのを忘れずに。

新しいディスクもEFIで運用するためにGPTで用意する必要がある。
% sudo parted -a optimal /dev/sdb
(parted) mklabel gpt
(parted) mkpart primary ext4 0 100%
(parted) q
optimal付けとくと、ブロックのアライメントをメディアの物理単位に合わせてくれる。性能に影響するし、手動で揃えるのは面倒なので指定しておくのが無難。これで手順4までが完了。ddはif=/dev/mappers/loop0p2 of=/dev/sdb1以下お好み。最後にresize2fs /dev/sdb1を走らせれば確保した新パーティションのサイズ目一杯までファイルシステムを拡張してくれる。あと、古いメディアではswap領域がloop0p1相当の場所にあってfstabにも相当のエントリが存在していたので、複製した/dev/sdb1をマウントしてfstabから不要になったswapエントリを削除した。

EFIで運用していれば、ddでパーティションを複製した際にUUIDもそのまま複製されるので、ブートストラップ周りのディスク名の修正対応に追われないので楽ちん。blkidコマンドはどこかにキャッシュがあるのか、ddによる複製後も古いUUIDを返し続けるが、実際には正しく書き換わっているので混乱しない事。自分はこれに気づかずgrub.confのrootfs指定のUUIDを書き換えてしまい起動時にrootfsが見つからずにinitramfsの中で起動停止。initramfs上でgrub.confを書き換える苦行をするはめに。この中ってviどころかedすら使えないのね。適当な場所にrootfsを手動マウントして/mnt/bin/ed使うくらいしか思いつかなかった。/mnt/usr/bin/vim.basicとかは共有ライブラリ周りをうまく手当してやる必要があるので少し面倒なはず。自分はed使ったほうが早いのでviはさっさと諦めた。

おまけ:吸いだしたイメージをKVMで起動

復旧には直接必要なかったんだけど、吸いだしたディスクイメージが起動するかKVM上で試してみたのでメモ。こちらはEFI対応とかブートストラップの手当とか、わりと面倒だった。記憶で書いてるので不正確な部分もあるかも。

まずはEFI対応の方法。参考にしたのはtire.retireさんのKVMでUEFI環境のゲストを作る。CentOS向けの説明なのでOVMF.fdの置き場所が違うんだけど、他はそのまま。UbuntuではOVMF.fdの置き場所は確か/usr/share/qemuで通ったはず。

次に起動向けのEFI環境の準備。HP Stream 11ではSD CardはEFIから見えないため、例のSD Card環境ではEFIシステムパーティション、/bootは内蔵ディスクにありました。この辺を内蔵ディスクに頼らないように手当してやる必要がある。まずEFIシステムパーティションは新規ディスクイメージを作成してマウントさせる事で対処。
% head -c `expr 8 \* 1024 \* 1024` /dev/zero > efi.img
% parted efi.img
(parted) mklabel gpt
(parted) mkpart primary fat32
(parted) q
% sudo kpart -a efi.img
% sudo mkfs.vfat /dev/mappers/loop1p1
% sudo mount /dev/mappers/loop1p1 target
% sudo mount /dev/mmcblk0p1 original
% sudo mkdir target/EFI
% sudo cp -rfp original/EFI/ubuntu target/EFI
まず、grubの設定を正しく読み込むために、target/EFI/ubuntu/grub.cfgの最初の行、search.fs_uuidに書かれているUUIDを書き換える必要がある。これはblkid /dev/mappers/loop0p2(吸いだしたイメージのrootfsパーティション)の値を使えば良い。

で、次は/bootの対処。/dev/mappers/loop0p2の/bootは空になっているので、内蔵ディスクの該当パーティションからコピー。
% sudo mount /dev/mmcblk0p5 boot
% sudo cp -rfp boot/* target/boot/
target/boot/grub.cfgには最低限の修正を適用。Ubuntuの起動エントリでlinuxとinitrdの項目が/vmlinuz-...と/initrd.imd-...というルート直下のパスになっており、linuxにはroot=UUID=でmmcblk0p5を指定している箇所があるはず。このroot=UUID=を初段で指定したUUIDと同じ/dev/mappers/loop0p2のIDに書き換え、/vmlinuz-...、/initrd-...を/boot/vmlinuz-...等に書き換えれば準備完了。

KVMから起動するとEFI Shellに落ちる。作成したEFIのディスクがFS0として見えたので、
Shell> fs0:
fs0:\> cd EFI\ubuntu
fs0:\EFI\ubuntu\> shimx64.efi
でgrubのメニューが出るはず。まぁ、何か間違っててメニュー読み込み失敗したらgrubの対話モードからconfig file (hd0,gpt2)/boot/grub/grub.cnf とかで読めるはずなので、tabキーと友達になりながらgrub.cnfを探して読んでみてください。僕はこの段階でbootが空になってる事に気づいて、bootディレクトリのコピーとかUUIDの書き換えが必要なのを思い出しました。一度起動しちゃえばupdate-grub、grub-installを走らせれば、この辺の修正は綺麗になるので。まぁ、適当に。