大規模コードクローン検出のための包含文字列を対象とした省メモ リ化

大規模コードクローン検出のための包含文字列を対象とした省メモ
リ化プログラム変換の予備的な性能評価
山崎 徹郎*
佐藤 芳樹 †
東京大学情報理工学系研究科*‡§
1 はじめに
千葉 滋 ‡
東京大学情報基盤センター †§
たり 16 コアかつ 32 GB メモリを搭載するので,計算コ
アあたり 2 GB しかメモリがない.
本論文は,我々が Scorpio の消費メモリ量の削減に向
膨大な量のソースコードから類似したコード片を見つ
けて検討している Java の文字列オブジェクトの実装の
ける大規模コードクローン検出はソフトウェアリポジト
工夫,およびそのためにおこなった実験の結果を報告す
リマイニングにおける重要な研究テーマの一つである.
る.Scorpio の動作を調査した結果,Scorpio は実行中,
このようなコードクローン検出の中でも Type 3 と呼
解析対象のプログラムの無数の断片を文字列として保持
ばれる種類のコードクローンの検出は,しばしば大量
しており,消費メモリの実に約半分が文字列オブジェク
の計算資源を必要とする.コードクローンは,主にソー
トによって占められていたからである.2 つの文字列オ
スコードのコピー&ペーストにより作られるが,ペー
ブジェクトがあり,それらが表す文字列の一方が他方を
ストされたコード片に多少の文が挿入されたり,一部の
包含している場合,2 つの文字列オブジェクトは内部情
文が削除または修正される場合,元のコード片と完全に
報を共有して消費メモリを減らすことができる.この手
は一致しなくなる.このようなコードクローンは Type
法をとる場合,実行中に包含関係にある文字列オブジェ
3 と分類されるが,それを検出するためにはソースコー
クトを多数発見できれば消費メモリは減少するが,多く
ドを抽象構文木に変換して,制御フローやデータフロー
発見しようとするとそれだけ実行速度が低下する.我々
のグラフも作るなどし,抽象構文木の類似する部分木を
はいくつかの設定の下,消費メモリと実行速度の測定を
探すことになる.これは計算時間やメモリを大量に消費
おこない,実行速度の低下をおさえつつ消費メモリを減
する.
少させる方法を検討した.
実際に Type 3 コードクローン検出器である Scorpio
[1] を用いた我々の予備実験では,入力サイズである解
2 文字列オブジェクトの実装法
析対象のプログラムの大きさに対して約 200 倍のメモリ
Java 言語の文字列オブジェクトの実装方法は,文字
を消費する場合があった.我々は大規模コードクローン
列処理が多いプログラムの場合,そのメモリ消費量を決
検出のために,スーパーコンピュータを用いて大規模並
める重要な要素である.メモリ消費を少しでも減らすた
列処理をおこなうことを計画しているが,実現のために
め,Java 6 までは例えば substring メソッドにより,あ
はクローン検出器が必要とするメモリ量を減らすことが
る文字列から部分文字列を切り出した場合,部分文字列
必要である.大規模並列計算機では,ノード計算機あた
のオブジェクトは元の文字列のオブジェクトと内部の
りに多数の計算コアを搭載するので,計算コアあたりの
char 配列を共有していた.この配列には文字列の各文字
メモリ量が相対的に少なくなるからである.例えば富士
通 FX10 スーパーコンピュータの場合,ノード計算機あ
A Preliminary Experiment of a Memory Reduction
Method Using Substrings Implemented by Program
Transformation for Large-Scale Code Clone Detection
* Tetsuro Yamazaki, †Yoshiki Sato, ‡Shigeru Chiba
§The University of Tokyo
ファイル数
合計サイズ
253
497
128
1.9MB
3.9MB
1.1MB
Compress
Collections
Validator
表1
入力データセット
Compress
Collections
Validator
共有範囲
実行時間
最大メモリ
実行時間
最大メモリ
実行時間
最大メモリ
(a) 共有なし
(b) 全フィールド
(c) 全 private フィールド
(d) 特定のフィールド
40sec
9,090sec
316sec
306sec
1.55GB
239MB
926MB
1.13GB
125sec
27,500sec
695sec
692sec
1.64GB
909MB
1.17GB
1.20GB
12sec
1,830sec
68sec
62sec
1.55GB
322MB
1.54GB
1.55GB
表2
実験結果 (最大メモリはメモリ消費が最大の時に確保したヒープのサイズ)
の文字コードが格納される.この実装は Java 7 Update
の範囲は次の通りである.(a) まったく置換せずに全て
6 からは変更され,部分文字列のオブジェクトは独立し
元の String クラスを利用,(b) 全てのクラスの全ての
た char 配列を内部に持つようになり,元の文字列のオブ
フィールドを新しい文字列クラスに置換,(c) 全てのク
ジェクトと配列を共有することはなくなった.これは,
ラスの private フィールドを新しい文字列クラスに置換,
長い文字列からごく短い文字列を部分文字列として切り
(d) 事前の分析で選んだ特定のフィールドだけを新しい
出す場合,長い文字列全体を格納する char 配列が共有
文字列クラスに置換.なお新しい文字列クラスは,同じ
されるのを避けるためである.さもないと長い文字列が
クラスの全てのオブジェクトとの間で文字列の共通部分
ゴミになった後も短い文字列が生きている間はその char
がないかを探す.全てのオブジェクトとの間で探すので
配列はゴミとして回収されず無駄である.
はなく,一部の限られたオブジェクトとの間でだけ探し
我々は,substring メソッドで切り出した部分文字列の
て探索時間を短くするような工夫はおこなっていない.
オブジェクトだけでなく,任意の文字列オブジェクトが
実験結果を表 2 に示す.実行時間と最大消費メモリ
新しく生成される度に他の文字列オブジェクトとの間に
の間にはトレードオフがあることが見て取れる.確かに
文字列の共通部分がないか調べ,ある場合には char 配
全てのフィールドを新しい文字列クラスに置換する (b)
列を共有させる手法を検討している.これによりメモリ
と,消費メモリ量を大幅に削減できた.一方で実験した
消費量は抑えられるが,共通部分を調べるために実行時
方針 (c),(d) では,新しい文字列クラスに置換する範囲
オーバーヘッドを伴う.そこでプログラムの限られた範
を狭めると,実行時間は改善するものの,消費メモリ量
囲で作られる文字列オブジェクトの間でだけ,文字列の
が増大した.実行速度を改善しつつ (b) に比べて消費メ
共通分がないか調べる手法を考えた.この手法は,共通
モリ量を増やさない方針は見つけられなかった.
部分がある文字列オブジェクトはプログラムの狭い範囲
で主に生成されるという仮説に基づいている.
3 実験
4 まとめ
大規模コードクローン検出に向けて Type 3 コードク
ローン検出器 Scorpio のメモリ消費量を減らすため,文
我々は Scorpio を用い,文字列の共通部分がないか調
字列オブジェクトの実装方法の見直しを検討した.今後
べるオブジェクトが生成される範囲を色々に変えて,消
も実験を継続して,実行速度の悪化を許容できる範囲に
費メモリ量と実行速度を測定した.解析対象のプログラ
おさえつつ,消費メモリを削減して大規模並列計算機の
ムとして Apache Commons プロジェクトから大きさの
上で Scorpio を動かす方法を探る.
異なるサブプロジェクトを選んで用いた (表 1).Scorpio
は Intel Core i7-4770S (3.10GHz),Ubuntu 14.04LTS,
OpenJDK 8 で実行した.
実験では,生成時に他と共通部分がないか調べる特別
な文字列クラスを実装し,プログラム中に現れる String
クラスを置き換えた.置き換えのためにプログラム変換
器を作成し,機械的に置き換えた.元の String クラス
と新しい文字列クラスは互換性がないので,必要に応じ
て両者間の変換を実行するコードを挿入した.置き換え
参考文献
[1] 肥後芳樹,楠本真二. プログラム依存グラフを用いた
コードクローン検出法の改善と評価. 情報処理学会
論文誌ジャーナル, 51(12):2149–2168, 2010.