Bonjour,
J'ai besoin de récupérer un assez grand nombre d'informations depuis un serveur, et je parse donc un fichier XML.
J'ai beaucoup d'entrées dans ce fichier XML, et je créé environ 3000 objets Client qui seront stockés dans une liste ArrayList<Client>.
Pour information, j'utilise toutes les informations (toutes les balises, tous les attributs...) du fichier XML.
Je n'ai donc pas spécialement besoin d'un système qui saute plein de balises/tags ou autre.
Je connais donc plusieurs moyens pour parser un fichier XML : DOMDocument, XmlPullParser, et SAX.
J'ai effectué plusieurs tests, et voici ce qui en sort dans mon cas :
- SAX est le plus rapide, mais on voit plusieurs actions du Garbage Collector dans le logcat.
- DOMDocument est le moins rapide, et on voit plusieurs actions du Garbage Collector (c'est sans doute le pire, et je m'en doutais).
- XmlPullParser est au milieu en terme de rapidité, et c'est celui qui demande le moins d'action du Garbage Collector.
Code Trace du logcat à l'exécution : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 01-28 09:01:02.923: E/SAX(2063): début SAX 01-28 09:01:03.113: D/dalvikvm(2063): GC_CONCURRENT freed 92K, 3% free 6337K/6471K, paused 27ms+5ms, total 74ms 01-28 09:01:04.273: D/dalvikvm(2063): GC_CONCURRENT freed 29K, 2% free 6735K/6855K, paused 29ms+35ms, total 126ms 01-28 09:01:05.163: D/dalvikvm(2063): GC_CONCURRENT freed 12K, 2% free 7129K/7239K, paused 30ms+4ms, total 106ms 01-28 09:01:06.043: D/dalvikvm(2063): GC_CONCURRENT freed 14K, 2% free 7515K/7623K, paused 29ms+55ms, total 138ms 01-28 09:01:06.713: D/dalvikvm(2063): GC_CONCURRENT freed 16K, 2% free 7894K/8007K, paused 23ms+22ms, total 124ms 01-28 09:01:06.873: E/SAX(2063): fin SAX 01-28 09:01:29.313: E/DOM(2114): début DOM 01-28 09:01:29.534: D/dalvikvm(2114): GC_CONCURRENT freed 96K, 4% free 6332K/6535K, paused 20ms+15ms, total 74ms 01-28 09:01:31.894: D/dalvikvm(2114): GC_CONCURRENT freed 30K, 2% free 6726K/6855K, paused 22ms+28ms, total 176ms 01-28 09:01:33.713: D/dalvikvm(2114): GC_CONCURRENT freed 15K, 2% free 7126K/7239K, paused 30ms+21ms, total 134ms 01-28 09:01:35.523: D/dalvikvm(2114): GC_CONCURRENT freed 16K, 2% free 7507K/7623K, paused 19ms+22ms, total 98ms 01-28 09:01:37.126: D/dalvikvm(2114): GC_CONCURRENT freed 79K, 2% free 7850K/8007K, paused 29ms+18ms, total 144ms 01-28 09:01:37.723: E/DOM(2114): fin DOM 01-28 09:01:57.684: E/XmlPullParser(2166): début XmlPullParser 01-28 09:01:57.884: D/dalvikvm(2166): GC_CONCURRENT freed 97K, 4% free 6334K/6535K, paused 9ms+13ms, total 91ms 01-28 09:02:01.714: D/dalvikvm(2166): GC_CONCURRENT freed 67K, 3% free 6686K/6855K, paused 31ms+9ms, total 112ms 01-28 09:02:02.744: E/XmlPullParser(2166): fin XmlPullParser
Code Aperçu du fichier XML : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 <?xml version="1.0" encoding="UTF-8"?> <clients> <client machin="fesfse" truc="sfeg" /> <client machin="srg" truc="dfhjjtr" /> ... </client>
Code Aperçu de l'asynctask : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 public class XMLTask extends AsyncTask<Void, Void, ClientAdapter> { private String url; private Context context; private MonListener monListener; public XMLTask(String url, Context context, MonListener monListener) { this.url = url; this.context = context; this.monListener = monListener; } @Override protected ClientAdapter doInBackground(Void... params) { try { List<Client> clients; Log.e("ClientXmlParser", "début"); ClientXmlParser parser = new ClientXmlParser(); clients = parser.parse(Network.streamUrl(this.url)); Log.e("ClientXmlParser", "fin"); Log.e("DOM", "début"); URL mUrl = new URL(this.url); DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); Document doc = builder.parse(new InputSource(mUrl.openStream())); Element racine = doc.getDocumentElement(); NodeList liste = racine.getElementsByTagName("client"); Element client; // Parcours des clients clients = new ArrayList<Client>(); int nbClient = liste.getLength(); for (int i = 0; i < nbClient; i++) { client = (Element) liste.item(i); clients.add(new Client(client.getAttribute("truc"), client.getAttribute("machin"), ...)); } Log.e("DOM", "fin"); Log.e("SAX", "début"); URL url = new URL(this.url); ClientHandler handler = new ClientHandler(); XMLReader xmlReader = SAXParserFactory.newInstance().newSAXParser().getXMLReader(); xmlReader.setContentHandler(handler); xmlReader.parse(new InputSource(url.openStream())); clients = handler.getClientsList(); Log.e("SAX", "fin"); if (clients == null || clients.size() == 0) { return null; } else { return new ClientAdapter(clients, this.context, R.layout.clientList); } } catch (Exception e) { return null; } } @Override protected void onPostExecute(ClientAdapter adapter) { if (adapter != null) { this.monListener.onSuccess(adapter); } else { this.monListener.onError(); } } }
Code Aperçu de la classe ClientHandler (SAX) : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 public class ClientHandler extends DefaultHandler { private List<Client> clients_list; public ClientHandler() { this.clients_list = new ArrayList<Client>(); } @Override public void startElement(String nameSpaceURI, String localName, String qName, Attributes attributs) throws SAXException { if (localName.equals("client")) { String machin = attributs.getValue("machin"); String truc = attributs.getValue("truc"); this.clients_list.add(new Client(machin, truc)); } } public List<Client> getClientsList() { return this.clients_list; } }
Code Aperçu de la classe ClientXmlParser (XmlPullParser) : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 public class ClientXmlParser { private static final String namespace = null; // pas de namespace public List<Client> parse(InputStream inputStream) throws XmlPullParserException, IOException { try { XmlPullParser parser = Xml.newPullParser(); parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false); parser.setInput(inputStream, null); parser.nextTag(); return readClients(parser); } finally { inputStream.close(); } } private List<Client> readClients(XmlPullParser parser) throws XmlPullParserException, IOException { List<Client> clients = new ArrayList<Client>(); parser.require(XmlPullParser.START_TAG, namespace, "clients"); while (parser.next() != XmlPullParser.END_TAG) { if (parser.getEventType() != XmlPullParser.START_TAG) { continue; } String name = parser.getName(); if (name.equals("client")) { clients.add(readClient(parser)); } else { skip(parser); } } return clients; } private Client readClient(XmlPullParser parser) throws IOException, XmlPullParserException { parser.require(XmlPullParser.START_TAG, namespace, "client"); String machin = parser.getAttributeValue(null, "machin"); String truc = parser.getAttributeValue(null, "truc"); ... // TODO : nextTag + require OU next ? //parser.nextTag(); //parser.require(XmlPullParser.END_TAG, namespace, "client"); parser.next(); return new Client(machin, truc, ...); } private void skip(XmlPullParser parser) throws XmlPullParserException, IOException { if (parser.getEventType() != XmlPullParser.START_TAG) { throw new IllegalStateException(); } int depth = 1; while (depth != 0) { switch (parser.next()) { case XmlPullParser.END_TAG: depth--; break; case XmlPullParser.START_TAG: depth++; break; } } } }
Question 1 : Est-ce mieux d'utiliser XML ou JSON ? Pourquoi ?
Question 2 : Est-ce que mon code est correcte ?
Question 3 : Par rapport à ce dont j'ai besoin, quelle est le meilleur parser XML selon vous ?
Question 4 : Que signifie ces différentes actions du Garbage Collector ?
Question 5 : Pourquoi la mémoire ne redescends pas ? (nombres en gras : GC_CONCURRENT freed 111K, 2% free, 14394K/14599K, paused 24ms+6ms total 173ms)
Une fois que je quitte l'activité qui affiche la liste, les objets ne sont-ils pas censés être détruits/désalloués état donné que je ne m'en sert pas en dehors de cette activité ?
Pire, si je lance plusieurs fois de suite l'activité de récupération/création de la liste, on voit bien que la mémoire augmente et on arrive même à un message "Clamp target GC heap...".
D'ailleurs, j'ai testé avec 20.000 entrées et le système force l'application à se fermer (sauf avec XMLPullParser).
Code Trace du logcat après plusieurs exécutions : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 01-28 08:58:05.751: D/dalvikvm(1993): GC_CONCURRENT freed 92K, 3% free 6341K/6535K, paused 29ms+9ms, total 89ms 01-28 08:58:07.001: D/dalvikvm(1993): GC_CONCURRENT freed 26K, 2% free 6735K/6855K, paused 26ms+4ms, total 78ms 01-28 08:58:07.770: D/dalvikvm(1993): GC_CONCURRENT freed 12K, 2% free 7134K/7239K, paused 29ms+4ms, total 98ms 01-28 08:58:08.550: D/dalvikvm(1993): GC_CONCURRENT freed 13K, 2% free 7513K/7623K, paused 22ms+4ms, total 104ms 01-28 08:58:09.250: D/dalvikvm(1993): GC_CONCURRENT freed 16K, 2% free 7898K/8007K, paused 37ms+57ms, total 154ms 01-28 08:58:12.560: D/dalvikvm(1993): GC_CONCURRENT freed 50K, 2% free 8372K/8519K, paused 23ms+4ms, total 176ms 01-28 08:58:13.860: D/dalvikvm(1993): GC_CONCURRENT freed 39K, 2% free 9024K/9159K, paused 22ms+21ms, total 127ms 01-28 08:58:17.340: D/dalvikvm(1993): GC_CONCURRENT freed 61K, 2% free 9899K/10055K, paused 52ms+24ms, total 274ms 01-28 08:58:19.590: D/dalvikvm(1993): GC_CONCURRENT freed 63K, 2% free 11052K/11207K, paused 27ms+0ms, total 136ms 01-28 08:58:24.331: D/dalvikvm(1993): GC_CONCURRENT freed 81K, 2% free 12568K/12743K, paused 22ms+34ms, total 183ms 01-28 08:58:29.841: I/dalvikvm-heap(1993): Clamp target GC heap from 16.094MB to 16.000MB 01-28 08:58:29.841: D/dalvikvm(1993): GC_CONCURRENT freed 111K, 2% free 14394K/14599K, paused 24ms+6ms, total 173ms
Merci d'avance pour votre aide.
Partager