Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
RecordGridColumnの配列は、フィールドで定義するな
05-16-2014, 07:21 PM,
#1
RecordGridColumnの配列は、フィールドで定義するな
★point
 RecordGrid.columns に設定するRecordGridColumnの配列は、フィールドで定義するな!


下記の数値は、RecordGridUI.get-cell-at で、
1回につき、100レコード×100カラム のセルを取得した場合の、
メモリの使用量の推移です。
※Curlのメモリ使用量は、「タスクマネージャ」の「プロセス」タブで表示される
 「surge,.exe」の「メモリ(プライベートワーキングセット)」を参照しました

■セル取得時のメモリ使用量
①「field定義のカラムを利用」した場合のメモリ消費量(単位は100KB)
1回目: 508 差分
2回目: 791 283
3回目:1074 283
4回目:1347 273
5回目:1629 282
6回目:1894 265
7回目:2195 301

②「一時的なカラムを利用」した場合のメモリ消費量(単位は100KB)
1回目: 549 差分
2回目: 791 242
3回目:1075 284
4回目:1347 272
5回目:1367 20
6回目:1383 16
7回目:1407 24



①と②の違いは、下記のアプレットのコードを見てもらうとわかりますが、
簡単に言うと、RecordGrid.columns に設定する{Array-of RecordGridColumn} を、
クラスのフィールド(field)に定義して利用するか、そうでないか、というものです。

Code:
{define-class public Screen {inherits Dialog}

  ||レコードとカラムの数
  field rs-size:int = 100
  field rf-size:int = 100


  ||フィールドとして定義するレコードグリッドカラムの配列
  field ary-column:{Array-of RecordGridColumn}

  ||一時的なレコードグリッドカラムの配列を返却するゲッター
  {getter {tmp-ary-column}:{Array-of RecordGridColumn}
    {return {self.make-columms}}
  }

  {constructor public {default}
    set self.ary-column = {self.make-columms}

    def ary-rf = {{Array-of RecordField}}
    {for i:int = 0 below self.rf-size do
        {ary-rf.append
            {RecordField {String i}, nullable? = true}
        }
    }

    def rs =
        {RecordSet
            {RecordFields {splice ary-rf} }
        }


    {for i:int = 0 below self.rs-size do
        def new-r = {rs.new-record}
        {rs.append new-r}
    }

    def cb-permanent =
        {CommandButton
            label = "field定義のカラムを利用する",
            {on Action do
                {self.get-cell rs, self.ary-column}
            }
        }

    def cb-tmp =
        {CommandButton
            label = "一時的なカラムを利用する",
            {on Action do
                {self.get-cell rs, self.tmp-ary-column}
            }
        }

    def cb-gc =
        {CommandButton
            label = "ガベージコレクト",
            {on Action do
                {garbage-collect}
            }
        }

    {self.add
        {VBox
            cb-permanent,
            cb-tmp,
            cb-gc
        }
    }

  }

  ||セルを取得すrう
  {method {get-cell
              record-set:RecordSet,
              cols:{Array-of RecordGridColumn}
          }:void

    let cnt:int = 0
    def grid = {RecordGrid }
    set grid.columns = cols
    set grid.record-source = record-set


    {for r in grid.records do
        {for col in grid.columns do

            def cell = {grid.ui.get-cell-at r, col}
            {if-non-null cell then
                set cnt = cnt + 1
             else
                {output "cell が見つかりません"}
            }
        }
    }
    {output cnt & "個のセルを生成しました"}
  }


  ||大量のカラムを生成する
  {method {make-columms}:{Array-of RecordGridColumn}

    def cols = {{Array-of RecordGridColumn}}
    {for i:int = 0 below self.rf-size do
        {cols.append
            {RecordGridColumn {String i}}
        }
    }
    {return cols}
  }

}

{def s = {Screen}}
{value s}

数値の推移をみてもわかるように、フィールドで定義して利用した①には、
単純増加傾向がみられるのに比べ、
そうではない②は、4回目以降、メモリの使用増加量が低下しています。
①については、私が試した限りでは20回以上、単純増加傾向か続きました。

また、各処理の間で、明示的に「ガベージコレクト(garbage-collect)」を呼び出した場合も、
①ではその効果がみられませんでした。
プログラムでは、グリッドを毎回作り直しているので、
以前のグリッド内で生成されたセルは、ガベージとして認識され、破棄されてほしいところですが、
私の試した限りでは、そのように期待した結果にはなりませんでした。

どうも、フィールドで定義したカラムを利用して生成されたセルは、
そのフィールドの親クラスが破棄されるまで、
ずっとガベージとして認識されないのではないかと推測されるのです。


静的に、グリッドとカラムを保持するような画面であればよいのですが、
グリッドに対して何度もカラムの再設定をする処理のある画面では、
上記のように、メモリの使用量がどんどん増えてしまう、
という問題が起こる可能性があります。

今回私が試した環境は、Windows7+Curl8.0.4 だけですので、
この現象が、ほかの環境でも発生するかは不明ですが、
できるだけ、RecordGridColumn の配列は、フィールドで定義せず、
記載したアプレットのサンプルソースのようにgetterで一時的に作成するなどの方式にしたほうがよさそうです。


Reply


Messages In This Thread
RecordGridColumnの配列は、フィールドで定義するな - by umemura - 05-16-2014, 07:21 PM
Forum Jump:


Users browsing this thread:
1 Guest(s)

MyBB SQL Error

MyBB has experienced an internal SQL error and cannot continue.

SQL Error:
1017 - Can't find file: 'mybb_threadviews' (errno: 2)
Query:
INSERT INTO mybb_threadviews (tid) VALUES('1083')