ファイルからシーケンスの大きなリストを読み取り、そのリスト内のすべてのペア間で計算を行うプログラムがあります。次に、これらすべての計算をハッシュセットに格納します。このプログラムを途中で実行すると、GC オーバーヘッド制限エラーが発生します。
これは、ガベージ コレクターが計算時間の 98% を使い果たしており、ヒープの 2% を回復することさえできないためです。ここに私が持っているコードがあります:
ArrayList<String> c = loadSequences("file.txt"); // Loads 60 char DNA sequences
HashSet<DNAPair,Double> LSA = new HashSet<DNAPair,Double>();
for(int i = 0; i < c.size(); i++) {
for(int j = i+1; j < c.size(); j++) {
LSA.put(new DNAPair(c.get(i),c.get(j)),localSeqAlignmentSimilarity(c.get(i),c.get(j)));
}
}
実際のメソッドのコードは次のとおりです。
public static double localSeqAlignmentSimilarity(String s1, String s2) {
s1 = " " + s1;
s2 = " " + s2;
int max = 0,h = 0,maxI = 0,maxJ = 0;
int[][] score = new int[61][61];
int[][] pointers = new int[61][61];
for(int i = 1; i < s1.length(); i++) {
pointers[i][0] = 2;
}
for(int i = 1; i < s2.length(); i++) {
pointers[0][i] = 1;
}
boolean inGap = false;
for(int i = 1; i < s1.length(); i++) {
for(int j = 1; j < s2.length(); j++) {
h = -99;
if(score[i-1][j-1] + match(s1.charAt(i),s2.charAt(j)) > h) {
h = score[i-1][j-1] + match(s1.charAt(i),s2.charAt(j));
pointers[i][j] = 3;
inGap = false;
}
if(!inGap) {
if(score[i-1][j] + GAPPENALTY > h) {
h = score[i-1][j] + GAPPENALTY;
pointers[i][j] = 2;
inGap = true;
}
if(score[i][j-1] + GAPPENALTY > h) {
h = score[i][j-1] + GAPPENALTY;
pointers[i][j] = 1;
inGap = true;
}
} else {
if(score[i-1][j] + GAPEXTENSION > h) {
h = score[i-1][j] + GAPEXTENSION;
pointers[i][j] = 2;
inGap = true;
}
if(score[i][j-1] + GAPEXTENSION > h) {
h = score[i][j-1] + GAPEXTENSION;
pointers[i][j] = 1;
inGap = true;
}
}
if(0 > h) h = 0;
score[i][j] = h;
if(h >= max) {
max = h;
maxI = i;
maxJ = j;
}
}
}
double matches = 0;
String o1 = "", o2 = "";
while(!(maxI == 0 && maxJ == 0)) {
if(pointers[maxI][maxJ] == 3) {
o1 += s1.charAt(maxI);
o2 += s2.charAt(maxJ);
maxI--;
maxJ--;
} else if(pointers[maxI][maxJ] == 2) {
o1 += s1.charAt(maxI);
o2 += "_";
maxI--;
} else if(pointers[maxI][maxJ] == 1) {
o1 += "_";
o2 += s2.charAt(maxJ);
maxJ--;
}
}
StringBuilder a = new StringBuilder(o1);
b = new StringBuilder(o2);
o1 = a.reverse().toString();
o2 = b.reverse().toString();
a.setLength(0);
b.setLength(0);
for(int i = 0; i < Math.min(o1.length(), o2.length()); i++) {
if(o1.charAt(i) == o2.charAt(i)) matches++;
}
return matches/Math.min(o1.length(), o2.length());
}
これは、メソッド内で宣言するすべての変数 (2 つの int 配列と stringbuilders など) が、メソッドが実行されるたびにますます多くのオブジェクトを作成するためだと考えたので、それらをすべて静的フィールドに変更し、毎回クリアしました ( ex. Arrays.fill(score,0);) 新しいオブジェクトを作成する代わりに。
ただし、これはまったく役に立ちませんでした。それでも同じエラーが発生しました。
すべての計算を格納するハッシュセットが大きくなりすぎて、Java で格納できなくなっている可能性がありますか? ヒープ領域不足エラーが発生していないので、ちょっと奇妙に思えます。
また、コマンド ライン引数を変更して JVM により多くのスペースを与えましたが、それは役に立たなかったようです。
この問題に関する洞察は役に立ちます。ありがとう!