Archive: 2017

タグ・月別アーカイブ

Disk Checker

ドライブレコーダー用にMicroSDを何枚か買いました。SDカード系って偽物とかありますよね。自分は信頼できる店でしか買わないのでひっかかったこととかないつもりですが...。

チェックするツールもWindows用でいくつか検索で見つけることができますが、色々と面倒なので低機能なものを作ってみました。

  • node.jsで200行未満
  • ディスクが一杯になるまで指定ディレクトリに再現可能な乱数系列の256MBのファイルを作成し続ける
  • ディスクが一杯になったら、作成したファイルを検証する
  • ついでに読み込み・書き込み速度を測る

低レベルで検査しているわけではないので、全エリアはチェックしていません(256MB未満の残り領域、アライメント部分、ディレクトリ情報等)。デバイスファイルを使えばできますが、オペミス怖いしそこまでやらなくてもいいと思いましたのでこのような実装にしました。

https://github.com/Bugfire/diskchecker.git にあります。

RayProfiler

簡単なデバッグ用スクリーンインジケータを作りました。
ゲーム開発でよく見る奴です。

車輪の再発明というか、標準の Profiler でよくね?と思いますが、私もだいたい同意です。

RayProfiler

  • 上の白い四角がTargetFPSの範囲になります。グラフがはみ出すのは処理が間に合っていないときです。
  • 赤がRender、グレーは1フレームの時間です。Editor 上のスクリーンショットなので TargetFPS とグレーが一致していませんね。
    Physics, Update, LateUpdate, Animation 等の処理別に処理時間を計測していますが、Render 以外は目立ちません。
  • 下が過去60フレームの1フレームの処理時間/1フレームの時間のグラフです。
  • GCがあったフレームはグラフ上で赤/黄で目立つように表現されます。

特徴

  • リリースビルドでも動く(むしろ、止めたければどうにかいじってください)
  • 動的なメモリ割り当て無し(例外あり、後述)
  • スクリーンに描画を行うので、実機で確認可能

動的なメモリ割り当てなし

プロファイル、描画等で動的なメモリ割り当ては行なっていません。固定バッファでやりくりしています。

例外は、 yield WaitForEndOfFrame を行なっている部分で、Unity側の MoveNext () で毎フレーム16byte確保されます。
誰か防ぐ方法教えてください。

RayString

低機能なStringモドキです。使い方は例を見ればわかると思います。

var r = new RayString(100);
r.AddStr ("Foo").AddInt (10).AddStr ("Bar").AddFloat (0.5f, 0, 1);
Assert.AreEqual(r.ToString (), "Foo10Bar0.5");

上の例では、ToString ()でnew stringされていますが、char[] Bufferを参照することで動的メモリ割り当て無しで中身が取り出せます。

実装上の都合で(floatの内部表現が面倒なので)、AddFloat の精度は低いです。float の持つ精度を超える小数部の桁数を指定した場合、
C# のライブラリでは0でフィルされますが、このAPIでは精度以上の部分はゴミが入ります。

バッファが溢れそうなときは拡張を行うので、このときは動的メモリ割り当てを行います。

RayCanvas

デバッグ用簡易Canvasです。文字列と矩形しか表示しません。
Mesh 用のデータを静的に持っておくことで、動的割り当てを回避する実装になっています。
データサイズは静的になりますが、表示内容が少なくても多くてもメモリ消費も描画コストもかかります。

参照

パッケージとソースはgithubにあります。

Unity5.3, 5.4, 5.5. 5,6でパッケージを作りましたが(疲れました)、ソースは同一です。サンプルprefabをそれぞれのバージョンで生成しただけです。

QNAP NAS DLNA / ffmpeg 変換

家で家族の動画を共有している QNAP / DLNA が最近動いていないのでメンテをしました。

  • TwonkyServer がメンテされていないみたいなので、標準の DLNA Server に置き換えました。
  • PS4 から見に行くと反応が遅いですが、一応動いていますね。
  • もともと、MTS がうまく再生できていなかったのは、やっぱりうまくいかない。
  • トランスコード設定をしてみるが、やっぱりうまくいかない。
  • ログをみると変換に失敗しているようだ。

昔は、自分で QNAP 上で ffmpeg を実行して再生可能にしていたので、思い出しつつ実行してみる。

  • 過去のスクリプトではやっぱりうまくいかない。
  • コマンドラインオプションが違うようだ。ffmpeg のバージョンが違うかな?
  • ググってみると複数の ffmpeg が入っているようだ。確かに。
  • 新しい方でもやっぱりこける。ググってみるとライセンス上の問題で AC3 を外しているようだ。

しょうがないので自前ビルドしてみる。

  • ipkg がない...。これも紆余曲折あって App Center から入らないようだ。
  • こちらからインストール
  • /opt/bin/opkg install ffmpeg

なんとか動作。

AssetBundle の圧縮(4) 圧縮下段

圧縮

下段として通常の圧縮を試してみます。その前に、先人の知恵を見て見ましょう。

参考:.NET Compression Libraries Benchmark

何も考えずに.NETのDeflateと、性能が良さそうなLZMAを試して見ることにします。

LZMAはPublicDomainの7Zip SDKを使用します。

結果

方法 サイズ
RAW 4198973
LZ4 876341
LZMA 609787
圧縮 2381911
二段圧縮(.NET) 409940
二段圧縮(LZMA) 318962

ようやく、素のLZMAの半分くらいになりました。DeflateとLZMAは、速度とサイズのトレードオフでしょうか。

サンプルソースは、 https://github.com/Bugfire/test_assetbundlecompress に置いておきました。

追記

2016年のOSS圧縮ツール選択カタログ を読んだら、zstdのC#版が欲しくなってきました。native wrapperは存在しましたが、なんとなく。

AssetBundle の圧縮(3) 圧縮上段

圧縮の方針

仮定

  • アーカイブ内に存在するファイルの内容は、同一オフセットには同一のデータが入ることが多い。

実装

アーカイブ全体からファイル名部分を検索するのには、有名な Boyer-Moore String Search アルゴリズムを使います。
wiki にソースすらあるので、それを参考にしても良いですが、今回は StackOverflow の記事から使用させていただきました。

参考:Search longest pattern in byte array in C#

ファイル名で区切られた領域をブロックとみなし、ファイル中の全ブロックと全ブロックを比べ、同じオフセットで同じデータ
が入る部分を抽出し、出力は、データブロックと参照ブロックが並ぶ構成にしました。頭の悪い辞書圧縮という感じです。

正確にデータ部分が抽出できれば、PVRTC/ETC1ともに8byteが1blockなので、それを利用して、オフセットによらず圧縮テクスチャ特化型辞書圧縮もできそうですが、手間をかけない方針なのでやりません。

参考:Disunity on github

結果

方法 サイズ
RAW 4198973
LZ4 876341
LZMA 609787
圧縮 2381911

大部分が同じデータなのでだいたい半分にはなりましたが、通常の圧縮をしていないのでまだまだ大きいですね。

(4)へ続く。