# Große Liste von Strings mit indiziertem Zugriff



## Unkenfängerin (7. Dez 2011)

Guten Morgen!

Folgendes Problem: Ich habe mehrere wachsende Liste von Strings (im Moment je 5000 Einträge, Wortlänge 5 - 10 Zeichen), bei denen ich als einzige wesentliche Operation einen Zugriff via des Indexes machen möchte. 

Bislang sind die Daten in TXT-Dateien gespeichert und werden dann einmal gelesen und im Speicher gehalten, das ist aber unschön aus mehreren Gründen: Das Lesen der Dateien dauert verhältnismässig lange, im Moment sind das bei mir 5 Dateien und 6 Sekunden. Der Zugriff danach ist zwar schnell, aber alles in allem muss ich solche Datenmengen ja nicht im Zwischenspeicher halten, wenn ich eigentlich nur einen zufälligen Wert abfragen möchte.

Für mich klingt das wie ein typischer Fall für eine (sehr schlanke) Datenbank, allerdings möchte ich 1 Sekunde Lesezugriff der Datei nicht gegen 10 Sekunden Datenbankinitialisierung tauschen. (Wobei sich das andererseits bei einer wachsenden Datenmenge rechnen würde.) Es ist außerdem einigermaßen wichtig, dass die Datenbank innerhalb des JARs liegt, und das habe ich so noch nie gemacht und vermute es wird so nicht gehen. Und dann wäre natürlich die Frage, ob es das ganze Programm nicht zu sehr aufblähen würde, wegen der zusätzlichen JARs und der DB.

Ich möchte also alles in allem die richtige Mischung aus Initialisierungszeit und Zugriffszeit finden, und dabei eine insgesamt möglichst kleine Anwendung erstellen. Wie würdet ihr das machen?

Liebe Grüße.


----------



## tfa (7. Dez 2011)

Ich kann mir nicht vorstellen, dass es 6 Sekunden dauert, ein paar Dateien von ein paar kB Größe einzulesen. Vielleicht kannst du hier einiges optimieren. (Liest du die vielleicht byteweise ein?)

Ansonsten kann man natürlich mit eingebetteten Java-DBs wie z.B. H2 arbeiten (H2 Database Engine). Ob sich das aber bei den geringen Datenmengen lohnt, ist eine andere Frage.


----------



## faetzminator (7. Dez 2011)

Ich würde dir auch zu einer kleinen DB raten.


Unkenfängerin hat gesagt.:


> Es ist außerdem einigermaßen wichtig, dass die Datenbank innerhalb des JARs liegt, und das habe ich so noch nie gemacht und vermute es wird so nicht gehen.


Nein, das geht nicht. Das laufende Jar kann man (logischerweise) nicht von einem zweiten Prozess überschreiben - wenn man darin etwas ändern möchte. Zusätzlich wärs dann wohl auch nicht mehr schneller als deine Methode.


Unkenfängerin hat gesagt.:


> Und dann wäre natürlich die Frage, ob es das ganze Programm nicht zu sehr aufblähen würde, wegen der zusätzlichen JARs und der DB.


Ich find das überhaupt nicht schlimm. Normalerweise baut man gleich auf einem Framework auf, verwendet noch 3 Apache Commons Libs und 7 sonstige (z.B. Joda Time) 



Unkenfängerin hat gesagt.:


> Ich möchte also alles in allem die richtige Mischung aus Initialisierungszeit und Zugriffszeit finden, und dabei eine insgesamt möglichst kleine Anwendung erstellen. Wie würdet ihr das machen?


Was verstehst du unter _möglichst klein_?


----------



## c_sidi90 (7. Dez 2011)

Eventuell kannst du ja Code posten, wo du die Datei einliest und abspeicherst. Wie schon erwähnt gibt es verschiedene Möglichkeiten ein solches Verfahren zu realisieren. Wir sollten einmal einen Blick drauf werfen.

Ansonsten zum Thema DB denke ich nicht, das die Initialisierungszeit bei 10 Sekunden liegt, diese Variante wäre in jedem Fall einfacher, schneller und komfortabler.

Lg


----------



## Unkenfängerin (7. Dez 2011)

Danke für die schnellen Antworten!



> Ich kann mir nicht vorstellen, dass es 6 Sekunden dauert, ein paar Dateien von ein paar kB Größe einzulesen. Vielleicht kannst du hier einiges optimieren. (Liest du die vielleicht byteweise ein?)


Kann natürlich an meinem Rechner liegen, und klar kann ich auch versuchen, da zu optimieren. Hab den Code im Moment nicht vorliegen, aber das ist ja auch erstmal mehr oder weniger Dummy-Code, damit ich die Daten erstmal habe. Was ist die beste Art des Einlesens für diesen Anwendungsfall? Macht es einen Unterschied, wo die Dateien liegen (JAR oder außerhalb) und welches Format sie haben (ZIP wird sicherlich langsamer sein, aber vielleicht gibt es andere Arten zur Platzoptimierung)?

Was mir Sorgen macht ist allerdings, dass dann diese vielen String-Listen sinnlos im Arbeitsspeicher rumliegt, obwohl mir ja im Prinzip die Information "Länge" genügen würde.



> Nein, das geht nicht. Das laufende Jar kann man (logischerweise) nicht von einem zweiten Prozess überschreiben - wenn man darin etwas ändern möchte.


Ich möchte nichts verändern. Die Datenbank wird nur einmal zur Entwicklungszeit gefüllt und dann nur noch gelesen.



> Was verstehst du unter möglichst klein?


Es geht um ein sehr kleines Framework, bei dem die Klassen an sich nur ein paar KB groß sind. Im Moment gehen die Datenlisten in den einstelligen MB Bereich, mit zusätzlichen 3rd Party Libs (egal ob es "nur" Abhängigkeiten sind oder irgendwie integriert) würde das natürlich noch mal sprunghaft ansteigen, was dem ganzen Sinn des Frameworks komplett zu wider laufen würde.



> Ansonsten zum Thema DB denke ich nicht, das die Initialisierungszeit bei 10 Sekunden liegt, diese Variante wäre in jedem Fall einfacher, schneller und komfortabler.


Von welchen DBs redest du? Ich habe bislang nur Erfahrung mit H2 und HSQL, und bei denen kommt die Initialisierungszeit etwa hin.


----------



## tfa (7. Dez 2011)

Unkenfängerin hat gesagt.:


> Was mir Sorgen macht ist allerdings, dass dann diese vielen String-Listen sinnlos im Arbeitsspeicher rumliegt, obwohl mir ja im Prinzip die Information "Länge" genügen würde.



Du meinst die String-Länge? Dann speicher doch nur die in die Listen.


----------



## langhaar! (7. Dez 2011)

Unkenfängerin hat gesagt.:


> (ZIP wird sicherlich langsamer sein, aber vielleicht gibt es andere Arten zur Platzoptimierung)?
> 
> Was mir Sorgen macht ist allerdings, dass dann diese vielen String-Listen sinnlos im Arbeitsspeicher rumliegt, obwohl mir ja im Prinzip die Information "Länge" genügen würde.



Du machst dir zu viele Gedanken um Optimierungen. Wieso willst du ein paar hundert Kb unbedingt komprimieren? Und wenn die 'sinnlos im Arbeitsspeicher herumliegenden' Strings wirklich ein Problem sein sollten (was ich nicht glaube), dann setzt die Referenzen der Objekte, die du nicht mehr benötigts auf null.

Wenn du über jedes Byte Kontrolle haben möchtest, ist die Java Welt ohnehin nicht sonderlich gut geeignet. Dann sollte man gleich auf C oder noch besser Assembler zurückgreifen.


----------



## ARadauer (7. Dez 2011)

Unkenfängerin hat gesagt.:


> Kann natürlich an meinem Rechner liegen,


oder an deinem Code... zeig mal, echt beim Einlesen von Daten kann man viel falsch machen.



Unkenfängerin hat gesagt.:


> Was mir Sorgen macht ist allerdings, dass dann diese vielen String-Listen sinnlos im Arbeitsspeicher rumliegt, obwohl mir ja im Prinzip die Information "Länge" genügen würde.


Dann halt dir die Länge im Arbeitsspeicher ;-)


----------



## tfa (7. Dez 2011)

langhaar! hat gesagt.:


> Du machst dir zu viele Gedanken um Optimierungen.


Wenn man aber zum Einlesen von ca. 250kB ca. 6 Sekunden braucht, ist definitiv irgendwo der Wurm drin. Da sollte man sich schon Gedanken machen.


----------



## langhaar! (7. Dez 2011)

Stimmt auch wieder. Das würde ich aber schon fast als Korrektur sehen, nicht als Optimierung 
Wer allerdings aus Platzgründen 250 Kb zippt, hat die 80er Jahre noch nicht hinter sich gelassen.

Anders gesagt, Optimierungen nur da, wo sie wirklich etwas bringen und nicht als Selbstzweck.


----------



## Unkenfängerin (7. Dez 2011)

```
BufferedReader bufferedReader = new BufferedReader(new FileReader("blub.txt"));
		ArrayList<String> values = new ArrayList<String>();

		String line;
		while ((line = bufferedReader.readLine()) != null) {
			values.add(line);
		}
```
Das wäre der Code zum Einlesen, eine Schwachstelle ist da ja auch offensichtlich: die ArrayList. Ist wie gesagt erstmal Dummy-Code, um weiter an den Kern-Funktionalitäten mit echten Daten arbeiten zu können. Ich wollte mich nur erstmal über Alternativen informieren, bevor ich anfange, einen völlig falschen Ansatz tot zu optimieren.



> Du meinst die String-Länge? Dann speicher doch nur die in die Listen.


Das wäre kein Problem, aber wie kriege ich dann einen einzigen Datensatz mit einem bestimmten Index? Dafür brauch ich ja alle Daten (zumindest bis zu diesem Punkt). Jedes Mal einzeln einlesen halte ich für wahnsinnig verschwenderisch.



> Und wenn die 'sinnlos im Arbeitsspeicher herumliegenden' Strings wirklich ein Problem sein sollten (was ich nicht glaube), dann setzt die Referenzen der Objekte, die du nicht mehr benötigts auf null.


Ich brauche alle Objekte zu beliebigen Punkten während der Laufzeit. Ich kann da nichts auf null setzen. Und wenn die reinen Textdateien 1 MB groß sind, sollten nach allem, was ich über Java weiß, die Listen zumindestens 3 - 5 MB groß sein. Es werden vermutlich leicht 10 bis 20 mal so viele Daten anfallen, und dann landet man an der Grenze von dem, was der Java standardmässig zur Verfügung hat (sind doch noch 128MB, oder nicht?). Und das alles für Daten, die EIGENTLICH in eine Datenbank gehören und damit eigentlich keinen Arbeitsspeicher wegnehmen sollten.



> Wieso willst du ein paar hundert Kb unbedingt komprimieren?


Das habe ich nicht gemeint. Was ich meinte war: Ich möchte die Größe meines Frameworks nicht verfünfzigfachen, weil ich 3rd-Party-Produkte einsetze. Von dem zusätzlichen Wartungsaufwand, den Abhängigkeiten notgedrungen erzeugen mal abgesehen.



> Anders gesagt, Optimierungen nur da, wo sie wirklich etwas bringen und nicht als Selbstzweck.


Da würde ich mal widersprechen. 

Das Projekt um das es geht ist ein Hobbyprojekt. Das letzte, was ich auf ähnliche Weise gemacht habe, hatte eine Berechnung, die 5 Minuten gedauert hat. Es war nicht zeitkritisch und da ich es nur privat angewandt habe hätte ich sehr gut damit leben können. Aber ich habe mich hingesetzt und mich in die Materie vertieft und optimiert. Verschiedene Implementierungen von List und Set untersucht, verschiedene Lösungen zu Sortierung, zum Permutieren, usw. Am Ende hat die selbe Berechnung 2 Sekunden gebraucht. 

Diese Optimierung war an sich nicht nötig, aber die Sachen, die ich im Verlauf dessen gelernt habe, sind unbezahlbar und bringen mich auch im Beruf weiter. Genauso ist es hier: Vielleicht ist es nicht nötig, Text-Dateien zu zippen - aber das Wissen, wie sich zum Beispiel der Zeitaufwand dafür im Verhältnis zur Größe verhält, kann mir später einmal sehr wervoll sein. 

Und deshalb kann Optimierung zum Selbstzweck durchaus angebracht sein - auch wenn es für das Problem im Moment keinen Vorteil bringt. Wie gesagt, ich wollte mich im Vorraus informieren, um am Ende konkrete Lösungsansätze untersuchen zu können - was am Ende in das fertige Produkt kommt, ist eigentlich Nebensache, wenn ich das mal so sagen darf.


----------



## SlaterB (7. Dez 2011)

der Code sieht nicht nach 6 sec aus und grundsätzlich sei einmal gesagt, dass eine Datenbank auch nicht zaubern kann,
die muss genauso Dateien von der Festplatte einlesen, ob TXT oder ein anderes Format ist nicht entscheidend,

eine DB ist sich auch nicht zu schade, jede Menge Daten auf einen Schwung einzulesen, und dann im Arbeitsspeicher das benötigte herauszusortieren, anders gehts auch gar nicht,

Java bzw. generell eigene Programme mögen in manchen Dingen langsam sein, schon einigermaßen komplzierte Dinge wie Suchen/ Sortieren kann man schnell falsch programmieren,
nur eine Datei einzulesen gehört aber weniger dazu, jedenfalls nicht mit dem geposteten Code, da hat die DB auch keinen besseren Turbo


250 KB oder paar MB sollten auf Festplatte geschrieben + gelesen + an eine DB geschicht + wieder zurückgeholt
nur wenige Sekunden dauern, in dem Bereich kann man aber wahrlich nicht viel optimieren,


----------



## fastjack (7. Dez 2011)

Kannst Du ein Beispiel aus der Datei posten?


----------



## bERt0r (7. Dez 2011)

Ich optimiere mal:

```
BufferedReader bufferedReader = new BufferedReader(new FileReader("blub.txt"));
        ArrayList<String> values = new ArrayList<String>(5000);
 
        String line;
        while ((line = bufferedReader.readLine()) != null) {
            values.add(line);
        }
```


----------



## faetzminator (7. Dez 2011)

```
List<String> values = ...
```
Wenn, dann gleich das Interface verwenden


----------



## bERt0r (7. Dez 2011)

Es ging mir eher um das was rechts steht, da bekannt ist dass es 5000 Einträge sind, kann man gleich ein 5000er Array in der ArrayList anlegen, anstatt bei jedem hinzufügen ein neues zu reservieren.
Aus Neugier: Was bringt es Performancemäßig die Variablen als Interface zu definieren? Meiner Ansicht nach ist das mehr eine Sache des wiederverwendbar und modular Programmierens.


----------



## faetzminator (8. Dez 2011)

bERt0r hat gesagt.:


> Aus Neugier: Was bringt es Performancemäßig die Variablen als Interface zu definieren?


Nichts.


bERt0r hat gesagt.:


> Meiner Ansicht nach ist das mehr eine Sache des wiederverwendbar und modular Programmierens.


Richtig, man soll einfach immer das "generellste" verwenden, dann kann man auch ohne Probleme die konkreten Klassen wechseln, ohne die ganze Applikation umstellen zu müssen.


----------



## tfa (8. Dez 2011)

bERt0r hat gesagt.:


> kann man gleich ein 5000er Array in der ArrayList anlegen, anstatt bei jedem hinzufügen ein neues zu reservieren.


ArrayList ist schon schlau genug, dass das nicht passiert. Wenn das Array voll ist, wird ein neues reserviert, das 50% größer ist. Trotzdem ist es natürlich besser, den Platz gleich richtig zu reservieren, wenn man denn weiß, wie viel Platz man braucht.


----------



## Unkenfängerin (8. Dez 2011)

Habe ich das jetzt richtig verstanden? Eine Datenbank sollte keinen merklichen Vorteil zu der reinen Text-Datei bringen? 
Ich finde das einigermaßen kurios, weil Datenbanken meines Erachtens genau für diesen Anwendungsfall gemacht sind. 



> eine DB ist sich auch nicht zu schade, jede Menge Daten auf einen Schwung einzulesen, und dann im Arbeitsspeicher das benötigte herauszusortieren, anders gehts auch gar nicht,


Das bezweifle ich extrem. Unsre Datenbanken hier haben Millionen wenn nicht Milliarden von Zeilen - die kommen definitiv NICHT alle in den Arbeitsspeicher, wenn eine einzige Zeile mit festgesetztem Index gebraucht wird.



> Es ging mir eher um das was rechts steht, da bekannt ist dass es 5000 Einträge sind, kann man gleich ein 5000er Array in der ArrayList anlegen, anstatt bei jedem hinzufügen ein neues zu reservieren.


Na ja, die 5000 Zeilen sind etwa, was jetzt drinne ist. Ich kann in keinster Weise dafür garantieren, dass es nicht mal mehr oder weniger werden. Wäre vielleicht eine andere Listenart besser geeignet, die nicht immer neue Arrays erstellt? 

Um den (imho) schnellsten möglichen Zugriff zu gewährleisten kommt die Liste dann eh in ein Array.



> Kannst Du ein Beispiel aus der Datei posten?


Adam
Beatrix
Cornelia
David
Eva
...


----------



## SlaterB (8. Dez 2011)

> Eine Datenbank sollte keinen merklichen Vorteil zu der reinen Text-Datei bringen? 

für dein Beispiel

-------

Millionen und Milliarden sind ganz andere Größen, schon das Ausrechnen sagt einen dass es mit Einlesen nicht hinkommt,
aber dein Beispiel KB/ wenige MB, das ist so wenig, da kann man gar nicht anders vorgehen als die entsprechenden Abschnitte komplett einzulesen

riesige Datenbestände werden in kleineren Einheiten gespeichert, ob diese nun 1 KB, 100 KB oder 1 MB groß sind ist fast egal,
wenn der Index sagt, dass die benötigten 5 Einträge A, B, C, D und E in den Abschnitten 17, 17, 34, 36 und 402 liegen,
dann werden diese 4 Festplatten-Abschnitte eingelesen, jeder enthält vielleicht 20 Tabelleneinträge, 
aus Abschnitt 17 werden zwei Ergebnisse rausgeholt, aus den anderen je einer

bei x MB und mehr an Daten lohnt sich das, aber der ganze Vorgang dauert immer eine minimale Zeit y,
und wenn man in der Zeit y auch gleich eine Textdatei mit Größe z einlesen kann, dann hat die DB eben nicht unbedingt einen Vorteil,

große Dateien erfordern viel Zeit, da ist die DB schneller, kleine Dateien können genauso direkt eingelesen werden,
denn wie gesagt, die DB kocht auch nur mit Wasser, muss auch auf die Festplatte zugreifen

von den ganzen anderen tausenden Funktionen einer DB abgesehen


----------



## Unkenfängerin (9. Dez 2011)

Interessant. Ich durfte heute den Tag über DB4O evaluieren, und hab es grade nur spaßeshalber an den Rest des Frameworks geklemmt - und siehe da, selbst mit dieser Datenbank, die nicht mal annäherungsweise für den Anwendungsfall  taugt, sank die Initialisierungszeit auf 500ms (bzw. 1000ms, wenn ich alle Daten auf einmal auslese und im Arbeitsspeicher halte). 

Da hier ja allen Anschein nach Unklarheiten über die Leistungsfähigkeit von Datenbanken bestehen, kann ich mich ja noch mal melden, falls ich Zeit finde, noch ein paar andre Datenbanken auszutesten. Definitiv falsch ist, dass damit keine Geschwindigkeitsverbesserung möglich ist.

(Wobei man der Fairness halber sagen muss, dass sich die Gesamtgröße des Frameworks durch diese spezielle Datenbank mindestens verfünffacht hat - aber wie hier viele schon richtiger Weise angemerkt haben, ist Speicherplatz deutlich weniger wertvoll als Zeit.)


----------



## SlaterB (9. Dez 2011)

> sank die Initialisierungszeit auf 500ms
was immer du da machst, das Einlesen einer 1 MB-Datei direkt kann davon dann nur 100 ms betragen
(normalerweise)


----------



## Unkenfängerin (9. Dez 2011)

Entschuldigung, ich habe nicht damit gerechnet, dass mein Arbeits-PC so viel langsamer ist als mein Laptop. Natürlich vergleiche ich so Äpfel mit Birnen. Also vergleichbare Daten vom Laptop:

Text-Datei: 2200ms für 5MB Dateien
DB4O: 500ms/1000ms (siehe oben) für eine 30MB Datenbank



> was immer du da machst, das Einlesen einer 1 MB-Datei direkt kann davon dann nur 100 ms betragen



Die Antwort macht mich ein wenig traurig, sagt aber auch was zu der Glaubwürdigkeit deiner Beiträge. Natürlich wird auch bei DB4O (ich würde mal pauschal behaupten: wie bei jeder Datenbank-Implementierung) NICHT die ganze Datei eingelesen. Das wäre ja der größte Schwachsinn und würde völlig dem Konzept, welches man mit Datenbanken verfolgt, entgegen laufen. Und war nebenbei bemerkt der Grund, warum ich noch die Zeit für das Auslesen aller Daten mit dazu addiert habe - um wenigstens halbwegs vergleichbar zu bleiben.


----------



## SlaterB (9. Dez 2011)

überlege mal mit welcher Geschwindigkeit ein Betriebssystem bzw. auch ein Java-Programm Dateien kopieren kann,
das Einlesen ist im Normalfall wirklich kein Bottleneck, vielleicht ist es in deinem Fall irgendwie blockiert, oder du arbeitest im Programm noch mit jeder Zeile einzeln und rechnest das dazu,
1 MB ist nichts, 5 MB auch nicht,
allein der Programmstart eines Java-Programms + JVM mit Einlesen von zig MB Java-Libs dauert natürlich ein bisschen,
aber das ist unabhängig von der User-Datei


----------



## langhaar! (10. Dez 2011)

Unkenfängerin hat gesagt.:


> Natürlich wird auch bei DB4O (ich würde mal pauschal behaupten: wie bei jeder Datenbank-Implementierung) NICHT die ganze Datei eingelesen. Das wäre ja der größte Schwachsinn und würde völlig dem Konzept, welches man mit Datenbanken verfolgt, entgegen laufen.



Wenn ich alle Daten, die in der Datenbank sind, selektiere, werde alle Daten in den Speicher gelesen. So einfach ist das. Das Einlesen der selben Datenmenge aus einer Datei ist schneller, da der Overhead zur Verwaltung der Daten fehlt. Eine Datenbank macht letztendlich auch nichts anderes, als die Daten von Festplatte zu lesen.

Da gibt's nichts zu rütteln und zu deuten und wenn das in deinen Heimtests anders ausfällt, so solltest du dort das Problem suchen.


----------



## SlaterB (10. Dez 2011)

> Wenn ich alle Daten, die in der Datenbank sind, selektiere, werde alle Daten in den Speicher gelesen. 
es werden sicherlich nicht alle selektiert, sonst wäre es ja zu einfach,
interessant ist nur ob bei benötigten 5 KB von 1 MB die DB schon was spart oder nicht


----------



## Unkenfängerin (10. Dez 2011)

> Wenn ich alle Daten, die in der Datenbank sind, selektiere, werde alle Daten in den Speicher gelesen.


Es ging um die reine Initialisierungszeit, und da wird nicht die gesamte Datenbank eingelesen. 

Also ich hab heute in der Mittagsruhe bisschen rumprobiert:

H2 und HSQL unterstützen es beide, aus einer JAR-Datei schreibgeschützt gelesen zu werden und haben mit 12 und 18 MB relativ kleine Datenbanken. Allerdings ist der Overhead beim Einlesen aller Daten zu viel, weswegen sie 6 und 4 Sekunden für alle jetzt vorhandenen Daten brauchen, das ist definitiv zu viel. (Im Moment ist der Datenbestand so klein, dass ich statistisch gesehen häufiger auf eine Tabelle zugreife, als es Zeilen gibt, von daher ist es sinnvoll, noch alles auf einmal auszulesen. Wenn der Datenbestand wächst werde ich die Tests aber wohl noch mal machen müssen.)

Zwischendurch war ich noch auf ein paar andere Ideen gekommen, und eine davon hat sich als tauglich rausgestellt: Java Properties. Ich weiß nicht, wie sie das schaffen, aber plötzlich wird die selbe Datenmenge in 600ms Sekunden eingelesen. Dazu noch lazy loading und es reicht erstmal für meinen Anwendungsfall. Es scheint manchmal doch zu helfen, out of the box zu denken und sich nicht einschüchtern zu lassen, nur weil alle behaupten, es geht nicht.

Grüße und danke für alle, die zumindest versucht haben, zu helfen!


----------



## bERt0r (10. Dez 2011)

Mach mal diesen Test auf deinem Rechner:

```
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;


public class FileTest 
{
	public static void main(String args[])
	{
		System.out.println("Erstelle Datei");
		File f=new File("vornamen.txt");
		try {
			PrintWriter writer=new PrintWriter(new FileWriter(f));

			for(int i=0;i<5000;i++)
			{
				writer.println("Sepp"+i);
			}
			writer.close();
		} catch (IOException e) 
		{
			e.printStackTrace();
		}
		System.out.println("Datei erstellt, beginne einlesen");
		long start=System.nanoTime();
		
		ArrayList<String> vornamen=new ArrayList<String>(5000);
		File f2=new File("vornamen.txt");
		try
		{
			BufferedReader reader=new BufferedReader(new FileReader(f2));
			String s=reader.readLine();
			while(s!=null)
			{
				vornamen.add(s);
				s=reader.readLine();
			}
			reader.close();
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		long end=System.nanoTime();
		System.out.println("Einlesen fertig, Zeit: "+(end-start)+" ns");
	}
}
```
Mein Ergebnis:
Erstelle Datei
Datei erstellt, beginne einlesen
Einlesen fertig, Zeit: 7211322 ns =7,21 Millisekunden


----------



## Unkenfängerin (11. Dez 2011)

Das passt doch gut 2s die ich auf dem Laptop gemessen habe - es ist die 100fache Datenmenge und der Garbagecollector springt an (nach einer langen Testreihe auf Arbeit sind wir zu dem Schluss gekommen, dass er die Zeit einer laufende Berechnung um 1 bis 1,5 Sekunden verlängert, natürlich abhängig davon, wie viel Überschneidung es zwischen den 2 Prozessen gibt).


----------



## bERt0r (11. Dez 2011)

Wie jetzt, hast du 5000 Einträge oder 500000? Es ist ein unterschied ob du jetzt 10 MB Daten auf 500 Einträgen oder 1 MB auf 5000000 Einträgen hast (die 10 Mb sind viel schneller geladen). Und der Garbage Collector sollte dabei gar nix zu sagen haben, weil alle Daten referenziert werden und gar nix gesammelt werden kann.


----------



## Unkenfängerin (13. Dez 2011)

Ich habe viele Dateien mit 5000 Einträgen, und im Moment um die 5 MB Daten. Und scheinbar hat der GC doch was zu sagen - immerhin springt er ja an. Vermutlich werden an irgendeiner Stelle die Strings kopiert statt die selbe Referenz weiter zu verwenden oder er recycelt die Listen, die nicht mehr gebraucht werden oder oder oder...


----------



## tuxedo (15. Dez 2011)

Mich wundert's gerade dass hier noch keiner auf die Idee gekommen ist folgendes in den Raum zu werfen:

1) Profiler
Wenn's irgendwo lange dauert, dann findet's der Profiler raus und sagt auch noch wo es lange dauert..

2) Java NIO
Ja, man glaubt's kaum, aber das N steht nicht für Netzwerk. Man kann mit NIO auch schnelle Fileoperationen machen. Wenn der Profiler ausspuckt dass das File lesen das zeitliche Problem ist: Evtl. mal auf FileChannel wechseln und nochmal profilen....

Alles andere ist doch nur sinnloses im dunkeln stochern nach dem try&error Prinzip sowie stumpfes Rätsel-Raten ...

Gruß
Alex


----------

