Performance Code Review 2026 10 07 - log5r/simple-media-player GitHub Wiki
性能重点のソースコードレビュー(2026-10-07)
2026-10-07、main の 86eb6b90a50087e31310a7775ce7451cb8816245(PR #21 マージ後)を対象に、ソース全体を性能を重点に読んだ記録。アプリのソースは変更していない。実装の読み取りに基づく指摘であり、Instruments や実機での測定は行っていない。各 Issue に「未測定」と明記した項目は、修正時に計測して確認する。
レビューは 5 領域(ライブラリ・永続化、再生エンジン、埋め込みタグの読み書き、上部ビューと設定、LED デッキ)に分けて読み、複数の領域から独立に挙がった指摘(再生時計の 30Hz 更新、変換書き出しの進捗通知、MainActor 上のブックマーク解決)を優先した。#9〜#13 の修正済み項目は再報告せず、残っている部分だけを記録した。
起票した Issue
| 優先度 | Issue | 要点 |
|---|---|---|
| P1 | #23 | 再生時計の 30Hz 更新が詳細エリア・iPhone デッキ・LED パネル全体を再評価する。先頭曲の再生中だけ重くなる |
| P1 | #24 | アルバム詳細の各行で全曲を再グループ化する |
| P1 | #26 | macOS の M4A 取り込み・編集で曲ごとに Music への AppleScript を実行し、Music の古い値が編集結果に混入する |
| P1 | #29 | 動画音声のタップがリアルタイムスレッドでメモリ確保とロック取得を行う |
| P2 | #25 | 一覧行とスナップショット生成の曲ごとのファイルシステム照会。取り込み中の全件再取得 |
| P2 | #27 | 一括編集の曲ごとの全ソース再読込・全ファイル複製・保存。進捗とキャンセルの不在 |
| P2 | #28 | MainActor 上のブックマーク解決・ファイル削除の一括経路 |
| P2 | #30 | 変換書き出しの進捗がレンダーバッファごとに MainActor へ通知される |
| P2 | #31 | LED デッキの毎フレームのパス生成、マーキーと解析の停止中・背面での継続 |
| P2 | #32 | タグ保存の全ファイル複製と Ogg のビット単位 CRC |
| P2 | #33 | 楽曲解析キャッシュがタグ編集で無効化される。アクター内の同期デコード |
| P2 | #34 | 曲切り替えの準備がフェードアウト後に始まる。協調スレッドプールの長時間占有 |
| P2 | #36 | 消した歌詞・タグ値が再起動後や別ソースから復元される |
| P2 | #38 | MP4 の hdlr なし meta 生成と断片化 MP4 のオフセット未補正 |
| P3 | #35 | プレイリスト追加と書き出し名入力のキー入力ごとの全件走査 |
| P3 | #37 | 曲終端コールバックに読み込み ID の検証がない |
| P3 | #39 | ID3v2.4 のフレームフラグを無視して本文を解釈する |
修正の順序は、差分が小さく効果が広い #23(currentTime の読み取り箇所の限定と tick() の同値代入の抑制)、#24、#30 を先に行い、次に取り込み・編集経路(#25、#26、#27、#28)、再生経路(#29、#34)、デッキ描画(#31)の順を想定している。
Issue #23 の修正内容と検証結果は 再生時計の監視範囲と回帰検証 に記録した。
読んで問題なしと確認した点
AudioEngineServiceのload/seek/pause/suspendとscheduleSegmentの完了は、loadGeneration・activeLoadID・scheduleGenerationで古い結果を退ける。例外はonFinishedだけ(#37)。SpectrumAnalyzerの内部状態は専用の直列キューに閉じ、MainActor へは値コピーを渡す。停止・シーク後の古いフレームは世代で退ける。FFT の setup と窓は再利用している。AVAudioEngine 側のタップは描画スレッド外で動く。- 再生用の PCM をメモリに保持する箇所はない。拡張形式の PCM はディスク上のキャッシュと参照カウント付きのリースで管理され、
docs/extended-audio-formats.mdと一致する。 LibraryArtworkView・LyricsPanelView・MediaInfoView・BulkMetadataEditView・SeekBarView・PlayerViewModel.playは、非同期結果の適用時に項目 ID や世代を検証している。- VU メーターの文字盤とガラスは静的な Canvas に分離され、針だけが再描画される。アイドル時の
TimelineViewは停止する。 - LED 表記(EQ/KEY/SPEED/VOLUME/ON/OFF/BPM)は
Text(verbatim:)かshouldTranslate: falseで扱われ、アクセシビリティ文言には日本語が用意されている。コードで使う文字列カタログのキーに欠落はなかった。 - ID3 の v2.2/v2.3/v2.4 のサイズ符号化・拡張ヘッダー・フッター・UTF-16 BOM、MP4 の 64 ビットボックスと
co64、Ogg のページ CRC パラメータ・ラシング・シーケンス伝播、WAV の RIFF サイズ、FLAC の最終ブロックフラグは仕様どおりだった。
未検証の項目
@Queryが未保存の挿入ごとに配列を更新するかどうか(#25 の M×N の前提)。URL(fileURLWithPath:)のディレクトリ判定が相対パスでも stat を発行するか(fs_usageで確認する)。- Music ライブラリの規模ごとの AppleScript 1 回の所要時間(#26)。
- 動画再生での音切れの再現頻度と、動画タップのバッファ長による発光レート(#29)。
- ID3v1 と v2 が併存する MP3 で AVFoundation がどちらの値を返すか(#36)。
- WAV/AIFF で最終チャンクが奇数長かつパディングなしの場合、
canWriteは true を返すが保存は失敗する。許容する価値があるか未判断のため Issue 化していない。 MediaInfoInspectorはプロジェクトの既定分離で MainActor 上の同期resourceValuesを行う(#28 に補足として記載)。