Ik ben tegen een probleem aangelopen dat ik eigenlijk niet had verwacht. Het gaat om een klasse waarmee ik van twee tekst bestanden een tree moeten creeren en in die tree elke node van een mooi x en y coordinaat moet voorzien.
Ik ga als volgt te werk. Eerst lees ik de twee input bestanden in een aparte vector. Vector 1 (uit bestand 1) bevat een lijst met begin nodes de tweede vector bevat een lijst met parent child relaties. Om de tree te kunnen creeren maak ik gebruik van een DOM Document object. Hier maak ik eerst een algemene root aan en voeg daarna voor elk object uit de eerste vector een child toe. Elke node bestaat uit een algemene tag name ("Node" in dit geval) met 3 attributen: id, x, y. De naam van de node zoals deze in de vector staat vul ik in bij het id attribuut en de x en y attributen laat ik leeg. Als ik deze start nodes heb ingevuld ga beginnen met het creeren van mijn boom aan de hand van de waarden in de tweede vector. Hiervoor heb ik een loop die per node de kinderen ophaalt van zichzelf en zijn siblings en zo steeds alles afgaat totdat er gen kinderen meer zijn. Hiervoor moet hij wel steeds voor elke node door de tweede vector loopen. Wat ik wel doe is als ik een of meerdere child nodes heb gevonden dan verwijderen ik deze uit de vector (met Vector.remove(index) methode). De tweede vector wordt dus steeds kleiner.
Als ik de tree heb gemaakt dan ga ik door de tree heen lopen om zo structureel alle nodes van een x en y coordinaat te voorzien. Ik doe dit nadat de tree klaar is omdat ik bij het toewijzen van achter naar voren werk (ik begin bij een leaf) omdat dit voor mij de duidelijkste weergave geeft.
Uiteindelijk moet ik een bestand genereren waarin de naam van elke node staat met daarachter de x en de y waarde. Hiervoor gebruik ik de Document.getElementByTagName("Node") waarbij alle nodes (hebeen immers allemaal de tag naam "Node") in een NodeList krijg en deze kan ik zo wegschrijven in een bestand.
Dit alles werkt op zich allemaal prima. Maar als ik wat grotere bestanden gebruik dan raakt Java heel sneller zonder geheugen. Pas met een -Xmx256m toevoeging krijg ik de melding niet meer. Het probleem is dan dat de verwerking dan heeeeeeel lang diuurt. Dit is het geval als ik 10000 startnodes heb (1e vector) en 20000 parent-child verwijzingen (2e vector).
Ik vraag me nu af waar dit aan kan liggen? Het inlezen van de bestanden is geen probleem. Deze zijn respectievelijk 1,65 Mb (waarin elke waarde 6x voorkomt, dus 60000 regels voor de utieindelijke 10000 nodes) en 891 kb voor de 20000 regels met parent-child verwijzingen.
Dan zou het natuurlijk kunnen dat mijn keuze voor de DOM structuur niet goed is. Het voordeel voor mij is dat ik zo makkelijk de parent-child-sibling structuur heb waarmee ik mijn tree kan bouwen en mijn coordinaten kan toewijzen. Maar de tree bevat uiteindelijk 20000 nodes en dat zou toch nog wel te doen moeten zijn. But please correct me if I'm wrong.
Wat voor mij dan nog zou het probleem zou kunnen zijn is het continue doorzoeken van de vector met 20000 elementen dit gebeurt precies 10000 keer. Maar die vector van 20000 zou dis steeds kleiner moeten worden.
Kortom ik weet niet waar de geheugen problemen vandaan komen en als ik java genoeg geheugen geef waarom hij zo vreselijk traag is. Is er een betere manier om dit alles aan te pakken?
Voor de volledigheid is hier mijn code:
Ik ga als volgt te werk. Eerst lees ik de twee input bestanden in een aparte vector. Vector 1 (uit bestand 1) bevat een lijst met begin nodes de tweede vector bevat een lijst met parent child relaties. Om de tree te kunnen creeren maak ik gebruik van een DOM Document object. Hier maak ik eerst een algemene root aan en voeg daarna voor elk object uit de eerste vector een child toe. Elke node bestaat uit een algemene tag name ("Node" in dit geval) met 3 attributen: id, x, y. De naam van de node zoals deze in de vector staat vul ik in bij het id attribuut en de x en y attributen laat ik leeg. Als ik deze start nodes heb ingevuld ga beginnen met het creeren van mijn boom aan de hand van de waarden in de tweede vector. Hiervoor heb ik een loop die per node de kinderen ophaalt van zichzelf en zijn siblings en zo steeds alles afgaat totdat er gen kinderen meer zijn. Hiervoor moet hij wel steeds voor elke node door de tweede vector loopen. Wat ik wel doe is als ik een of meerdere child nodes heb gevonden dan verwijderen ik deze uit de vector (met Vector.remove(index) methode). De tweede vector wordt dus steeds kleiner.
Als ik de tree heb gemaakt dan ga ik door de tree heen lopen om zo structureel alle nodes van een x en y coordinaat te voorzien. Ik doe dit nadat de tree klaar is omdat ik bij het toewijzen van achter naar voren werk (ik begin bij een leaf) omdat dit voor mij de duidelijkste weergave geeft.
Uiteindelijk moet ik een bestand genereren waarin de naam van elke node staat met daarachter de x en de y waarde. Hiervoor gebruik ik de Document.getElementByTagName("Node") waarbij alle nodes (hebeen immers allemaal de tag naam "Node") in een NodeList krijg en deze kan ik zo wegschrijven in een bestand.
Dit alles werkt op zich allemaal prima. Maar als ik wat grotere bestanden gebruik dan raakt Java heel sneller zonder geheugen. Pas met een -Xmx256m toevoeging krijg ik de melding niet meer. Het probleem is dan dat de verwerking dan heeeeeeel lang diuurt. Dit is het geval als ik 10000 startnodes heb (1e vector) en 20000 parent-child verwijzingen (2e vector).
Ik vraag me nu af waar dit aan kan liggen? Het inlezen van de bestanden is geen probleem. Deze zijn respectievelijk 1,65 Mb (waarin elke waarde 6x voorkomt, dus 60000 regels voor de utieindelijke 10000 nodes) en 891 kb voor de 20000 regels met parent-child verwijzingen.
Dan zou het natuurlijk kunnen dat mijn keuze voor de DOM structuur niet goed is. Het voordeel voor mij is dat ik zo makkelijk de parent-child-sibling structuur heb waarmee ik mijn tree kan bouwen en mijn coordinaten kan toewijzen. Maar de tree bevat uiteindelijk 20000 nodes en dat zou toch nog wel te doen moeten zijn. But please correct me if I'm wrong.
Wat voor mij dan nog zou het probleem zou kunnen zijn is het continue doorzoeken van de vector met 20000 elementen dit gebeurt precies 10000 keer. Maar die vector van 20000 zou dis steeds kleiner moeten worden.
Kortom ik weet niet waar de geheugen problemen vandaan komen en als ik java genoeg geheugen geef waarom hij zo vreselijk traag is. Is er een betere manier om dit alles aan te pakken?
Voor de volledigheid is hier mijn code:
code:
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
| /*
* Created on Dec 6, 2004
*/
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* @author Coert van den Thillart
*/
public class GenerateSNOTree {
static Document document;
int x = 0;
int y = 1;
int xcoord = 400;
int ycoord = 300;
FileOperator fo = new FileOperator();
public GenerateTree(String xc, String yc, String inputPath, String outputPath, boolean debug){
xcoord = Integer.parseInt(xc);
ycoord = Integer.parseInt(yc);
Vector supply = getSupplyNodes(inputPath+"\\supply.txt");
if(supply==null) terminate("Fatal Error:\tSupply file not found.");
System.out.println("Extracted "+supply.size()+" supply nodes!");
Vector arcList = getArcNodes(inputPath+"\\arc.txt");
if(arcList==null) terminate("Fatal Error:\tSupply file not found.");
System.out.println("Extracted "+arcList.size()+" arc nodes!");
Vector output = new Vector(0);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder builder = factory.newDocumentBuilder();
document = builder.newDocument();
Element root = (Element) document.createElement("Root");
document.appendChild(root);
Vector nodeList = new Vector(0);
Vector nodeLists = new Vector(0);
for(int telSupp=0; telSupp<supply.size(); telSupp++){
String supplyData = (String) supply.get(telSupp);
Element supplyEl = (Element) document.createElement("Node");
supplyEl.setAttribute("id", supplyData);
supplyEl.setAttribute("x", "");
supplyEl.setAttribute("y", "");
root.appendChild(supplyEl);
nodeList.add((Node) supplyEl);
}
nodeLists.add(nodeList);
boolean lastLeaf=false;
while(lastLeaf==false){
Vector childrenLists = new Vector(0);
//Iterate through nodeLists vector
for(int telNls=0; telNls<nodeLists.size(); telNls++){
Vector childrenList = new Vector(0);
Vector children = new Vector(0);
nodeList = (Vector) nodeLists.get(telNls);
//Iterate through nodeList to start parsing the nodes
for(int telNl=0; telNl<nodeList.size(); telNl++){
Node parent = (Node) nodeList.get(telNl);
String nodeId =
parent.getAttributes().getNamedItem("id").getNodeValue();
children = getChildNodes(arcList, nodeId, true);
if(children.size()==0){
if(childrenList.size()==0) continue;
else {
childrenLists.add(childrenList.clone());
continue;
}
}
else{
for(int telChild=0; telChild<children.size(); telChild++){
String childName = children.get(telChild).toString();
//Element child = (Element)
document.createElement(getNodeType(childName));
Element child = (Element)
document.createElement("Node");
child.setAttribute("id", childName);
child.setAttribute("x", "");
child.setAttribute("y", "");
parent.appendChild(child);
childrenList.add(child);
}
childrenLists.add(childrenList.clone());
}
}
}
if(childrenLists.size()>0)
nodeLists = (Vector) childrenLists.clone();
else lastLeaf=true;
}
}
catch (ParserConfigurationException pce) {
// Parser with specified options can't be built
pce.printStackTrace();
}
document = assignXY(document);
if(debug) writeXmlFile(document, outputPath+"\\SNO_Output.xml");
fo.writeCharFile(createOutput(document, "\t"), outputPath+"\\tmp_newnodexy");
System.out.println("Tab-delimited outputfile written "+outputPath+"\\tmp_newnodexy");
if(debug) {
fo.writeCharFile(createOutput(document, ","), outputPath+"\\output.csv");
System.out.println("Comma-delimited outputfile written: "+outputPath+"\\output.csv");
}
// Enable this function to generate orphan report
if(debug) writeOrphanReport(arcList, outputPath+"\\Arc_left.txt");
}
private Vector getSupplyNodes(String filePath){
File sourceFile = new File(filePath);
if(!sourceFile.isFile()) return null;
Vector output = new Vector(0);
String record = new String();
String lastLine = new String();
try{
FileReader src = new FileReader(sourceFile);
BufferedReader source = new BufferedReader(src);
while((record=source.readLine())!=null){
String[] line = record.split("\t");
for(int tel=0; tel<line.length; tel++)
line[tel] = line[tel].replaceAll("\"", "");
String strippedLine = line[0];
if(!strippedLine.equals(lastLine)){
lastLine = strippedLine;
if(line.length>0) output.add(strippedLine);
}
}
}
catch(Exception e){
e.printStackTrace();
}
return output;
}
private Vector getArcNodes(String filePath){
File sourceFile = new File(filePath);
if(!sourceFile.isFile()) return null;
Vector output = new Vector(0);
String record = new String();
String[] lastLine = new String[3];
try{
FileReader src = new FileReader(sourceFile);
BufferedReader source = new BufferedReader(src);
while((record=source.readLine())!=null){
String[] line = record.split("\t");
for(int tel=0; tel<line.length; tel++)
line[tel] = line[tel].replaceAll("\"", "");
String[] strippedLine = {line[1], line[2]};
if(!strippedLine[0].equals(lastLine[0])
|| !strippedLine[1].equals(lastLine[1])){
lastLine = strippedLine;
if(line.length>0) output.add(strippedLine);
}
}
}
catch(Exception e){
e.printStackTrace();
}
return output;
}
private static void writeXmlFile(Document doc, String filePath) {
try {
// Prepare the DOM document for writing
Source source = new DOMSource(doc);
// Prepare the output file
File destFile = new File(filePath);
if(!destFile.isDirectory()) destFile.mkdirs();
if(destFile.exists())destFile.delete();
destFile.createNewFile();
Result result = new StreamResult(destFile);
// Write the DOM document to the file
Transformer xformer =
TransformerFactory.newInstance().newTransformer();
xformer.transform(source, result);
System.out.println("XML generated at: "+filePath);
}
catch (Exception e) {
e.printStackTrace();
}
}
private Vector getChildNodes(Vector arcList, String parentNode, boolean removeFound){
Vector children = new Vector(0);
Vector found = new Vector(0);
for(int telArc = 0; telArc<arcList.size(); telArc++){
String[] arcLine = (String[]) arcList.get(telArc);
if(arcLine[0].equals(parentNode)
&& (arcLine[1].substring(0,2).equalsIgnoreCase("st")
|| arcLine[1].substring(0,2).equalsIgnoreCase("pr")
|| arcLine[1].substring(0,2).equalsIgnoreCase("sd"))) {
found.add(""+telArc);
children.add(arcLine[1]);
}
}
if(removeFound && found.size()>0){
for(int telFnd=found.size()-1; telFnd>=0; telFnd--){
String index = found.get(telFnd).toString();
arcList.remove(Integer.parseInt(index));
}
}
return children;
}
private String getNodeType(String name){
String code = name.substring(0,2);
if(code.equalsIgnoreCase("st")) return "Storage";
else if(code.equalsIgnoreCase("pr")) return "Process";
else if(code.equalsIgnoreCase("sd")) return "Storage_Demand";
else return code;
}
private void writeOrphanReport(Vector v, String outputpath){
FileOperator fo = new FileOperator();
StringBuffer input = new StringBuffer();
for(int telV=0; telV<v.size(); telV++){
String[] line = (String[]) v.get(telV);
for(int tStr=0; tStr<line.length; tStr++)
input.append(line[tStr]).append("\t\t");
String type = getNodeType(line[0]);
NodeList searchNodes = document.getElementsByTagName(type);
boolean found=false;
for(int tn = 0; tn<searchNodes.getLength(); tn++){
if(searchNodes.item(tn).getAttributes().getNamedItem("id").getNodeValue().equals(line[0])) found=true;
}
if(found)input.append("\t\t").append("X");
else input.append("\t\t").append("-");
input.append("\r\n");
}
fo.writeCharFile(input.toString(), outputpath);
System.out.println("Orphan report generated at: "+outputpath);
}
private Node getLeaf(Node start){
Node leaf = start;
boolean leafFound = true;
while(leafFound){
NodeList childNodes = start.getChildNodes();
if(childNodes.getLength()==0) {
leaf = start;
leafFound = true;
break;
}
else {
x++;
start = childNodes.item(0);
}
}
return leaf;
}
private Document assignXY(Document doc){
Node start = doc.getFirstChild();
boolean lastLeaf = false;
while(!lastLeaf){
Node leaf = getLeaf(start);
leaf.getAttributes().getNamedItem("x").setNodeValue(""+(x*xcoord));
leaf.getAttributes().getNamedItem("y").setNodeValue(""+(y*ycoord));
assignEmptyParents(leaf);
Node sibling = leaf.getNextSibling();
if(sibling==null){
Node parent = leaf.getParentNode();
if(parent==null || !parent.hasAttributes()) lastLeaf=true;
else{
x--;
while(parent.getNextSibling()==null) {
parent = parent.getParentNode();
if(parent==null || !parent.hasAttributes()) {
lastLeaf=true;
break;
}
else x--;
}
if(!lastLeaf) {
start = parent.getNextSibling();
y++;
}
}
}
else {
y++;
start = sibling;
}
}
return doc;
}
private void assignEmptyParents(Node leaf){
boolean notdone=true;
int xstart = x;
while(notdone){
Node parent = leaf.getParentNode();
if(parent!=null && parent.hasAttributes()){
x--;
if(parent.getAttributes().getNamedItem("x").getNodeValue()==""
&& parent.getAttributes().getNamedItem("y").getNodeValue()==""){
parent.getAttributes().getNamedItem("x").setNodeValue(""+(x*xcoord));
parent.getAttributes().getNamedItem("y").setNodeValue(""+(y*ycoord));
leaf = parent;
}
else notdone = false;
}
else notdone = false;
}
x = xstart;
}
private String createOutput(Document doc, String delim){
StringBuffer output = new StringBuffer();
NodeList nodes = doc.getElementsByTagName("Node");
for(int nTel=0; nTel<nodes.getLength(); nTel++){
Node n = nodes.item(nTel);
if(output.indexOf(n.getAttributes().getNamedItem("id").getNodeValue())==-1){
output.append("\""+n.getAttributes().getNamedItem("id").getNodeValue()+"\"").append(delim);
output.append(n.getAttributes().getNamedItem("x").getNodeValue()).append(delim);
output.append(n.getAttributes().getNamedItem("y").getNodeValue()).append("\r\n");
}
}
return output.toString();
}
private void terminate(String error){
System.out.println(error);
System.exit(1);
}
} |
[ Voor 42% gewijzigd door Deddiekoel op 16-12-2004 12:31 ]
Verlanglijstje: Switch 2, PS5 Pro Most wanted: Switch 2