2015年12月31日

年末のご挨拶です

 



 




「 私の部屋に薄い本などあるが 今は話したくない 」



 



 






じょしらく 時そば




今年も 年またぎは 『じょしらく ドラマcd』 を聞きながら過ごしてまいりましょう
大晦日らしく 演目は 『ときそば』をチョイスしてみます。 ドラマCD版のマリーさん CV:阿澄佳奈さんです

じょしらく動画 前回いつだっけ?
さいきん正月に『和尚が2(ツー)』って聞かされなくなった


2年前だったよ (´・ω・`) ナツカシネー


今年気づいたことは ブログ更新をサボると書き方を忘れる
ので 2016年は定期的に記事を書いていこうと思った所存 カタジケナイ



dat151230064148.jpg


今年も29から31日までの3日間 東京ビックサイトにおいてコミックマーケット89が開催されました


例の紐 フミナさま 夜のヤッターマン 一瞬で過ぎ去るブーム


おれたちは同人絵かき・・・
紙キレ同然 己の薄い本
萌えつきるのに
わずか数秒・・・

的な



生活かかってる人もいるから 確実に売れるネタをチョイスしないと大変なことになっていしまいます

応募締め切りが半年前だから 半年先のブームを読み切るすごい嗅覚だよね

ちなみにどうしてもネタがなくて困ったときは”ドラクエ”をネタにするんだとか聞きました

ドラクエのファンは年齢層が高くて懐に余裕があるのでドラクエネタであれば

手にとってくれるし複数買いしてくれるので安定株なんだそうです。

すごく売上げがあるわけではないけど次のコミケまで生活できるぐらいの儲けが期待できる鉄板ネタだとか




そういえば同人誌は発売されると即日翻訳されてアップロードされてしまうので

いちはやく翻訳版を読むためにロシア語や中国語をマスターする人がいるとか 前にどこかで見たよ

今は知らないけど

努力の方向がよくわからない




コミケの華は 同人誌 &たぶん物販とか ( てきとーだなおい)

検索してみると抱き枕は相変わらず需要が高いみたい

ヲタクイズビューティフル

「 3次は枕営業があるから2次最高! 」

っていうけど 2次嫁は作品が売れても売れなくても安定の枕営業です


no title

そういえば抱き枕の記事前に書いてたね
終わらない すごい 絵コンテ






ネット界隈で話題の 声優研究同人誌とか





no titleno titleno titleno titleno title

 


 


 


 


 


 


 



 



【画像】冬コミで発売されたこの同人誌頭おかしすぎるだろwwwww



声優ブームはいいけど声優さんもたいへんだよね 電話の種類特定されたり シャンプーの銘柄を調べあげられたり

写真のExifを削除しても 部屋の写真に写り込んだものやら窓の景色から住所特定とか

そりゃ声優さんも塩対応したくなるわ

塩対応はしょっぱい対応(つれない対応)という意味だそうだけど


塩対応と聞いて

ファン「私の不注意です、塩がなくなりますが手に入りませんか?」
声優さん「塩?塩か?」

みたいなオタク的戯れかと思ったのは秘密よ

いまどきノ子がファーストガンダムもないか



no title
あと前回C88 のこれはちょっと欲しくなったかな ちなみにパラメータふってあるけど これデュエルできるの?




同人ゲーム c89

同人ソフトを忘れていました がんばってるなー
好きなモノが作れる幸せ(重い言葉)






no title

ちなみに今年のコスプレ一等賞を選ぶならコレです
困ったような表情といいシチュエーションといい最高





ということで

今年はほとんど更新できなかったけど

2016年はなんとか更新頻度を上げていきたいので よろしくおねがいします





そういえば 掃除してたら5年前に描いた漫画が出てきた エロだけどw
古川さとしさん という成年小説?官能小説? を書かれているお友達のHPにプレゼントしたもので 同人誌ではない

詳しくはぐぐる





失望しました ぶぎょうさんのファン辞めます




no title


no title



おまけ1 今年話題になったものを無理やり動画で振り返る





■ スターウォーズ 新作エピソード公開




STAR WARS 子門真人

子門真人カバーの スターウォーズのテーマ。 日本サイドが勝手に歌詞をつけてレコードを製作したため ルーカス激おこで速攻回収されてしまいました 絶版のため貴重な音源みたいですよ。 ルーカスフィルムもディズニーの軍門に下ったことですし
ディズニーの偉い人新作エピソードでつかってみませんか?
宇宙からのメッセージ。。。 銀河大戦。。。 を見てルーカスが腹を抱えて笑ってたそんな時代



スタジオジブリ散開




風の谷のナウシカ

おなじみ安田成美の風の谷のナウシカ ちなみに当時映画館でこの曲は流れていません。
松本隆&細野晴臣タッグで楽曲としてはよろしかったのですが、当時 宮駿監督は「ヴォルガの舟唄」
のような荘厳な曲をイメージしていて
映画公開の直前にこの曲を聞き あわてて全国の映画館に曲差止めの通達が出されました。
・・ですが一部地方の映画館は差し替えが間に合わず 映画を台無しにされてしまったようです



no title
そういえば年末になって急に ナウシカ姐さん漫画がとりあげられてたんだが なにか起きているんだろうか? 田中圭一先生が 一周回って注目を集めだしているのか? 『おそまつさん』のエンド絵あたりがきっかけなんかな わからん





笑っていいとも終了




ネバーエンディングストーリー

ネバーエンディングストーリーBD化を記念して(いつのはなしだよ) 羽賀研二カバーの ネバーエンディングストーリーのテーマです。 いいとも青年隊からタレントや役者もこなし 『ストリートファイターII MOVIE』のケン役で声優としても高性能でしたが、サギ容疑で逮捕されてしまったのは記憶にあたらしいところ ウィキペディアの代表作『サギ師一平シリーズ』は狙い過ぎな気もします だが GJ。

「♪照れた男のジグザグをわかってくれ~」突っ込みどころ満載の歌詞ですが、 昭和の歌謡曲では「ジグザグ気取った~」「照れてジンジ~ン」「ギザギザハートの子守唄~」のように繰り返す濁点のはいったワードをつかうとヒットするというジンクスがあったのです 竹本孝之の『てれてzinzin』はヒットなの?。 ジブリ作品がヒット祈念でタイトルに「の」をつけるジンクスみたいなものです たぶん。。 『となりの山田くん』なんてなかった




おまけ2 2015年個人的ヒット商品




アリエール 洗濯洗剤 液体 パワージェルボール(アマゾンだと¥360くらい)
no title
洗濯物に一度ついた匂い(納豆みたいなくさったかおり)は絶対に落とせないはずだったのに それを取り去る快挙をアリエールがやってくれました 強力な殺菌効果で部屋干しなどで染み付いた匂いをカットする業界初の ありえなーい商品 こんなんでいいかな?
これは売上1位になるわけだわ
魔法みたい






北越 たまねぎおかき 12枚×12袋 (アマゾンだと2800円ぐらい)
no title
玉ねぎの香ばしい香りと さくさくの食感で ’開ければ最後ユーキャントストップ’ そんな禁断のお菓子
(このキャッチはプリングルスのCM)
Box12袋が数日で消費されます。 危険ですから食べないでください アマゾンの在庫がなくなると管理人が死にます。










akinow at 22:09|PermalinkComments(2)TrackBack(0) Clip to Evernote 日記 

2015年11月30日

31日なんてなかった


こんにちは そろそろ生活をなんとかしたいと考えている管理人です


いちおう 近況を話しますと

「イラスト描いたこと無いけど仕事とっちゃったんで 描いてもらえない?」 そんな話からはじまった去年の夏。

ご存知のように現在斜陽なゲーム業界。 微妙に仕事が減って来ているので、フリーの人は不慣れな仕事にも手を出し始めているのですが 以前も書いたように流行に乗っかった日本全国萌擬人化イラストを使用したソーシャル系プロジェクトで、とにかく絵素材が大量に必要という話。

仕事絵を描いたことがないのに50枚のイラスト仕事を受けるとか心臓強すぎなので、ちょっと痛い目にあったほうが本人のためじゃないのかと考えもしたのですが 商品レベルではないイラストを提出させるわけにも行かず 完成してるという説明だったところまで描きなおしたりで スケジュールを大幅にぶっちぎって行くことになるのでした。

自分は当初仕事が減った分をIT系の仕事で埋めようとしていて すでに企業向けのクラウドサービスのお仕事をいただく手はずになっていたのですが その学習に当てる準備期間が吹っ飛んでしまい 作業が泥沼化していくのです。

その後、いわゆるサイトバレが発生してしまい 仕事が押している状態でのつぶやきやブログの更新が困難になったという次第。

つまり この先更新が長期間ないときは管理人が危険水域にいると察してくださいというお願いです。

IT系作業も慣れてきて時間が取れそうなので 頑張って更新しようとは考えてますけどね さすがにブログの休眠期間長すぎた



そういえば今年も12月末には冬のコミケが開催されますが 最近「このデザイナーさんはコミケに行かれますか?」という質問をクライアントの方から何度も確認されるので、理由を聞いてみたところ
「プロジェクトのマスターアップ直前」や「作業提出後に修正のため待機」をお願いしているデザイナーが
コミケに参加するために連絡を断ってしまうケースが多くて、電話がつながらなくスケジュールが押していると年末だと特にですが、代わりのデザイナーを探そうにも連絡がつかずに現場がパニックになってしまうということで確認を何度もしているそうです。

もちろん代打のデザイナーにも迷惑はかかるわけですが( 私にだ ) 
クライアントにあまり酷い仕打ちをすると裏で名前が回ってお仕事が来なくなる場合がありますので、きちんと一報入れておくことをおすすめします。人として 

ちなみにこの話 デザイナーに限らなくて、社長がアニメ世代だと社員全員でコミケに参加して連絡がとれなくなるケースもあるみたいです 一つはこの前倒産したような気がしますが。 

信用って大事



そんな ここがヘンだよ日本人話でした。



おしまい


akinow at 10:56|PermalinkComments(0)TrackBack(0) Clip to Evernote 日記 

2015年10月05日

うにばな メモリ使用量の最適化・ヒープメモリ ほか

 

 

ヒープメモリやらメモリ管理で検索が多いので記事にしてみたのですが 久しぶりのブログ更新なので後半部分をまとめたところで力尽きました。力尽きました

メインは海外サイトの翻訳なのですが どうにもわかりにくい。メモリ管理で検索するんだからわりと初級?だもの この説明では難しいことでしょう

後日改めて、 もう少しわかりやすくまとめた前半部分を追記しますのでこのページにリンクを貼らないで置いてください。

<文字列制限があるので記事を分割するとアドレスが変わる可能性があるのです>


追記:10.8 スケジュール的にムリでした。。。ほかのサイトで補完してください




 

 ヒープメモリとは?                                              

更新予定

■とりあえずはここらへんを読んでおいてください

  • Unity - マニュアル- 自動メモリ管理を理解する
  • 【Unity】Unite 2015「Unity パフォーマンス・チューニング」レポート – Qiita
  •  

     

     不必要なヒープ割り当ての一般的な原因               

    この元ブログ記事では以下の様な内容でメモリ管理について論じています

    1. メモリ管理とメモリリークの一般的な原因
    2. ユニティプロファイラによるメモリリークの検出
    3. C#でのオブジェクトプーリング

    ここから元記事の意訳

    • この最初の投稿は.NETとMonoのガベージコレクトされた世界のメモリ管理の基本について議論します。またメモリリークのいくつかの一般的な原因について説明します。
    •  
      2番目の投稿はメモリリークを発見するためのツールについてです。Unityプロファイラは、この目的にとって素晴らしいツールですが、それはまた高価です。そこであなたが唯一の無料ツールでメモリリークを発見する方法をお見せするために、.NETの逆アセンブラと共通中間言語(CIL)について議論します。
    •  
      3番目の投稿は、ふたたびC#のオブジェクトプーリングを議論します。ここでも焦点はUnity/ C#の開発で生じる特定のニーズです。

     

    ■ガベージコレクションの限界

    最近のほとんどのオペレーティング・システムでは、スタックとヒープに動的メモリを分割します。多くのCPUアーキテクチャ(PC/Mac そしてスマートホン/タブレットが含まれます)でこのような命令セットがサポートされています。c#では値の型を区別することでこれらをサポートしています(単純な組み込み型などとして宣言されているユーザー定義型  enum  または  struct)と参照型(クラス、インタフェース、およびデリゲート) 値型はスタックに参照型はヒープに割当てられます。スタックは新しいスレッドの開始時に設定された固定サイズを有しています。これは通常は小さくて たとえばwindowsのデフォルトの.Netスレッドは1Mb。このメモリはスレッドの主な機能とローカル変数をロードし メイン関数から呼び出される関数(それらのローカル変数)をアンロードするために使用されます。その一部は動作を高速化するためにCPUのキャッシュにマッピングすることができます。コールが深すぎないかローカル変数は巨大すぎないかといったスタックオーバーフローを恐れる心配はありません。スタックのこの使われ方は構造化プログラミングの概念と整合することを確認してください。

     

    オブジェクトがスタックに対して大きすぎる場合またそれらの機能がスタックに長く残ってしまった時にヒープが発生します。ヒープはそれ以外のメモリの箇所で 通常はOSとプログラムの規則の要求通りに増加します。一方スタックにある場合はメモリ管理をするのは簡単で(フリーなメモリの場所を記憶するためにはポインタが使用されます) ヒープを管理することは,ヒープが断片化した場合すぐに割当てられたオブジェクトからオブジェクトを開放させる要求をださなければならないことは明らかで,すべてのスイスチーズの穴のような場所を覚えることに気を止めなければならず 全く楽しくありません。そこで自動メモリ管理を導入します。 自動割当てのタスクは 主にあなたにとってのすべてのチーズの穴のようなメモリ断片を追跡する簡単なもので実質すべてのプログラミング言語でサポートされています。 自動割当てをする決定の多くの困難なタスクを特にあなたが心配する必要はなくオブジェクトは割当て解除の準備ができています。

    この後者のタスクは、ガベージコレクション(GC)と呼ばれています。あなたのランタイム環境を伝える代わりに 実行時に一定の間隔でオブジェクトへのすべての参照を追跡し確定後オブジェクトが破壊されてメモリが解放されたときに おそらくコードからオブジェクトに到達できなくなります。ガベージコレクトは未だに学者によって活発に研究されていることが ガベージコレクトのアーキテクチャが。Netフレームわーっクから大幅に変更と改善をされている理由です。またUnityはMONOの最新バージョン(2.11 / 3.0)にデフォルト設定はありませんが、その代わりに バージョン2.6を使用しています(正確には、私のWindowsの2.6.5は、Unityの4.2.2 がインストールされています。Unty4.3についても同様です) あなたが自身でこれらを確認する方法に不明な点があるようであれば 次の投稿でそれを説明していきます。

     

    バージョン2.6以降のMONOに導入されたGC関連は主要な改変のひとつです。新しいバージョンがGenerational GC(世代別GC)を使用しているのに対し バージョン2.6ではまだあまり洗練されていない ベームガベージコレクタを使用しています。最近の世代別GCはゲームなどのリアルタイムアプリケーションのために(制限内ですが)良好に動作します。ベームスタイルのGCは一方で比較的まれな間隔(通常は一回あたりのフレームのゲームに比べてはるかに少ない頻度)でヒープ上のガベージごみを徹底的な検索を実行して動作します。これによって一定の間隔でフレームレートの低下が引き起こされる圧倒的な傾向があり プレーヤーは迷惑を蒙(こうむ)ります。UnityのドキュメントではFPSが低下する状態の場合にはSystem.GC.Collect()を呼ぶことを推奨しています(例えば、新しいレベルのロードやメニューを表示する時) しかし多くのゲームの種類においてこのような機会はまれにしか発生せず あなたがGCのをしたい時にガベージコレクトを拒否するかもしれません。あなたの唯一の選択肢は勇敢にメモリを自分で管理することで、それについて残りの2つの記事で述べています。

     

    ■メモリマネージャを適切なものに

    ユニティ/ .NETの世界では「メモリを自分で管理する」ことを意味するかについて明確にしてみましょう。メモリ割当てがされる方法に影響を与えるためのあなたの力は(幸いなことに)非常に限られています。あなたは クラス(常にヒープ上に割り当てられた)または  構造体(クラス内に含まれていない限りスタック上に割り当てられます)のカスタムデータ構造を選択し採用することができます。あなたがより多くの魔法の力が必要な場合は、C#のUnsafe コードのキーワードを使用する必要があります。しかしUnsafe コードは、UnityのWeb Player及びおそらく他のいくつかのターゲットプラットフォームで実行されないことを意味している検証できないコードです。このことと  その他の理由により安全ではありませんので使用しないでください。

    ※Unite EUROPE2015のKEYNOTEを観る限りではUnsafeコードは普通に使用されているようですが?

    そのためスタックの上記の制限およびC#の配列がためだけの糖衣構文であるためのSystem.Array(これらはクラスです)自動ヒープ割当てを避けることはできません。不要なヒープの割り当てを何によって避けるべきかをこの記事の次の(そして最後の)セクションで知ってください。

    メモリ割当て解除されるまではあなたの及ぶ力は限定的です。実際ヒープされたオブジェクトの割り当てを解除することができる唯一の方法はGC(ガベージコレクト)であり その働きはあなたから遮蔽されています。ヒープ上のオブジェクトのいずれかへの最後の参照がスコープ外になったときにGCがその前にそれらに触れることができないため、何らかの影響を与えることはできます。定期的なガベージコレクション(あなたが抑制することができない)が解放するものがないときには非常に高速になる傾向があるため この制限された力は、たいへん実用的な関連性を持っていることが判明しました。この事実は様々なアプローチの基礎となるオブジェクトプーリングについて3番目の投稿で議論します。

     

     

    ■foreachループを避けるべきでしょうか?

    foreachループを使用する代わりにforまたはwhileループを使用するべき理由は、foreachは実際には単なるシンタックスシュガー(糖衣構文:読み書きのしやすさのために導入される構文)で、以下のようなコンパイラの前処理コードだからです。

    foreach (SomeType s in someList)
        s.DoSomething();

    ...次のように:

    using (SomeType.Enumerator enumerator = this.someList.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            SomeType s = (SomeType)enumerator.Current;
            s.DoSomething();
        }
    }

    foreach はenumeratorオブジェクトを生成します。 System.Collections.IEnumeratorインターフェースのインスタンス シーンの裏側で このオブジェクトはスタックとヒープのどちらに生成されるのでしょうか?両方が実際に可能であるため これは大変よい質問です。もっとも重要なことはSystem.Collections.Generic の namespace (List<T>, Dictionary<K, V>, LinkedList<T>, etc.)は構造体を返すのに GetEnumerator()メソッドは大変適しています(参考記事が書かれた時点ではUnityはMono 2.6.5を使用)

     

    foreachのループを回避する必要がありますか?Unityでコンパイル可能なC#のコードでそれらを使用しないでください。foreachを標準のgeneric collections (List<T> etc.) を用いて反復処理するために、あなたがC#のコードをコンパイルに最近のコンパイラを使用していますか?Visual Studioのほかに無料の.NET Framework SDKが適正であることを前提とし(ただし、確認はしていない)Monoと最新バージョンに付属しているMonoDevelopも同様に適正とします。外部コンパイラを使用して foreachループを反復するための他の種類のコレクションをどうすればいいでしょうか? 残念ながら答えはありません。 foreachを安全に使用するためどのコレクションを使用するかあなた自身が見つけ出すためのテクニックの使用法を次回のブログポスト元記事2で論じてみます。

     

    ※2

  • http://www.gamasutra.com/blogs/WendelinReich/20131119/203842/C_Memory_Management_for_Unity_Developers_part_2_of_3.php
  • http://monodevelop.com/
  •  

    ■あなたはclosuresやLINQを避けるべきでしょうか?

    C#では匿名メソッドやラムダ式(かなり互いに同一)が提供されていてdelegateキーワードと=>演算子 を用いてそれらを作成することが出来ます。これらはしばしば便利なツールであり List<T>.Sort()) や LINQ といったライブラリ関数を使用するときたいへん重宝します。 匿名メソッドとラムダ式は、メモリリークを起こしているでしょうか? それは依存しています C#コンパイラには、実際にそれらを処理する2つの非常に異なった方法があります。違いを理解するために次のコードを考慮してください。

     

    int result = 0;
        
    void Update()
    {
        for (int i = 0; i < 100; i++)
        {
            System.Func<int, int> myFunc = (p) => p * p;
            result += myFunc(i);
        }
    }

     このようにスニペットmyFuncというdelegateを1フレームあたり100回生成する計算を実行します。しかしながら Monoはヒープ割当てを最初にUpdate()関数(※筆者の環境で52Byte)が呼ばれた時だけ実行します。サブシーケンスでヒープ割当ては実行されません。どうなっているのでしょう?コードリフレクタ(part2を参照)を使用すると  C#コンパイラはmyFunc型の静的フィールドでSystem.Func <int 型、int型 >を含むクラスでUpdate()関数を単に置き換えることがわかります。 このフィールドには明示的な名前 f__am $ cache1を取得しています  (システム上で多少異なる場合があります)。つまりdelegatorは一度だけ割り当てられて、その後キャッシュされてるのです。

    今度は、デリゲートの定義にマイナーチェンジを作ってみましょう:

    System.Func<int, int> myFunc = (p) => p * i++;

     

    closuresは関数型プログラミングの柱です。closuresはデータに関数を結びつけます、より正確には関数外で定義される非ローカル変数に結びつけます。 このmyFuncの例の場合'p'はローカル変数ですが'i'はUpdate()関数に属する非ローカル変数です。 C#コンパイラはmyFuncをアクセスと非ローカル変数を更新することができるように変換する必要があります。 リファレンス環境にあわせて新規にクラスを宣言することでmyFuncの生成を実現しています。 このクラスのオブジェクトは、for-loopを通過するたびに割当てられるため(※筆者の環境ではフレームごとに2.6kb) 突然巨大なメモリリークに襲われます。

    もちろん closuresや他の言語機能がC#3.0で導入された主な理由はLINQです。closuresがメモリーリークに繋がることができればゲームでLINQを使用しても大丈夫でしょうか?LINQの一部はiOSなどの実行時コンパイラをサポートしないOS上で明らかに動作しません。メモリ管理の側面からLINQはとにかく良くありません。

  • http://answers.unity3d.com/questions/376884/using-linq-when-building-to-ios.html
  • クロージャ – Wikipedia
  •  

    次の信じられないような基本的な表現:

    int[] array = { 1, 2, 3, 6, 7, 8 };
    
    void Update()
    {
        IEnumerable<int> elements = from element in array
                        orderby element descending
                        where element > 2
                        select element;
        ...
    }

    毎フレーム68バイトを割当て( Enumerable.OrderByDescending() が28バイト、 Enumerable.Where()で40バイト)!

    ここでの犯人はclosuresではありません 拡張メソッド IEnumerable:LINQは最終的な結果を出力するために 中間の配列を作成する必要があり そのあとそれらをリサイクルするシステム領域を持ちません。(※私はLINQの専門家ではないので リアルタイムの実行環境で安全にそれらのコンポーネントを使用する方法はわかりません)

    ■コルーチン

    あなたがStartCoroutine()経由でコルーチンを起動した場合は、暗黙的にunityのインスタンスコルーチンのクラス(私のシステムで21バイト)とEnumerator(16バイト)の両方を割り当てます。yield's や resumesコルーチンは何も割当てをしません そこでメモリリークを回避するためにはゲームが実行されている間StartCoroutine()の呼び出しを制限してください。

    void Update()
    {
        string string1 = "Two";
        string string2 = "One" + string1 + "Three";
    }

    ■ストリングス

    C#とunityのメモリに関しては文字列に言及しない訳にはいきません。文字列は変わっていて、ヒープ割当てでありながらイミュータブルです。2つの文字列を連結するとき(これらの変数や文字列定数で)ランタイムは 結果を含む少なくとも1つの新しい文字列オブジェクトを割り当てることがあります。String.Concat()これはFastAllocateString()と呼ばれる外部メソッドにより効率的に行われます。(ただし上記の例ではシステム上の40バイト)。 変更または実行時に文字列を連結する必要がある場合にはSystem.Text.StringBuilderを使用します。

    オブジェクト指向プログラミングにおいて、イミュータブル(immutable)なオブジェクトとは、作成後にその状態を変えることのできないオブジェクト のこと

    ■ボクシング

    時々データがスタックとヒープを移動する必要があります。例えば 次のように文字列のフォーマットを設定する場合です:


    string result = string.Format("{0} = {1}", 5, 5.0f);

    次のシグネチャを持つメソッドを呼び出しています。
    public static string Format(
    	string format,
    	params Object[] args
    )

    言い換えると、整数「5」および浮動小数点数「5.0f」はSystem.ObjectがFormat()を呼び出した際にキャストする必要があります。 しかし、オブジェクトが参照型なのに対して他の2つは値型です。 C#はこのようにヒープ上の割り当てられたメモリに値をコピーすることがあり、Format()はint型とfloat型のオブジェクト参照を新しく作成します。 このプロセスがボクシング、 反対の動作をアンボクシングと言います。 このstring.Format()のビヘイビアは問題となるかもしれません すなわちヒープメモリからとにかくそれを取り除く必要があります(新しいstring のために) しかしボクシングは期待される場所に出現するわけではありません。悪名高い例として 等価演算子"=="を実装するとき (例えば、複雑な数を表す構造体)

    ※このような場合のボクシングを避ける方法についての記事をリンク先で読むことが出来ます。

  • http://stackoverflow.com/questions/10390782/why-cant-we-override-equals-in-a-value-type-without-boxing
  •  

    ■ライブラリメソッド

  • Dictionary<K, V>.KeyCollection と Dictionary<K, V>.ValueCollectionはクラスで構造体ではありません。 これらはつまり"foreach (K key in myDict.Keys)..."に16バイト割りつけるということです。
  •  List<T>.Reverse() は標準のインプレース配列反転アルゴリズムを使用しています、それがヒープメモリを割り当てないと考えるかと思いますが、少なくともMono 2.6バージョンでは間違いです。 ここで拡張メソッドは.NET/Mono バージョンで最適化されないときに代用出来るかもしれません。少なくともList<T>.Reverse()を使用するのと同じやり方で、ヒープ割当てを避けるための管理がなされます。

    public static class ListExtensions
    {
        public static void Reverse_NoHeapAlloc<T>(this List<T> list)
        {
            int count = list.Count;
    
            for (int i = 0; i < count / 2; i++)
            {
                T tmp = list[i];
                list[i] = list[count - i - 1];
                list[count - i - 1] = tmp;
            }
        }
    }

     

     

    ここから、これまでの考察をまとめた別記事の意訳です

     ■Unity、C#と.NET /モノラルでメモリ使用量を削減             

  • Reducing Memory Usage in Unity, C# and .NET-Mono - Andrew Fray
  •  

    iOSの上のUnityはMonoのヒープマネージャの初期のバージョンを使用しています。このマネージャは、パッキングを行いませんので、ヒープメモリが断片化された場合は新しいメモリを確保してしまいます。私はUnity開発者がこの問題を回避するために新しいヒープマネージャで作業している印象なのですが、今のところメモリリークを持つゲームは増え続けるメモリを消費してしまいます。C#は,すばやく読みやすさを犠牲にすることなく強力なコードを記述することができる楽しい言語です。しかしこの方法の欠点は自然なC#のコードを書くことがガベージコレクションの多くを生成してしまうことです。これを回避する唯一の方法はヒープ割当てを排除または低減することです。私は機能性を低下させることなく これを行うための便利な方法をリストにまとめました。最終的な効果として あなたのC#コードは,はるかにC ++のように見えC#の力の一部を失ってしまうものの それにより生きてきます副次効果としてヒープアロケーションは本質的にスタックアロケーションよりもよりCPU集約型なので、おそらく同様にいくつかのフレーム時間を節約できます。あなたの努力目標のためにユニティプロファイラは多くのメモリ割当てを作る作業を助けてくれます。情報は多くはないですが。プロファイラを開きゲームを実行し、CPUプロファイラを選択して、問題箇所をソートするためのGCアロケータカラムをタップします。はじめにそれらの機能にこれらのガイドラインを適用してください。

     

    foreach()を使用しないでください。

  • GetEnumerator()を呼び出しlist型にヒープ上のenumeratorを割り当てるのをすぐに止めてください。for(;;)構文に,より詳細なC ++スタイルを使用することが必要になります: あなたが配列上にforeach-ingしなければ,それは何もメモリを割当てません。私はそれがfor(...){}のための構文糖衣(読み書きのしやすさのために導入される構文)になった特殊なケースだと推察します。

    Ian Horswill氏このポイントを指摘していただき有り難うございます。

  • Ian Horswill http://www.cs.northwestern.edu/~ian/
  •  

     

    strings文字列を避けてください。

     

    文字列は.NETでは不変でヒープメモリ領域に割り当てられています。UIのためC言語の様にその場で それらを操作することはできません StringBuilders で、できるだけ文字列への変換を遅らせてメモリ効率の良い方法で文字列を構築します。あなたはリテラルがメモリ内の同じインスタンスを指す必要があるためキーとしてそれらを使用することができますが、あまりにも多くの操作はしないでください。

  •  http://msdn.microsoft.com/en-us/library/2839d5h5(v=vs.71).aspx
  •  C#入門-リテラル - WisdomSoft
  • 構造体を使用してください。

  • MonoのStruct型はスタック上に割り当てられています、ユーティリティクラスを持っていれば構造体作成にスコープを残すことはありません。任意のコピーのコストを回避するためにrefとパラメータの前に付ける必要があります。構造体は値で渡されることを覚えておいてください。

     

    スコープ結合を固定サイズ配列の構造体に交換してください。

     

    固定サイズの配列を持っている場合スコープを残さずメンバ配列を再利用できます。またはそれをミラーフィールドを持つ構造体を作成することができます メンバー配列に置き換えることのいずれかを検討してください。 私は4つのフィールドを持っているスプラインクラスのControlList構造体を呼び出すときはいつもVector3 [4]に置き換えます。そしてインデックス基準のアクセスのためにthis[]プロパティを追加しました。それは頻繁に呼び出される関数だったので大量のメモリ割当てを回避できました。

     

    リストを受け渡す際refキーワードを使用した参照渡しが好ましいです。

  • あなたはヒープメモリに渡すリストを必要とするのが正解で、これで何も変わらないように聞こえますか? ですがこれにより必要に応じて最適化を可能にします。

  •  パラメーターの引き渡し (C# プログラミング ガイド)
  • 方法 - メソッドに構造体を渡すこととクラス参照を渡すことの違いを理解する (C# プログラミング ガイド)
  •  

    ■頻繁な呼び出しをする関数をメンバ変数としてをローカルストレージにスコープすることを検討してください。 

    毎回大きなリストを呼びださなければならない時,リストにメンバ変数が作成されストレージはフレーム間持続します。 次のフレームにはメモリ領域が不足するのでC#のリストでバッファ領域から削除するためClear()を呼びださなければいけません。それによりコードが酷く読みにくくなるので、わかりやすいコメントが必要になりますが 作業は大幅に軽減できます。

  • 2-2 変数と定数 https://msdn.microsoft.com/ja-jp/library/cc406734.aspx
  • 変数のスコープ http://wisdom.sakura.ne.jp/programming/cs/cs23.html
  •  

     

    ■IEnumerable拡張メソッドを避けてください。

    ほとんどの便利なLINQのIEnumerable拡張メソッドは、新しい割り当てを作成することは言うまでもありません。私は.Any()が IList<>で呼びだされた時  Count> 0で Virtual関数がメモリ割当てを引き起こす First() とLast()のようなIlist()関数のメソッドも同様だと考えたのですが予想に反していました。この結果とforeach()の制限から あなたのインタフェースにはIEnumerable <>抽象化を避けて代わりにIList <>を使用するべきでしょう。

    ■関数ポインタ使用を最小限に 

    クラスメソッドをデリゲートやFunc<>に代入するとボックス化の原因となりメモリ割当てを引き起こします。私にはボクシングのないメソッドへのリンクを格納するための任意の方法はわかりません。デカップリングに大きな恩恵があるため割当てられたメモリは残り続けますが関数ポインタのほとんどは残してきましたが,いくつかは削除しました。

    ※デカップリング(Decoupling) プログラミングとデザインで、一般的に 再利用され可能な限り少数の依存関係を使用してコードを作成する行為のこと

     

    クローン化されたマテリアルに注意してください。 

    任意のレンダラのマテリアルプロパティを取得する場合、それに何も設定しない場合でもマテリアルを複製します。このマテリアルはGC'dされていません レベルの変更(シーンロード)またはResources.UnloadUnusedAssetsを呼び出したときのいずれかの場合のみクリーンアップされます。マテリアルを調整する必要はありませんが知っていればmyRenderer.sharedMaterialを使用してください。

    ※MaterialPropertyBlock を使用することで改善できる場合があります

  •  

    ディクショナリキーとして生の(未加工)構造体を使用しないでください 

    Dictionary<K、V>型を使用する時 あなたのキー値が構造体である場合はTryGetValue()またはインデックスアクセサを使用してDictionaryから値を取得することが出来ますが ここでメモリ割当てが発生します。これを回避するには構造体のためにIEquatable <K>を実装します。Dictionaryはいくつかの既定の等値比較をするたびに作成されていると思います。

     ライアン・ウィリアムズhttps://twitter.com/quxmore のおかげで,これを見つけられました。

    Enum.GetValues()またはmyEnumValue.ToString()を使用し過ぎないようにしてください。

    Enum.GetValues(typeof(MyEnum))は呼びだされるたびに配列を割り当てます。Enum.GetNames()も同様です。他の場所同様にUIを扱う際enum変数に.ToStringを加えて使用すべきです。enum値をループなどcachedEnumNames [(int)myEnumValue]に使用するように簡単にこれら両方の配列をキャッシュすることができます。enum型の値を手動で設定している場合 例えばフラグですが、これは動作しません。

     

     

     

     

     

     C# Coroutine WaitForSeconds Garbage Collection tip - Unity Community 

     

  •  

    追記:メモリ最適化の実装例としてWaitForSecondsコルーチンを最適化してガベージコレクトを抑える記事を簡単にまとめておきます。

     

    詳細はリンク先の記事で確認してください

     

     

     

    A: <Before>"yield return new WaitForSeconds()" は呼び出されるごとにガベージメモリを21バイト消費します

    ("yield return null"なら9バイトのメモリ消費)

    <After>  そこで"new WaitForSeconds()" を使用前にキャシュしてヒープ上に確保するメモリを削減してみます。

    これにより一回のIEnumeratorメソッドの呼び出しを9バイトに減らすことが出来ました。

    B:Yieldメソッドを場合分けして辞書登録し Yieldersクラスとして呼び出します。WaitForSeconds()メソッドは直値を指定すると A:の例では”0.1f、0.5f"のフロート型の数値ですが、呼び出されるたびにヒープメモリには新規に数値がキャッシュされ これが9バイトのメモリ消費となってしまいます。

    そこでUnityのシステムが管理する値 WaitForFixedUpdate()に代入される値をstatic型で置き換えることで、値がヒープメモリに複製されないようにしています。

    A:も ガベージコレクト対策としては悪いアイデアではないのでケースに応じて使い分けることが良いかもしれません。

    IEnumeratorメソッドはゲームオブジェクトのスクリプトに含まれることが多いためアタッチされたインスタンスが数百単位で複製される場合もあり 多くのヒープメモリを消費してしまいます。そのためガベージコレクト回避の対策として"Yield〜WaitForSeconds()" まわりを最適化することは有効だと考えられそうです。

     

     

     

    A:

    <before>

    IEnumerator myAwesomeCoroutine()

    {

        while (true)

        {

            doAwesomeStuff();

            yield return new WaitForSeconds(waitTime);

        }

    }

    <After>

    WaitForSeconds shortWait = new WaitForSeconds(0.1f);

    WaitForSeconds longWait = new WaitForSeconds(5.0f);

     

    IEnumerator myEvenAwesomerCoroutine()

    {

        while (true)

        {

            if (iNeedToDoStuffFast)

            {

                doAwesomeStuffReallyFast();

                yield return shortWait;

            }

            else{

                dontDoMuch();

                yield return longWait;

            }

        }

    }

     

    B:

    <Class>

    using UnityEngine;

    using System.Collections;

    using System.Collections.Generic;

     

    public static class Yielders {

     

        static Dictionary<float, WaitForSeconds> _timeInterval = new Dictionary<float, WaitForSeconds>(100);

     

        static WaitForEndOfFrame _endOfFrame = new WaitForEndOfFrame();

        public static WaitForEndOfFrame EndOfFrame {

            get{ return _endOfFrame;}

        }

     

        static WaitForFixedUpdate _fixedUpdate = new WaitForFixedUpdate();

        public static WaitForFixedUpdate FixedUpdate{

            get{ return _fixedUpdate; }

        }

     

        public static WaitForSeconds Get(float seconds){

            if(!_timeInterval.ContainsKey(seconds))

                _timeInterval.Add(seconds, new WaitForSeconds(seconds));

            return _timeInterval[seconds];

        }

      

    }

    <呼び出し側>

    必要な時間間隔にするにはYieldメソッドを複数回記述する。

    yield return Yielders.Get(this.updateinterval);

     

     

    以降 後日更新予定

     

    ■リファレンス

  • Gamasutra- Wendelin Reich's Blog - C# Memory Management for Unity Developers (part 1 of 3)
  • Gamasutra- Wendelin Reich's Blog - C# Memory Management for Unity Developers (part 2 of 3)
  • Gamasutra- Wendelin Reich's Blog - C# Memory Management for Unity Developers (part 3 of 3)
  • Three kinds of generic object pools to avoid memory deallocations in Unity-based games. Released
  • Reducing Memory Usage in Unity, C# and .NET-Mono - Andrew Fray
  • https://unitygem.wordpress.com/memory-management/
  • https://web.archive.org/web/20140624150214/http://msdn.microsoft.com/en-us/library/e59b22c5(v=vs.71).aspx
  • https://web.archive.org/web/20140702030338/http://unitygems.com/wp-content/uploads/2012/12/Stack2.png
  • C#-.NETがやっていること 第二版
  • C#の高速化入門
  • メモリ管理の話_エスキュービズム勉強会20140926

     



  • akinow at 13:34|PermalinkComments(0)TrackBack(0) Clip to Evernote Unity3d | シリーズ講座