Мое приложение много мусорит. Смириться или можно исправить?

Ответить
leha
Сообщения: 2
Зарегистрирован: 26 сен 2013, 08:43

Мое приложение много мусорит. Смириться или можно исправить?

Сообщение leha » 26 сен 2013, 09:27

Уважаемые форумчане, научите!
Написал первое приложение - клиент для менеджера загрузок aria2.
При работе приложения парсятся json-строки (с помощью JsonReader) и создаются экземпляры соответствующего класса, заполняя его поля через рефлексию. Объектов довольно много и при каждом обновлении информации они создаются новые, а старые становятся добычей сборщика мусора. Т.к. я сделал обновление каждые 2 секунды, то в логе эмулятора с такой же интенсивностью идут сообщения от сборщика мусора, что он освободил сколько-то там памяти.
Вопрос 1 - это очень плохо или приемлемо?
Вопрос 2 - если очень плохо, то как бороться?

Код для ясности:
[syntax=java]
//наверное надо объявить абстрактным
public class JsonObject {

static public Object readValue(Class c, JsonReader reader) throws IOException, IllegalAccessException {

if (reader.peek() == JsonToken.NULL) {
reader.nextNull();
return null;
}

if (c.isArray()) {
if (reader.peek() != JsonToken.BEGIN_ARRAY) {
Log.d(DTAG, "Not an array");
reader.skipValue();
return null;
}
reader.beginArray();
ArrayList<Object> l = new ArrayList<Object>();
Object i;
while (reader.hasNext()) {
i = readValue(c.getComponentType(), reader);
if (i != null) l.add(i);
}
reader.endArray();
//if (l.size() > 0) {
Object[] a = (Object[]) Array.newInstance(c.getComponentType(), l.size());
return l.toArray(a);
//} else return null;
} else if (JsonObject.class.isAssignableFrom(c)) {
if (reader.peek() != JsonToken.BEGIN_OBJECT) {
Log.d(DTAG, "Not an object");
reader.skipValue();
return null;
}
//Log.d(DTAG, "Read object " + c.toString());
JsonObject o = null;
try {
o = (JsonObject) c.newInstance();
o.read(reader);
} catch (InstantiationException e) {
reader.skipValue();
}
return o;
} else if (c == String.class) {
return reader.nextString();
} else if (c == int.class) {
return Integer.valueOf(reader.nextInt());
} else if (c == long.class) {
return Long.valueOf(reader.nextLong());
} else if (c == boolean.class) {
if (reader.peek() == JsonToken.BOOLEAN)
return Boolean.valueOf(reader.nextBoolean());
else
return Boolean.valueOf(reader.nextString());
} else if (c == Object.class) {
return readValue(reader);
}
Log.d(DTAG, "Can not read value of " + c.toString());
return null;
}

public JsonObject read(JsonReader reader) throws IOException {

String name;
Field field;
Object o = null;

reader.beginObject();
while (reader.hasNext()) {
name = reader.nextName();
try {
//Log.d(DTAG, name);
field = this.getClass().getDeclaredField(name);
//Log.d(DTAG, field.getType().toString());
o = readValue(field.getType(), reader);
//Log.d(DTAG, o.toString());
field.set(this, o);
} catch (NoSuchFieldException e) {
reader.skipValue();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
Log.d(DTAG, o.toString());
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
reader.endObject();
return this;
}

}
[/syntax]
Для использования:
[syntax=java]
class GlobalStat extends JsonObject {
public int downloadSpeed;
public int uploadSpeed;
public int numActive;
public int numWaiting;
public int numStopped;
}

GlobalStat gs = new GlobalStat ().read(reader);
[/syntax]

Аватара пользователя
Mikhail_dev
Сообщения: 2386
Зарегистрирован: 09 янв 2012, 14:45
Откуда: Самара

Re: Мое приложение много мусорит. Смириться или можно исправ

Сообщение Mikhail_dev » 26 сен 2013, 12:31

Вопрос 1 - это очень плохо или приемлемо?
Есть большая и интересная статья, которая затрагивает данную тему. Там где-то в середине, написано о GC и о том, почему iOS вообще отказалась от GC. Плохо это или приемлемо, думаю вы потом сами решите. Но всё же советую прочитать полностью.
Почему веб-приложения на мобильных платформах работают медленно
Вопрос 2 - если очень плохо, то как бороться?
По мне вообще создание новых объектов, а тем более каждые две секунды - очень плохо. У нас используется похожее решение, когда идет парсинг JSON каждые 5 секунд, что порождает много лишних объектов. Я не занимался данной проблемой пока что, но понимаю что это плохо, что лучше иметь какой-нибудь пул объектов для их использования, а не порождать новые. Создание объекта - дорогая операция. Если найдете хорошее решение проблемы, дайте знать. :)

leha
Сообщения: 2
Зарегистрирован: 26 сен 2013, 08:43

Re: Мое приложение много мусорит. Смириться или можно исправ

Сообщение leha » 04 окт 2013, 21:16

Хорошего решения не нашел.
Попытался для большей части своих классов добавить пулы по аналогии с android.os.Message. Ощутимого эффекта на работу мусорщика не заметил.
Пришел к выводу что главный источник в моем случае это либо JsonReader, либо HttpURLConnection. Видимо это буфер в который считывается ответ сервера чистит мусорщик.
Кстати как должны выполняться периодические запросы к серверу? Я для каждого запроса в отдельном потоке выполняю:
Схематично[syntax=java]
URL url = new URL(aria2api.URL);
conn = (HttpURLConnection) url.openConnection();
... // настраиваю conn
OutputStream os = conn.getOutputStream();
os.write(request.toString().getBytes("UTF-8"));
...
JsonReader reader = new JsonReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
response.read(reader);
reader.close();
if (conn != null) conn.disconnect();
[/syntax]
Подозреваю, что делать так не совсем правильно...
Где бы глянуть пример клиента общающегося с сервером?

Ответить