private void main(PositionList Ps) {
if (xx >= 1900) setTextR(xx+" ");//Чтобы увидеть где программа тормозит
xx++;
PositionList Ps1 = new PositionList();
Ps1.setSize(Ps.size()+1);
this.copyPositionList(Ps,Ps1);// Если эту строку убрать, то программа работает нормально
this.main(Ps1);
private void copyPositionList(PositionList V, PositionList Vc) {
Position v;
int i = 0;
Position p = null;
while (i < V.size()){
v = V.list[i];
p = new Position();
if (v.questions != null) {// p.questions = copyTerms(v.questions);
Node t = v.questions.first;
NodeList TC = new NodeList();
while (t != null){
// TC.addLast(copyTerm(t)); -->
Node tc1 = new Node();
tc1.term = new Term();
tc1.term.name = t.term.name;
TC.addLast(tc1);
t = t.next;
}
p.questions = TC;
}
// p.vars = copyVars(v.vars); -->
p.vars = new LinkedList<Var>();
Iterator<Var> Vi = v.vars.iterator();
Var vv;
if(Vi.hasNext()){vv=Vi.next();}else{vv=null;}
while (vv != null){
Var vc = new Var();
vc.name = vv.name;
if (vv.term != null) {// На всякий случай
vc.term = new Term();
vc.term.name = vv.term.name;
}
p.vars.add(vc);
if(Vi.hasNext()){vv=Vi.next();}else{vv=null;}
}
p.n[0] = v.n[0];
Vc.list[i] = p;
i++;
}
Vc.list[i] = p;
}
Главная рекурсивная процедура main() запускается в фоновом потоке. Где-то на 2700 рекурсии main() прокрамма местами останавливается на 2 секунды, потом это происходит все чаще, пока через 100 рекурсий программа уже совсем топчится на месте. Внимание: это программа сокращенная версия моего приложения.
Если убрать из main() copyPositionList, то все нормально.
В чем дело?
Пробовал переводить все рекурсии в циклы и наоборот - все циклы в рекурсии. Результат один и тот же - при том же количестве основного цикла, что и числа рекурсий основной процедуры программа застапаривается.
Я перевел все рекурсии в циклы. Добавил в главный цикл:
if (xx==2600) {
Pos.clear();
Pos.add(Ps);
}
Тоесть, наш двумерный массив (своеобразный стэк для отката вычислений) очищается и в него снова добавляется один элемент одномерного массива с одним элементом.
Этот двумерный массив растет в цикле так:
→
1 1 1 1 1 … 1
2 2 2 2 2
3 3 3 3
4 4. 4
5. 5
6
7
N
После такого перезапуска массива, программа перестает на 2700 цикле зависать, как-будто занаво перезапустилась. Но у меня ведь максимальный объем массива половина от матрицы 2600х2600. Эти не такие и большие данные.
Что мне делать в этой ситуации?
Если дело не в алгоритме, то может сборщик мусора срабатывает в этот момент, хотя 2 сек вроде много.
Но наверно просто либо copyPositionList становится медленным с ростом размера списков, либо то, что вы со списками делаете потом.
Я добавил в основной цикл: Runtime.getRuntime().freeMemory()
для вывода на экран. И узнал.
Программа работает за раз не со всей свободной оперативной памятью, а берет по 25 мб. Когда заканчивается выделенная память - берет еще 25 мб (программа при этом виснет сек. на 2-3) и т.д.
Проблема в том, что мой двумерный массив (стэк) со временем занимает не один и не два таких размерчика из-за чего программа виснет на минуты.
Не могу найти в интернете: как задать программе, чтобы она хватала не по 25мб, а например по 100мб?
Так может не из-за памяти виснет. Добавьте вывод в каждой функции и т.п., чтобы узнать когда какая выполняется и сколько. Может вы там что-то сложное по времени делаете в основой части программы с этими списками.
Уже делал так. Стоило мне, например, для какой-нибудь переменной типа LinkedList убрать add(…), как программа висла в других местах.
Добавив Runtime.getRuntime().freeMemory() для вывода на экран показало, что когда заканчивается свободная память, программа привисает сикунды на 2-3. А потом выводится на экран, что свободной памяти снова 25мб. В скором времени это происходит все чаще, пока программа не зависает на долго.
Программа повторяла одни и те же действия, раз за разом.
...
if (v == V.getLast()&& w.equals("@")) setTextR("#0");
Vc.addLast(p);
if (v == V.getLast()&& w.equals("#0")) setTextR("#1");
if(Vi.hasNext()){v=Vi.next();}else{v=null;}
if (v == V.getLast()&& w.equals("#1")) setTextR("#2");
....
Она висла между setTextR("#0") и setTextR("#1"). А если убирал что-то из кода программы, то - между setTextR("#1") и setTextR("#2").
Так тут непонятно что когда выполняется из-за условий. Я бы просто в начало функций или каких-то важных блоков воткнул без всяких условий. Или профайлер.
Я еще упростил программу для нахождения возникшей проблемы:
LinkedList<PositionList> Pos = new LinkedList<PositionList>();
Pos.add(Ps);//Вставляем 1-ый одноэлементный список
while (xx <= 4000) {//Создаем матрицу со списками, пока без данных
if (xx >= 3400) {
setTextR(xx+"-"+Runtime.getRuntime().freeMemory()+" ");
}
int size0 = Pos.getLast().size();
Pos.add(new PositionList());
Pos.getLast().setSize(size0+1);
int i = 0;
Position p;
while (i < size0){
p = new Position();
p.questions = new NodeList();
p.vars = new LinkedList<Var>();
Pos.getLast().list[i] = p;
i++;
}
p = new Position();
p.questions = new NodeList();
p.vars = new LinkedList<Var>();
Pos.getLast().list[i] = p;
xx++;
}
На 3406 итерации цикла, программа виснет, а минут через две ее “выбрасывает”. Озу у меня хватает - 1гб свободной памяти. И не понятно почему так много памяти ест?
Я нашел, что у меня во многих местах после использования переменной объектного типа, не присваивается переменной null. Исправив это упущении, моя программа стала работать дольше, но по-прежнему не хватает памяти. Я узнал, что на моем смартфоне максимальное значение выделямой памяти для приложения - 512 мб, а для моего приложения этого оказалось мало. Пробовал с рут правами увеличить размер выделяемой памяти, но на моем телефоне рут прав нет! Теперь подумываю о приобретении хорошего смартфона.