ラベル C# の投稿を表示しています。 すべての投稿を表示
ラベル C# の投稿を表示しています。 すべての投稿を表示

2012/12/31

gitignore総まとめ

.gitignore @ Github
新しい統合開発環境で開発を始まるときって、どのファイルをバージョン管理したらいいか悩みます。その問題を解決してくれる。感謝感謝。

2010/03/13

Windows XPでのC#の動作の重さを解消する方法 (2)

C#でウィンドウ最小化時のスワップアウトを阻止する方法のつづき。

● WndProcをoverrideすることによって、ウィンドウメッセージ処理をinterruptできる。

http://www.atmarkit.co.jp/fdotnet/dotnettips/467wndproc/wndproc.html

知らなかった・・・。そんなことできるんだ。

● 最小化処理をinterrupt
先のコレ

http://support.microsoft.com/kb/293215/en-us

をC#で実装すると、こう

http://d.hatena.ne.jp/babydaemons/20080507/1210150398

なる。
これでフォームを最小化するだけでスワップアウトが発生するのは
防ぐことができる。

●ただし、

これをやると、最小化時にタスクバーからも表示が消えるので
タスクトレイにアイコンを置いておいて、そこから復帰させる用途じゃないと
そのままは使えない。
まぁ、そこまでしてスワップを避けたいソフトって常駐ソフトぐらいだから
まぁいっか。

2010/03/11

Windows XPでのC#の動作の重さを解消する方法

C#で組んだアプリがどうもなーんかモッサリ動作に感じる原因が
やーっと分かりました。

● フォームを最小化した後、復帰するときにすごく重いことがある。

最小化したフォームを復帰させるとき非常に重たいことがある。
PCがフリーズした状態で徐々にゆっくりフォームが表示されていく
感じ。時々起こるこれが実際以上に体感速度をすごく遅くしてる。

● 原因はフォーム最小化時のスワップアウト

http://d.hatena.ne.jp/NyaRuRu/20051022

Windows XPはフォームを最小化するとプロセスの"working set"を
縮小する。タスクマネージャのプロセスのメモリ使用量をみてると、
フォームを最小化したときに使用量がぐっと減るのが分かる。

http://d.hatena.ne.jp/NyaRuRu/20071010/p1
http://d.hatena.ne.jp/NyaRuRu/20071027/p1

この状態で他のプロセスがメモリを消費すると、簡単にスワップアウトしてしまう。
で、さらにスワップ状態でGCが動いたりすると、とても重たい処理に発展しちゃったり
することがあるらしい。
.netのメモリ消費量の多さとこのへんの動作の重さがが重なって結果的に
とっても重くなってる感じがする。

● で、どうやって回避するか

Firefoxとかのメモリを食うアプリは最小化時のスワップアウトを回避してるらしい。
これ、

http://support.microsoft.com/kb/293215/en-us

によると、WM_SYSCOMMANDメッセージのSC_MINIMIZEコマンド
の処理中にWorking Setの圧縮が行われているそうなので、
ここをinterceptすることでスワップアウトを阻止できるそうだ。
ただ、メッセージハンドラを直接触れない(多分)C#ではこのままの方法は
とれない。

● タスクトレイを使う方法

常駐型のソフトに関してはタスクトレイに常駐させてしまう方法をとることができる。
まずはNotifyIconを使ってタスクトレイにアイコンを配置して、
フォームの方の最小化ボタンはMinimizeBoxプロパティで禁止してしまう。
で、FormClosingイベントでフォームのVisibleをFlaseにするようにする。
VisibleをFalseにした際には問題のスワップアウトは発生しないようで、
これで動作は非常に快適になった。

●で、普通に最小化したいときはどうするのか

最小化ボタンを押したときに最小化前に発生するイベントが無いのが問題。
CloseしたときのFormClosingに相当するものがあればいいんだけど。
Layoutイベントで
this.WindowState==FormWindowState.Minimized
となるときを拾えば最小化前に処理を発生させることはできそうなんだけど、
FormClosingでのe.Cancelに相当するものが無い。
すなわち、最小化前にVisibleをfalseにすることはできても、
その後で発生するMinimizeを止めることができない。

さて、どうしたものか・・・。

2010/01/05

C#のエスケープシーケンス

C#で使えるエスケープシーケンスをよく忘れるのでメモ。

> http://www.melma.com/backnumber_120830_237603/

\' シングルクォーテーション
\" ダブルクォーテーション
\\ 円マーク
\0 null
\a ビープ音
\b バックスペース
\f 改ページ
\n 改行
\r キャリッジリターン
\t 水平タブ
\v 垂直タブ
\x16進数 16進エスケープシーケンス
\u16進数 UNICODE文字 0000 ~ FFFF

エスケープシーケンスを使いたくない場合には、
以下のように””の前に@をつけると
エスケープシーケンスが効かなくなる。

NG> filepath="c:\temp\test.text"
OK> filepath="c:\\temp\\test.text"
OK> filepath=@"c:\temp\test.text"

2009/12/23

C#のコードを高速化するための方法

以前のものの続き。
C#ならではのコーディングの際に注意するところまとめ。

○クラスと構造体の選択方法

オブジェクトのインスタンス生成はかなり重たい処理であるよう。

で、C#にはオブジェクトをヒープ内でなく、
スタックに積むための「構造体」という仕組みがあるのですが、
http://www.atmarkit.co.jp/fdotnet/special/java2cs/java2cs_01.html

構造体は値型であるためそのサイズが大きい場合にはかえってその受け渡し時の
コピーに負荷がかかってしまうよう。
http://www.atmarkit.co.jp/fdotnet/directxworld/directxworld06/directxworld06_04.html

構造体を使うかクラスを使うかの境界線はそのサイズで決まるようなの
ですが、その境界は意外と低くて16バイト以上のものはクラスを使ったほうがいいよう。

クラスと構造体の選択
http://msdn.microsoft.com/ja-jp/library/ms229017.aspx
実検証結果
http://mag.autumn.org/Content.modf?id=20061014194823

実際には構造体を使ったほうが得をする場合は
結構限られている感じをうけます。


○キャストはすごく重そうだ

型キャストはちょっと意外なぐらい重い。
http://www.atmarkit.co.jp/fdotnet/dotnettips/005castandas/castandas.html

上記のリンクにもあるように、参照型のキャストにはasを使ったほうが速い。
でも、asを使ってもそれなりに重い処理ではある。

Collectionはキャスト必須になってしまうので、
なるべく代わりにGenericを使ったほうが良い。

http://www.atmarkit.co.jp/fdotnet/csharp20/csharp20_02/csharp20_02_01.html
http://life-hack.jp/blog/charly/95

イベントハンドラでsenderを繰り返し使うと重くなるので、
senderは早めにas演算子でなんらかの型に変換しちゃったほうが良いみたい。


○多次元配列は比較的重い

多次元配列(x[i,j])よりジャグ配列(x[i][j])使ったほうが速いそうです。
http://d.hatena.ne.jp/EmK/20081130/1228025602
重い数値計算とかやる場合に影響するかも。

C++の多次元配列は実質的には単なるポインタ経由のアクセスなんで
べらぼうに速いですね。やっぱり。


○文字列の連結処理

頻繁な文字列の連結はメモリ中のコピーを繰り返すので遅い
http://www.atmarkit.co.jp/fdotnet/dotnettips/029strcat/strcat.html
ベンチマーク結果
http://sonic64.com/2005-11-30.html

stringbuilderを使うと高速化できる。
そこまで重い処理ではないので、ホントに大量の連結
を繰り返す場合にだけ対策が必要。


○画像処理

BitmapのGetPixel, SetPixelは画像処理に使うにはちょっと重すぎる。
http://www.atmarkit.co.jp/fdotnet/csharp_abc/csharp_abc_021/csharp_abc05.html

本気で画像処理するときには、unsafeになるけど
ポインタを使うしかないと思う。


○.net Frameworkの起動が遅い

Windows XPだと初回のアプリ起動時に.net Framework自体を起動しに行く。
http://ameblo.jp/norixp/entry-10013581738.html

対策するとしたら、
上のリンクのように別アプリでスプラッシュウィンドウを出す、とか、
スタートアップに空の.netアプリを入れとくか。

Vista以降だと最初から起動してるから
これがなくて速いんでしょうか?

2009/12/22

C#って遅いのか?

C#って遅いのかどうか?といういろいろ荒れがちなセンシティブな話。
でも結構高速化するときに結局どうすりゃいいのかわからなくて困るので
他力本願で収集した内容を分かる範囲でまとめてみる。

1) C#ってVMで中間言語を解釈しながら動いてるわけじゃない

ときどき間違って説明されていることがありますが、
C#って昔のVBのインタプリタとかJAVAのVMとは違って
中間言語を逐次実行してるわけではない。

VB.netの話だけど以下がわかりやすい。C#も同じ。
http://www.atmarkit.co.jp/fdotnet/vbcheer/vbcheer08/vbcheer08.html

だから数値計算とかでベンチマークすると実はかなり速いそうだ。
http://densanshokunin.at.webry.info/200701/article_2.html

でも実際に使っているとなにかとストレスを感じることもあるのは周知の通り。

2) コンパイルの時期に関して
より正確にはここに。
http://msdn.microsoft.com/ja-jp/library/ht8ecch6(VS.80).aspx

> すべての MSIL をネイディブ コードに変換するために時間とメモリを費やすのではなく、
> 実行時に必要になった MSIL を変換し、その結果生成されたネイティブ コードを保存して、
> 以降の呼び出しで利用できるようにしておきます。
> 型が読み込まれると、ローダーはスタブを作成し、その型の各メソッドに結び付けます。
> それ以降は、この JIT コンパイル済みのメソッドを呼び出すと生成済みの
> ネイティブ コードが直接実行され、JIT コンパイルとコードの実行に必要な時間を節約できます。

つまり、フォームを開くのにしてもメソッドを実行するのにしても
「初回だけ」遅い可能性があることになります。
故意に前もって特定のコンパイル実行しておくのも難しいようなので
このへんは気をつけておく必要あり。
最終的にはngen.exeを使った一括先行コンパイルか。試したことないですが。

3)ガベージコレクタの動作に関するオーバーヘッドは読みづらいので注意する必要がある。

ガベージコレクタの動作については以下が詳しい。
http://www.atmarkit.co.jp/fdotnet/directxworld/directxworld06/directxworld06_01.html

でも、結局プロのプログラマでない自分としてはいろいろ調べるのは面倒で、
なるべくobjectのinstanceをpublic宣言して
いろんなところで使いまわす、という腰の引けたコーディングをやりがち。
ホントはもっといいやり方があるはず。

4) System.Windows.Formsって重くないでしょうか。

http://d.hatena.ne.jp/NyaRuRu/20060203#p2
> トップレベルウィンドウとメニューやツールチップなどの一部の特殊ウィンドウのみを
> Win32ウィンドウとし,後はクライアント領域に完全自前描画になったことで,
> やっとInternet ExplorerやFirefox と同じ土俵に上がることができました.
> 要はこれまで WinForms が重かったのはアルゴリズム的問題があったと
> いうことなわけですが,今まで単に「.NET だから重い」と思っていた人は
> もう一度評価し直すべきときがいよいよ来たかと思います.

ちゃんとした検証はできてないですが、
どうもやっぱりFormsの標準コントロールが.net以前と比べて妙に重い気がします。
コントロールをフォーム上に大量配置しただけで露骨に重くなる感じが。

困ったときはすぐダブルバッファリング+自前描画
http://www.atmarkit.co.jp/fdotnet/dotnettips/197doublebuf/doublebuf.html
をやって無理矢理解決してるので、根本的にはどうしたらいいのかさっぱりわからないです。


5) 意外と遅い処理がいろいろあるよう。

C#では意外と遅い特定の処理というのがいろいろあるようで、
そこを気にしないといけないようです。

これについてはまた別途。

2009/12/18

システムの復元でC#のソースファイルが消える!

C#のソースファイルをいくらか無くしてしまいました。

PCを起動してみると突然Windowsがブルースクリーンに。
しょうがないのでセーフモードで起動し、初めて使う
「システムの復元」をすると、なんとか正常に戻った。
なんかシステム関連のファイルだけ以前の状態に戻してくれるんだそうだ。

なるほど、こりゃ凄いや。頻繁に復元ポイント作る設定でよかった。
と思いつついろいろやってると、
どうも最近インストールした自作ソフトのexeファイルが消えてることに気づく。

そっかー。実行ファイルだからシステム復元で消されてもしょうがないわな。
まぁ、ソースファイルあるんだしまたコンパイルすりゃいいや。と思って
VC#を開いてみると、ところどころC#のソースコード(拡張子.cs)が消えている!
プロジェクトファイルとかリソースファイルは消えてないのに。
いや、なんでソースファイルの状態巻き戻すかな。

で、いろいと調べた結果、
>http://www.atmarkit.co.jp/fwin2k/operation/srestore/srestore_02.html
Filelist.xmlを調べると、システム復元が対象にしてるファイルの拡張子がわかるそうだ。

・・・うわ。.csが入ってるよ。C Scriptか何かの拡張子とカブってんのかな?
.cとか.cppとか.vbとかは入ってないのに。なんてこった。

急いで再度システム復元を使ってなんとかソースファイルを復元しようとすると、
「システム復元に必要なHDD領域が足りません」とか言われる。
じゃあいらないファイル消してもう一回やるか、と思ったら、
なんとシステム復元ポイントがぜーんぶ無くなってる!

いや、それはないだろーと思って調べてみると、

> http://support.microsoft.com/default.aspx?scid=kb;ja;JP301224
この動作は仕様です。

・・・。うわー。

Windows XP SP3で確認。

2009/12/13

C#でフォームをアクティブにせずに開く方法

.net frameworkで、ポップアップウィンドウを作ろうとすると、
いろいろ面倒な罠がありました。

まず、アクティブにせずにフォームを開く必要があり、
ShowWithoutActivationというプロパティを変更するとよさそうなのですが、
読み取り専用なので、値を変更できない。

すると、このプロパティをoverrideするしかないのですが、

MSDNによると、
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.form.showwithoutactivation(VS.80).aspx

> フォーム内で ShowWithoutActivation をオーバーライドし、
> true が返されるようにプログラミングしても、値を変更することはできません。


なんだよー。と思いつつ調べてると、
http://d.hatena.ne.jp/masa-k/20080609/1213015216
こいつはどうも誤訳で、
> このプロパティはread-onlyなので、変えたいときは
> ShowWindowActivationをoverrideしてtrueを返すようにしてください。
が、正しいよう。

で、なんだーできるんじゃないですかー。と思いつつ試していると、
何故かできない。

で、結局原因は、
http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=401311
「TopMostプロパティをtrueにしているとShowWindowActivationが効かない」
というバグのせいのよう。

ポップアップに使うにはTopMostが効いてないといろいろ不便なので、
結局、ここの下のほうにあるように
http://www.r-nakai.com/archives/99
SetWindowPos APIを使うしかないよう。
(つうかC#でWIN32 APIって使っていいんだ・・・。)

ただ、これをやるとLoadとかのイベントが発生しないようなので、
そこらへんは手で実装してやる必要があるようです。


.net Framework3.5で確認。