ichirin2501's diary

いっちりーん。

YAPC::Kyoto 2023 に行ってきました

yapcjapan.org

スタッフ/スピーカーの皆様、本当にお疲れ様でした & ありがとうございました。
各発表に関しては色んな方が感想文を書いているので、そちらに任せることにします (自分では小学生の文章になってしまう)。

自分のことだけを書く。

チケット買わないの?と唆されたのと、場所が京都ということで参加。
YAPCに参加するのは今回で2回目で、確認したら最初に参加したのがYAPC::Asia Tokyo 2015....、8年経過していることに一番驚いてしまった。

イベントに参加する理由は人それぞれだと思いますが、今回は友人に会いに行くのが最大の理由でした。
会場を歩いているだけで見知った顔があちこちにいるので、わぁ〜〜〜って盛り上がる。最高か? 体験が良すぎる、これがオフライン、良き。
自分は現職で3社目ですが、それぞれの現/元の友人たちがイベントに参加してることもあって、実質同窓会ってやつを味わいました。

採用された発表も、Perlとはほぼ無関係な内容も多くて相変わらずのYAPC
ちょっと独特なコミュニティの雰囲気、スタッフの熱量も伝わってくる。


トークも含め、YAPC::Kyoto 2023 楽しかったです。


以下はYAPC前日祭の夜に株式会社はてなさんの新オフィスにお邪魔したときの写真。
このときonishiさんが一緒に映り込もうとしたので、「onishiさん邪魔ですっ」って言ってどいてもらいました。懐かしい気持ちになりましたね。


定年説

今年でプログラマ35歳定年説の年を迎える。

たしか大学生ぐらいのときにそれを知って、「今はまだ安月給の流れだから給料のためには管理職にならざるをえないとかそういう話で、今後はどんどん現場のエンジニアの価値が上がっていくだろうから関係ない」みたいに思ってた、気がする。

当時の自分が35歳の自分に質問できるとして、どんな質問をするだろう。
そして今の自分はどう答えるか。
親知らずの主張が激しく、痛み止めの薬を飲んで楽になっている間に適当に考える。


Q. 今何してるの?
A. 所謂管理職にはなってないし、意外だと思うけど面倒で嫌だったインフラ寄りのエンジニアを好きでやってるよ。コードをばりばり書くことは今はない。気付いてると思うがtry&errorできる気軽な環境が身近になく経験値が積めてないから面倒だと感じるだけで分かってくると楽しいよ。昼飯が100円チョコとか食パンで1日を過ごすこともあるのに電気代が増える自宅鯖で遊ぶとかは金銭面で厳しい話だね...まぁインフラより競プロの問題解いてるほうが娯楽に近くて楽しいしね、それは今も変わってないよ

Q. エンジニアとしてやっていけてるってこと?
A. やっていけてる。ただ、運が良いよ、まじで。幼少期は「運が悪い」が口癖だったけど、消し飛ぶぐらい運が良いよ。もっと周囲に感謝しよう

Q. ハッカーと画家みたいなハッカーにはなれた?
A. 残念ながらなれてない。でも、普段から黒い画面でごちゃごちゃやってるよ。こっちの分野に全く知らない人が見たらそれなりの格好にはなってるんじゃない?

Q. 社会人が言うコミュニケーション能力云々って実際どうなの?w
A. 残念というか悲しいことにコミュニケーション能力は必要。コミュニケーション能力が不要だと感じるなら環境と周囲の人たちに感謝しような

Q. 勉強しておくべきことは何?
A. 英語、わかってるのに聞くんじゃない。あと、研究方面はさっぱりだろうけど、研究の進め方や考え方についてはもっと真面目に向き合ったほうがいい

Q. 企業した?
A. してない。社会人になればすぐわかるが、ビジネス方面のセンスはないよ


昔の自分: もういいかな、そっちから言いたいことある?
今の自分: 自分のこと嫌いだもんな、わかるよ。こっちからも特にないかな。特にないって言えるほどにはそこそこ満足な人生送れるよ、今のところは。あ、嘘。大学生の長期休みがあるうちに親知らずを全部抜いておけ、それから歯の矯正を開始しろ。あとララ(愛犬)によろしくな

ファミコンエミュレータ実装の感想

とりあえずスーパーマリオが動いて一段落したので覚えているうちに感想書いていく。

(この記事の情報量は、デバッグは大変、以上)

動機

単に好奇心。ただ、ファミコンエミュレータに着手したのはこれで3回目になる。
1度目は10年前の身内ハッカソンのとき。このときはC言語で実装してて強引にHELLO, WORLD!を表示するだけで終わった。 実装の続きをしたかったけど、この後は忙しくなってしまって挫折している。
2度目は2年前で、過去の心残りを精算するためにGo言語で着手したのだけど、CPUの実装が終わった後ぐらいからまた忙しくなって挫折している。
今回は2年前のGoコードの続きからコミットを積んでここまで来たので、一応リベンジ成功....と言って良いんじゃないかな、たぶん。

過程

PPUの実装は最初からinternal register(v,t,x,w)を使う方法にした(PPU scrolling)。
hello world表示するだけでも地味にデバッグが大変になってしまって、最初は少し後悔した。

これは見切れているhello world


見切れるbugは修正したけど、次は左寄りになってるhello world
これはppu shift registersのbufferが1tile分足りなくて、1tileずれて表示されていた。

https://www.nesdev.org/wiki/PPU_rendering#Cycles_1-256
Note: At the beginning of each scanline, the data for the first two tiles is already loaded into the shift registers (and ready to be rendered), so the first tile that gets fetched is Tile 3.


hello world!!


正常なhello worldを確認して意気揚々とnestest.nesを読み込ませたらメモリアクセス違反でクラッシュしたんだけど、無視して強引に表示させた様子。 めっちゃバグってて草。画面表示なしだとnestest.nesのCPUテストはクリアするので、ここで少しデバッグに苦しんだ。


画面表示ありでnestest.nesが正常に動いた様子。
原因としては以下の一文を見落としており、メモリアクセス違反が発生していた。

https://www.nesdev.org/wiki/PPU_scrolling#PPU_internal_registers
Note that while the v register has 15 bits, the PPU memory space is only 14 bits wide. The highest bit is unused for access through $2007.


sprite実装に着手したがきもい色になった。
ここからギコ猫でもわかるファミコンプログラミングの各種ROMにお世話になる。


正常なgiko猫さん


背景動いている


sprite 0 hit の実装も(bugがあるが)比較的にすんなり進んでしまってgiko猫のラスタスクロールは動いた。ただ、この後の実装でこのgiko猫ラスタスクロールは動かなくなる、下記に従った実装すると動かなくなってしまった(今も)。

これと、

https://www.nesdev.org/wiki/PPU_registers#OAM_data($2004)%3C%3E_read/write
Writes to OAMDATA during rendering (on the pre-render line and the visible lines 0-239, provided either sprite or background rendering is enabled) do not modify values in OAM

これ

https://www.nesdev.org/wiki/PPU_registers#OAM_address($2003)%3E_write
Values during rendering
OAMADDR is set to 0 during each of ticks 257-320 (the sprite tile loading interval) of the pre-render and visible Scanlines.


公開されている2048.nes。このときはまだコントローラ実装が雑だったので操作感が微妙だったが、ぎり遊べた。

ここからは公開されているPPU系のテストROMと格闘することになる。
bug取り作業で印象に残っているのは3つ。

1. CPUとPPUのタイミング実装を変えたこと

まず、実機だとCPUとPPUは独立して動作し、clock差は1:3の関係になっている。対してエミュ実装の基本的な方針としては並列ではなくCPUを動かしてその後にPPUを動かす。 自分の実装でも方針は同じだけど、CPU命令を1つ実行したらその命令にかかったclock数に応じて最後にPPUを動かしていた。
各命令毎のclock数の表はこことか: https://www.nesdev.org/wiki/6502_cycle_times
例えばLDA ABSなら4clockなので、その命令の処理が全部終わってからPPU側を12clock動かす。 この実装のエミュだと、実機の挙動と比較してCPUとPPUの状態に差があるのでrace conditionの再現度がいまいち。それが原因でどうにもvbl flag timing系のテストが通らなかった。 https://www.nesdev.org/wiki/PPU_frame_timing#VBL_Flag_Timing

再現度を上げるためにも各命令の実行途中で良い感じにPPUを進ませたい (良い感じとは?)。 なんとかしてえ〜って思って各命令にかかるclock数に着目していたら、最低でもメモリの読み/書きする回数以上であることが分かった。 CPUから1回メモリを読み/書きするときにPPU 3clock進ませる方針にして、余ったclock数は最後に調節する設計に切り替えた。 これが良い感じにハマって多くのvbl flag timingu系のテストを通すことが出来た。 その後になって命令毎にどのタイミングでCPU 1clock相当の処理になるのか詳細に書かれた資料を見つけてさらにハッピー。
https://www.nesdev.org/6502_cpu.txt
dummy read/write はこの辺から来てるのか〜となった。

2. CPUから見たときのPPUの状態の定義

メモリの読み書き時にPPUを動かすようにしても一部のtiming testが通らなかった。デバッグするとテストROMが期待する状態に対してPPU 1clock分ずれていた。 CPU 1clock分ずれるのは分かるけどPPU 1clockずれることに心当たりがなくて???だった。 自分の最初の実装だと、「PPUのscanline=241,cycle=1のときにvblankが発生する」というのを、cycle 1 ~ 2 の間で発生すると解釈して実装していた。これだとCPUから見てPPUの状態がちょうどscanline=241,cycle=1のときはまだvblankが発生していないことになっていた。対してテストROMが期待していたのはvblankが発生済み、というものだったので、自分の解釈が間違っていた。 cycle 1 ~ 2 の間で発生する〜実装をやめて、CPUから見てPPU cycle=1状態だとcycle=1で発生するPPU側のイベントは全部終わっているように修正した。 これで当初こけてたテストも通った。

3. sprite 0 hitのbug


めっちゃハマった。上記はこのbugにハマっていたときのもの。 このbugに向き合う前は散々cpuとppuのタイミングのずれと格闘していたので、絶対それ関連だろうと憶測を立ててしまったのが誤り。 不幸なことにこの時点でsprite_hit_tests_2005.10.05のテストは全部OKだったので、既存のテストROMで検知出来ない部分のsprite 0 hit処理がバグってると考えるのにかなり時間がかかってしまった。 wikiの通りにoamはprimaryとsecondaryを用意する実装にしていたんだけど、"0 index"の対象をsecondary oam側にしてしまっていたのが原因だった。普通にbugである。 RasterDemoの画面の動きを観察したときに、背景を1本の軸で回転させてるなぁ〜 => ラスタスクロールはタイミングを捉えるのが重要だからこの1本の軸のところがsprite 0 hitだろう => 常に固定だろう => あれ、なんでsprite 0 hitが固定なのに画面がちらつくんだ? という思考による気付きだった。観察は重要。 primary oam側の0 indexを見るように修正して解決。

他にも色んなデバッグ苦労話があるがだいたいこんなところ

テストROMがある程度通したところで、FCダンパー購入


メルカリで購入したスーパーマリオをダンパーに指した様子

そしていざROM吸い出し....


これはカセットとROM吸い出しの接触不良によって生み出された謎のゲーム。
めっちゃわくわくして自作エミュに読み込ませたらこれだったので「えっ、自作エミュばぐってる?... 念入りにテスト通してきたのに?....」ってなった。 急遽別のエミュを落としてきて同ROMを読み込ませたら同じ現象になって安堵した。

カセットを抜き差しして何度か試すものの、毎回ハッシュ値が違ってて笑ってしまった。
念願のハッシュ値で吸い出し成功したら平和が訪れた。

だめだと分かってても懐かしさに負けてカセットをふーふーしてしまった。反省してます。

その他

実装の骨格はfogleman/nesを参考にさせていただいた。シンプルに書かれててすごい。自分のエミュではAPUは未実装、サウンドは...仕組みにあまり興味がないのでたぶん実装しない。vbl_nmi_timing/7.nmi_timing.nesppu_vbl_nmi/05-nmi_timing.nesはNMI発生をppu 2clock delayさせるhackをしてしまった。今の自作エミュだとcpuを動かした後にppuを動かす実装なので、ppuの動作が実際より遅れることはあっても早くなることはない、という理解なのだけど、テストROMが期待するよりもNMI発生が早い...という状態っぽくて ??? 状態。よくわかってない。あと、decay ppu openbusがよくわからず未実装。ppu openbusのテスト通しておきたい気持ちはある。ぽよよ

github.com

現時点で自分が主に使ったテストROMたち

Test SingleRom Result
blargg_ppu_tests_2005.09.15b palette_ram.nes OK
blargg_ppu_tests_2005.09.15b sprite_ram.nes OK
blargg_ppu_tests_2005.09.15b vbl_clear_time.nes OK
blargg_ppu_tests_2005.09.15b vram_access.nes OK
branch_timing_tests 1.Branch_Basics.nes OK
branch_timing_tests 2.Backward_Branch.nes OK
branch_timing_tests 3.Forward_Branch.nes OK
cpu_dummy_reads cpu_dummy_reads.nes OK
cpu_dummy_writes cpu_dummy_writes_oam.nes OK
cpu_dummy_writes cpu_dummy_writes_ppumem.nes OK
cpu_exec_space test_cpu_exec_space_apu.nes Failed
cpu_exec_space test_cpu_exec_space_ppuio.nes OK
cpu_timing_test6 cpu_timing_test.nes OK
instr_misc 01-abs_x_wrap.nes OK
instr_misc 02-branch_wrap.nes OK
instr_misc 03-dummy_reads.nes OK
instr_misc 04-dummy_reads_apu.nes Failed
instr_test-v5 01-basics.nes OK
instr_test-v5 02-implied.nes OK
instr_test-v5 03-immediate.nes OK
instr_test-v5 04-zero_page.nes OK
instr_test-v5 05-zp_xy.nes OK
instr_test-v5 06-absolute.nes OK
instr_test-v5 07-abs_xy.nes OK
instr_test-v5 08-ind_x.nes OK
instr_test-v5 09-ind_y.nes OK
instr_test-v5 10-branches.nes OK
instr_test-v5 11-stack.nes OK
instr_test-v5 12-jmp_jsr.nes OK
instr_test-v5 13-rts.nes OK
instr_test-v5 14-rti.nes OK
instr_test-v5 15-brk.nes OK
instr_test-v5 16-special.nes OK
nestest nestest.nes OK
oam_read oam_read.nes OK
oam_stress oam_stress.nes OK
ppu_open_bus ppu_open_bus.nes Failed
ppu_read_buffer test_ppu_read_buffer.nes OK
ppu_vbl_nmi 01-vbl_basics.nes OK
ppu_vbl_nmi 02-vbl_set_time.nes OK
ppu_vbl_nmi 03-vbl_clear_time.nes OK
ppu_vbl_nmi 04-nmi_control.nes OK
ppu_vbl_nmi 05-nmi_timing.nes OK
ppu_vbl_nmi 06-suppression.nes OK
ppu_vbl_nmi 07-nmi_on_timing.nes OK
ppu_vbl_nmi 08-nmi_off_timing.nes OK
ppu_vbl_nmi 09-even_odd_frames.nes OK
ppu_vbl_nmi 10-even_odd_timing.nes Failed
sprite_hit_tests_2005.10.05 01.basics.nes OK
sprite_hit_tests_2005.10.05 02.alignment.nes OK
sprite_hit_tests_2005.10.05 03.corners.nes OK
sprite_hit_tests_2005.10.05 04.flip.nes OK
sprite_hit_tests_2005.10.05 05.left_clip.nes OK
sprite_hit_tests_2005.10.05 06.right_edge.nes OK
sprite_hit_tests_2005.10.05 07.screen_bottom.nes OK
sprite_hit_tests_2005.10.05 08.double_height.nes OK
sprite_hit_tests_2005.10.05 09.timing_basics.nes OK
sprite_hit_tests_2005.10.05 10.timing_order.nes OK
sprite_hit_tests_2005.10.05 11.edge_timing.nes OK
sprite_overflow_tests 1.Basics.nes OK
sprite_overflow_tests 2.Details.nes OK
sprite_overflow_tests 3.Timing.nes Failed
sprite_overflow_tests 4.Obscure.nes Failed
sprite_overflow_tests 5.Emulator.nes OK
vbl_nmi_timing 1.frame_basics.nes OK
vbl_nmi_timing 2.vbl_timing.nes OK
vbl_nmi_timing 3.even_odd_frames.nes OK
vbl_nmi_timing 4.vbl_clear_timing.nes OK
vbl_nmi_timing 5.nmi_suppression.nes OK
vbl_nmi_timing 6.nmi_disable.nes OK
vbl_nmi_timing 7.nmi_timing.nes OK

References

今年?

前回から1年ほど経つらしい。

あれからorchestratorで中間マスターありの構成管理にしてリスク*1を減らし、マスターDB切り替えによる影響を約200ms程度*2に抑えるやつを作って、深夜ノーメンテでMySQL-5.6から5.7に上げていったりした。 GTIDの世界が到来して、P-GTID&MSRのHAのために作ったgohmsrは概ね役目を終えたのだが、GTID&MSRのサポートもしてるのでgohmsrは今も元気。OSSにしても良いと思うけど、めんどくささが勝ってしまう。

gh-ostも使ってる。MIXEDかつレプリカ側のみでtriggerが仕込まれてる運用だとROW fallbackしてつらぽよだけど、ROW fallbackしないフェーズになったタイミングでレプリカ側をうまく調整してmigrationしている。なかなかつらいですね。

Goを書く機会を得るために春ぐらいにNES emuを書き始めたんだけど、CPUだけ書いて止まっている。時間の余裕がなくなったタイミングかな。

数年振りにコードを書く機会が増えてきて、良い機会だと思ったのでEmacsバインドからVimバインドに改宗した。(VSCodeだけど)

Debeziumに触れる機会もあって、わけあってbinlog使ってごにょごにょするツールも書いたりしてた。debeziumもgo-mysqlももうちょっとなんとかならんかな.....。

Github Actionsで少し遊んだ。公開されているskeema-diffのgithub actionsは気になるところがあったので、少し手を入れたりしてcommitの山を築いた。 f:id:ichirin2501:20201227140302p:plain

英語は去年の7月ぐらいから、続けたりさぼったりしている。オンライン/コーチ付きで毎週10時間を約一ヶ月間続けてみたこともあったが全く効果はなく脱落とか。 今のところ、自分にとって最も学習効果を得られているのは「ビジュアル英文解釈 (Part1)*3」。「英語ドキュメントが読めないのでコードを見に行く」というスタンスから「まぁ英語ドキュメント読むか...」に変わったのは大きな進歩のはず。

これはベランダで飼い始めたメダカたち。 f:id:ichirin2501:20201116125808j:plain

*1:最新のbinlog問題

*2:色々オーバーヘッドがある関係でこれぐらい、速くはない

*3:結婚祝いでいただいた本、感謝

最近

たまにはブログも書いてみる。

最近?は、2019-07-04 Mercari meetup for SRE Vol. 2 にて登壇。ちょうどPercona XtraDB Cluster導入とかをやってたのでネタ自体は決まってたがネタが薄くてどうしようって直前まで呟いてた気がする。別にいいかって思って資料は公開していない。

mercari.connpass.com

既存のMySQLから移行するときに本番マスターDB(MySQL-5.7) -> PXC(5.7系、1台のみ) の非同期レプリの状態で、MTS-onでも夜中のピーク時にはレプリ遅延する箇所だったのでロールバック体制は準備していたものの、切替時は結構怖かったなぁ(これがPXC初導入)。


他には 2019-09-26 db tech showcase Tokyo 2019 にて登壇。タイトル「メルカリにおけるMySQLの運用」で発表して、こちらは資料が公開されている。
www.db-tech-showcase.com

主にorchestrator導入の話をした。登壇後にTwitter眺めてて2段階F/Oの話は意外と好評だったのでほっとしたのを覚えている。あと db tech showcase はこれが初参加だった。会場だと一人で良い感じに休む場所がなくてずっとウロウロぼっちしてた。

そんな感じ。

2019-11-02 10:46 追記:
こちらがいただいたイルカさんです。
f:id:ichirin2501:20191018143008j:plain