- PR -

コンテナ画像の手前のコントロール描画について

投稿者投稿内容
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-17 23:25
引用:

具体的なPCは以下です。
ttp://dynabook.com/pc/catalog/support/search/user/cgi-bin/disp.cgi?pid=PPL101GL4HA3K

メモリを1GB増設しています。

作業場にある複数のPCで試しても負荷が上がるので、PCスペックには依存せず、
何かしら使用率の上がる要因が、.Netアプリにはあるのだと思っていました。



他のPCでも試したとか、具体的なスペックとか、
そういう情報がほしかったんです。
gifのサイズやピクセル数、フォーマットも知りたかったですが。

何が言いたいのか、わかった気がします。

引用:

この状態で、作成した画面のLabelの手前を通るように、何か別なウィンドウをドラッグすると、
Labelが白表示になり、CPU使用率が一気に上がりました。



問題は、負荷ではなく、この「白表示」ではありませんか?
表示が醜くならないようにしたいのではありませんか?

でしたら、問題はダブルバッファが効いていないことです。

以下のコントロールをPanelの変わりに使ってみてください。
VBですが。

コード:
Public Class BufferedPanel
    Inherits Panel

    Public Sub New()
        MyBase.New()
        Me.DoubleBuffered = True
    End Sub

End Class



これでダブルバッファが(たぶん)効きます。
表示はかなり改善され、一見軽くなったように見えます。
実際の負荷はGPU、ドライバ、メモリの質、量などによって多くなる場合もあれば
少なくなる場合もあります。

たぶんこれで解決すると思いますが。

前出のPCで、Panel+Label10個のフォームを再描画するだけで
CPU使用率が100%になるのは変かもしれません。
少し重すぎな気がします。

同じ時期のより低スペックなDynabookを持っていますが、
がんばって再描画させてもせいぜい80%くらい。
環境もなんかおかしいかも知れません。
udon
会議室デビュー日: 2007/07/15
投稿数: 13
投稿日時: 2007-07-18 10:27
れいさん、返信ありがとうございます。

ダブルバッファを実装してみましたが、白表示に関しても負荷率に関しても効果がありませんでした。

実装はPanelとLabelがControlクラスの派生で、ダブルバッファを指定するにはprotectのSetStyleメソッドを呼ぶ必要があるようなので
Controlクラスの派生クラスを作成し、内部でSetStyleを呼ぶようにしました。

コードは以下のようにしました。
Labelのコードですが、Panelも同様のクラスを作成してFormの宣言をEx付きに変更しています。
また、Formにもダブルバッファ指定のプロパティがあったので設定してみました。(コードはありません)


  public ref class LabelEx : public System::Windows::Forms::Label
  {
   public:
    LabelEx(void)
    {
     InitializeComponent();
     //
     //TODO: ここにコンストラクタ コードを追加します
     //
     bool bRet;
     // ダブルバッファの指定がされていなければ指定する
     bRet = this->GetStyle( static_cast<ControlStyles>(ControlStyles:oubleBuffer|ControlStyles:ptimizedDoubleBuffer|ControlStyles::UserPaint|ControlStyles::AllPaintingInWmPaint|ControlStyles::CacheText) );
     if( bRet != true )
     {
      this->DoubleBuffered = true;
      this->SetStyle(static_cast<ControlStyles>(ControlStyles:oubleBuffer|ControlStyles:ptimizedDoubleBuffer|ControlStyles::UserPaint|ControlStyles::AllPaintingInWmPaint|ControlStyles::CacheText),true);
      this->UpdateStyles();
      bRet = this->GetStyle( static_cast<ControlStyles>(ControlStyles:oubleBuffer|ControlStyles:ptimizedDoubleBuffer|ControlStyles::UserPaint|ControlStyles::AllPaintingInWmPaint|ControlStyles::CacheText) );
     }
    }

   protected:
    /// <summary>
    /// 使用中のリソースをすべてクリーンアップします。
    /// </summary>
    ~LabelEx()
    {
     if (components)
     {
      delete components;
     }
    }

   private:
     /// <summary>
     /// 必要なデザイナ変数です。
     /// </summary>
     System::ComponentModel::Container ^components;

#pragma region Windows Form Designer generated code
     /// <summary>
     /// デザイナ サポートに必要なメソッドです。このメソッドの内容を
     /// コード エディタで変更しないでください。
     /// </summary>
     void InitializeComponent(void)
     {
     }
#pragma endregion
  };


れいさんの「問題は負荷ではなく、この「白表示」ではありませんか?
表示が醜くならないようにしたいのではありませんか? 」
のご質問ですが、負荷率を下げたいのが目標です。
理想で言えば、負荷が無く白表示されない状態で、負荷は高いけど白表示はしない、のは解決ではないのです。

私が一番問題視しているのは、ほぼデフォルトのプロパティ設定でLabelやPanelを配置し、
Panelに背景画像を指定しただけで、再描画に著しく負荷がかかってしまう事が.Netの仕様なのかどうか見極められない事です。
フレームワークライブラリの中で具体的に何をやっているから遅い、と回答出来る人は少ないと思いますので、おまじない的な設定やコードを入れる事で改善されるのであれば
積極的に試したいと思っています。


今、判っている事をここで整理します。
1.複数のLabelコントロールをFormに直接貼り付けて再描画(電卓などの別ウィンドウをLabel群の手前でドラッグを繰り返す)させてもCPU使用率が60〜80%まで上がる。(その際、Formに画像は無し。ダブルバッファ実装クラスでも同様)
2.LabelをPanelにコンテナ配置し、Panelの背景に画像を指定すると、確実に100%になる(Panel画像はgif,bmp問わず。Labelは再描画時に白表示してしまう)
3.高スペックデスクトップPCでは、白表示は起こりませんが、負荷率が高い現象になります。(グラボの性能による影響が大きいと思われます)

試した画像の概要は以下の通りです。

<gif画像>(エクスプローラのプロパティ - 概要の表示内容)
幅:1008ピクセル
高さ:184ピクセル
水平解像度:96dpi
垂直解像度:96dpi
ビット深さ:8
フレーム数:1

<bmp画像>
幅:817ピクセル
高さ:261ピクセル
水平解像度:96dpi
垂直解像度:96dpi
ビット深さ:24
フレーム数:1
udon
会議室デビュー日: 2007/07/15
投稿数: 13
投稿日時: 2007-07-18 10:51
補足です。画像はWindowsのペイントで作成し、サイズを指定して全体を赤く塗ったものです。
ソースに顔文字が入ってしまい判りづらくなってしまいました。申し訳ありません。
ニコニコした顔が:D びっくりした顔が:O です。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-18 15:54
引用:

udonさんの書き込み (2007-07-18 10:27) より:
ダブルバッファを実装してみましたが、白表示に関しても負荷率に関しても効果がありませんでした。



あれれ。そうですか。
残念。

引用:

れいさんの「問題は負荷ではなく、この「白表示」ではありませんか?
表示が醜くならないようにしたいのではありませんか? 」
のご質問ですが、負荷率を下げたいのが目標です。
理想で言えば、負荷が無く白表示されない状態で、負荷は高いけど白表示はしない、のは解決ではないのです。



そうですか。
では厳しいですね。

>フレームワークライブラリの中で具体的に何をやっているから遅い、と回答出来る人は少ないと思いますので、

いや。
たくさんいるでしょう。
Panelの背景描画はGDI+で普通に書いてるだけです。
Labelは普通背景を単色で塗って
DrawTextで文字を書いているだけです。

.Netは確かに重いですが、
この描画に関してはそれほど変わらないはずです。

引用:

私が一番問題視しているのは、ほぼデフォルトのプロパティ設定でLabelやPanelを配置し、
Panelに背景画像を指定しただけで、再描画に著しく負荷がかかってしまう事が.Netの仕様なのかどうか見極められない事です。



すくなくとも私の周りでは問題になるほど負荷は発生しません。
再描画する分の負荷は勿論ありますが、
再描画するんだからしょうがない、程度ですね。

最初に言っていたように、
MFCを使って
DrawTextExやDrawImageで試してみたらどうですか?
おそらく同程度の負荷になると思いますが。
udon
会議室デビュー日: 2007/07/15
投稿数: 13
投稿日時: 2007-07-18 18:49
れいさん、返信ありがとうございます。

引用:

いや。
たくさんいるでしょう。


.Netの内部動作を知っている方が多い事に驚きました。
ここをご覧の方でご存知な方が居られましたら、是非アドバイスをお願い致します。

引用:

引用:

私が一番問題視しているのは、ほぼデフォルトのプロパティ設定でLabelやPanelを配置し、
Panelに背景画像を指定しただけで、再描画に著しく負荷がかかってしまう事が.Netの仕様なのかどうか見極められない事です。



すくなくとも私の周りでは問題になるほど負荷は発生しません。
再描画する分の負荷は勿論ありますが、
再描画するんだからしょうがない、程度ですね。



今回のケースですが、高負荷が元で何かの問題が起きている訳ではないのです。
負荷が高い事を問題として捉えているのです。

「CPU負荷率は100%になるけど、問題無いからいいでしょ?」なんて言えません。
なので、簡単な操作で高負荷になる事を問題視しています。

例えば、メモリリークはリークしているか気にしなければ、探そうとしませんよね。
(普通は気にしますが)
後でリークが問題になる前にチェックするのと今回の話は同じニュアンスだと思っています。

引用:

最初に言っていたように、
MFCを使ってDrawTextExやDrawImageで試してみたらどうですか?
おそらく同程度の負荷になると思いますが。


こちらはもうちょっと後の話です。
「負荷率が高いのは当たり前」の言い訳になってしまいますので。


[ メッセージ編集済み 編集者: udon 編集日時 2007-07-18 18:50 ]

[ メッセージ編集済み 編集者: udon 編集日時 2007-07-18 18:51 ]
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-18 18:57
引用:

引用:

最初に言っていたように、
MFCを使ってDrawTextExやDrawImageで試してみたらどうですか?
おそらく同程度の負荷になると思いますが。


こちらはもうちょっと後の話です。
「負荷率が高いのは当たり前」の言い訳になってしまいますので。



いや、そこがおかしいでしょう。
MFCでDrawTextExやDrawImageが同程度に重いなら、
問題は.NetでなくDrawTextExやDrawImageにあると判断するべきで、
その場合はWindowsのほうに問題があるということになるわけですから。

なぜはじめから.Netが重いときめてかかるのですか?


[ メッセージ編集済み 編集者: れい 編集日時 2007-07-18 19:06 ]
udon
会議室デビュー日: 2007/07/15
投稿数: 13
投稿日時: 2007-07-19 10:45
れいさん、返信ありがとうございます。

引用:

れいさんの書き込み (2007-07-18 18:57) より:
引用:

引用:

最初に言っていたように、
MFCを使ってDrawTextExやDrawImageで試してみたらどうですか?
おそらく同程度の負荷になると思いますが。


こちらはもうちょっと後の話です。
「負荷率が高いのは当たり前」の言い訳になってしまいますので。



いや、そこがおかしいでしょう。
MFCでDrawTextExやDrawImageが同程度に重いなら、
問題は.NetでなくDrawTextExやDrawImageにあると判断するべきで、
その場合はWindowsのほうに問題があるということになるわけですから。

なぜはじめから.Netが重いときめてかかるのですか?



実際に重いからです。

開発の状況をお伝えする事になってしまいますが、客先よりVC.Netを使うよう要望があり、これは避けられない状況です。
VC.Netでの開発経験が豊富ではないので、テストアプリを造りアプリのパフォーマンスやコードの生産性の
調査を行っていたところ、今回の現象がわかりました。

なので、他の言語や環境(MFC)で重い軽いの話はすべきではないと判断した為です。気を悪くなさらないでください。
事前に客先へ説明し負荷率を許容してもらうか、他言語での開発にするかの材料が必要になりますが、これは最後の最後の手段です。
仮にMFCでも遅かった場合は、Windowsアプリでは遅いんだからしょうがない。と片付けはせず、.Netアプリでの高速化や負荷の軽減を図ります。
仮にMFCが早かった場合は、では何故.Netでは遅いのかと高速化や負荷の軽減を図ります。

重い軽いの話であれば、VC.Netで軽くする方法について考えたいのです。

幸いにもれいさんは、.Netの内部動作にまで精通され、dynabookでCPU使用率80%まで上がった事を目視されたと述べられています。

どういった内部の理由で80%まで上がるのか、ご存知でしたらご教授頂けないでしょうか。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-19 10:59
引用:

udonさんの書き込み (2007-07-19 10:45) より:
実際に重いからです。



話が通じていないようですね。
実際に重いということを否定してはいません。
問題の切り分けの話をしているのです。
ライブラリ内部が重いのか、ライブラリの外が重いのかを
私は問題にしているのです。

ですから、できればMFCも使わないで調査すると良いでしょう。

引用:

気を悪くなさらないでください。



別に気を悪くはしていません。

引用:

どういった内部の理由で80%まで上がるのか、ご存知でしたらご教授頂けないでしょうか。



何回も言っているように、再描画するからです。
私の環境の場合DrawImageで9割以上の時間が過ぎています。
つまり、これ以上早くするには
DrawImage部分を高速化しなければどうしようもありません。

スキルアップ/キャリアアップ(JOB@IT)