WinFuture-Forum.de: Java: Collection Für Primitive Datentypen - WinFuture-Forum.de

Zum Inhalt wechseln

Nachrichten zum Thema: Entwicklung
Seite 1 von 1

Java: Collection Für Primitive Datentypen


#1 _Fenix_

  • Gruppe: Gäste

geschrieben 18. August 2007 - 16:36

Hallo,
ich brauche einen Ersatz für die Java Collections, da ich große Datenmengen dynamisch im Speicher Verwalten muss und die Java internen Collections nur Objekte halten können. Das Problem ist, dass mit den Java Standard Klassen z.B. 60Byte für einen Integer draufgehen, der eigentlich nur 32Bit Informationen enthält.
Vlt. mal Source, um zu verdeutlichen, was ich meine:
		   Runtime runtime = Runtime.getRuntime(); // Runtime Objekt, das die verwendete Speichermenge auslesen kann
		   int i;
		   LinkedList blubb = new LinkedList();  // Die original LinkedList  aus java.utils
		   runtime.gc();  // Runtime Objekt Momentane Werte auslesen lassen
		   System.out.println("Speicherverbrauch vorher: " + (runtime.totalMemory()- runtime.freeMemory())); // Den verwendeten Speicher ausgeben
			
		   for (i = 0; i < 60; i++) {
			  blubb.add(new Integer(i)); // 60 Integer Objekte in der Liste ablegen
		   }
		   runtime.gc();  // Runtime neue Werte auslesen lassen
		   System.out.println("Speicherverbrauch nachher: " + (runtime.totalMemory() - runtime.freeMemory())); // Den jetzt verwendeten Speicher ausgeben


Gibt bei mir wieder:
Speicherverbrauch vorher: 302272
Speicherverbrauch nachher: 306216


Macht 3944 Byte Differenz, nachdem 60 Integer angelegt wurden, also etwa 60 Byte pro Integer (stark abgerundet). Ich habe schon testweise probiert, selbst eine stark vereinfachte Liste zu erstellen mit einem Iterator Objekt, dass direkt den primitiven Datentyp int hält:
public class listtest {
	
	class Iterator {
		int i;
		Iterator next;
	}
	
	private Iterator head;
	private Iterator current;
		
	public listtest() {
		head = new Iterator();
		current = head;
	}
	
	public void add(int i) {
		if (current.next == null) current.next = new Iterator();
		current = current.next;
		current.i = i;
	}
	
	public int next() {
		if (current.next != null) current = current.next;
		return current.i;
	}
	
	public void rewind() {
		current = head;
	}
	
}


Aber selbst so komme ich nicht unter 40Byte pro integer weg.

Das kann es aber nicht sein. Ich will ein Programm schreiben, dass Audiodaten verarbeitet und ich kann nicht bei einer Abtastrate von 8000 Samples pro Sekunde (und mehr) zwischen 40 und 60 Byte Speicher für jeden Sample draufgehen lassen - vor allem, da die eigentlichen Samples nur 16Bit quantisiert sind (32 Bit Integer nehme ich, weil ich im Laufe der Berechnungen, die ich damit anstelle, mehr als den 16Bit Zahlenraum brauche). Auf primitive Arrays (alla int [] bla = new int [60]) zurückzugreifen, kommt leider nicht in Frage, das wäre sinnloser Rechenaufwand beim Löschen und Verschieben von Zahlen.

Jetzt gibt es ja Libraries, wie PCJ, die Collections für primitive Datentypen anbieten. Allerdings habe ich Probleme, den stark abstrakten Code davon nachzuvollziehen (PCJ wurde extrem generisch programmiert und auf etliche Dateien aufgeteilt, sodass man den Überblick im Code sehr schnell verlieren kann). Das, was PCJ anbietet, ist mir auch zu viel, ich würde mir lieber etwas schlankeres selbst schreiben. Könnte mir jemand sagen, wie ich ein Collection Objekt für primitive Datentypen so in Java realisieren kann, dass nicht gleich etliche Byte für sinnlosen Overhead verschwendet werden? Gäbe es in Java ein Pointerverhalten, wie in C/C++, dann wäre es ja kein Problem, aber so bin ich leicht ratlos. Irgendeine Lösung muss es ja geben... ich kann mir nicht vorstellen, dass alle Javaprogramme, die dynamische Datenstrukturen brauchen, nur mit Wrapperklassen und massig sinnlosem Overhead arbeiten.

Vielen Dank für die Hilfe,
Fenix

Dieser Beitrag wurde von Fenix bearbeitet: 18. August 2007 - 16:44

0

Anzeige



#2 Mitglied ist offline   G.I.Joe 

  • Gruppe: aktive Mitglieder
  • Beiträge: 978
  • Beigetreten: 19. September 04
  • Reputation: 0

geschrieben 18. August 2007 - 16:46

Schreib doch selber eine Collection, z.B. eine ArrayList dürfte ja leicht zu machen sein. Das ist ja soweit ich weiss nur eine Klasse um ein Array rumgebastelt. Wenn der Platz im Array ausgeht wird einfach ein neues mit doppelter Größe erstellt und die bisherigen Daten werden reinkopiert. Ich denke die wichtigsten Sachen dürften sich in 30-40 Zeilen Code unterbringen lassen.
Eingefügtes Bild Eingefügtes Bild
0

#3 _Fenix_

  • Gruppe: Gäste

geschrieben 18. August 2007 - 16:56

Das könnte ich machen, aber das wäre nur eine pseudo Lösung. Ich möchte gerne die Datenstruktur einer Liste verwenden, weil ich eben die Vorteile davon, wie schnelles Löschen am Listenanfang, haben will. Alles in Arrays zu implementieren ist mir vor allem zu langsam, weil die Java Arrays ja nicht richtig dynamisch sind.. Dinge, wie realloc, gibt es in Java ja nicht. So müsste ich dann u.a. bei jeder Größenänderung das komplette Array kopieren - sinnloser Rechenaufwand.

Was ich noch als Lösung gefunden habe, empfinde ich als korruptes Gepfusche (denke das wird den meisten anderen auch so gehen):
http://www.cs.cmu.ed.../java/size.html meint:

Zitat

Don't initialize big arrays:
Although array initialization is a single statement in Java, the generated bytecode inserts one element at a time. If you've got a big array, this requires a lot of bytecode. You can save space by storing your data in a String and then parsing it into your array at runtime (tip from Andrew Scherpbier).

Dieser Beitrag wurde von Fenix bearbeitet: 18. August 2007 - 17:01

0

#4 Mitglied ist offline   G.I.Joe 

  • Gruppe: aktive Mitglieder
  • Beiträge: 978
  • Beigetreten: 19. September 04
  • Reputation: 0

geschrieben 18. August 2007 - 17:03

Beitrag anzeigenZitat (Fenix: 18.08.2007, 17:56)

Das könnte ich machen, aber das wäre nur eine pseudo Lösung. Ich möchte gerne die Datenstruktur einer Liste verwenden, weil ich eben die Vorteile davon, wie schnelles Löschen am Listenanfang, haben will. Alles in Arrays zu implementieren ist mir vor allem zu langsam, weil die Java Arrays ja nicht richtig dynamisch sind.. Dinge, wie realloc, gibt es in Java ja nicht. So müsste ich dann u.a. bei jeder Größenänderung das komplette Array kopieren - sinnloser Rechenaufwand.
Tja, dann weiß ich auch keine Lösung, alle Collections haben Overhead und/oder Rechenaufwand, egal ob HashSet, eine verlinkte Liste oder irgendeine Baumstruktur. Aber eine mit großzügigem Startwert angelegte ArrayList wäre doch sicher einen Versuch wert, zumal das Kopieren ja ziemlich fix gehen sollte, da ja alles im Speicher vorliegt.
Eingefügtes Bild Eingefügtes Bild
0

#5 _Fenix_

  • Gruppe: Gäste

geschrieben 18. August 2007 - 17:10

Ein bisschen Overhead wäre ja nicht tragisch, aber gleich das 10Fache von der Nutzdatenmenge, das ist absurd, finde ich. Wie kann sich eine Sprache, wie Java, sowas leisten? Listen, Bäume, etc. mit primitiven Daten drin sind doch essenziell. Und das es anders gehen würde, zeigen C++, Delphi, C# usw. ja zur genüge.

Dieser Beitrag wurde von Fenix bearbeitet: 18. August 2007 - 17:13

0

#6 Mitglied ist offline   G.I.Joe 

  • Gruppe: aktive Mitglieder
  • Beiträge: 978
  • Beigetreten: 19. September 04
  • Reputation: 0

geschrieben 18. August 2007 - 18:43

Tja, folgende zwei Lösungsmöglichkeiten könntest du noch versuchen:
- Über JNI (Java Native Interface) die Datenspeicherung in einen nativen Programmteil verfrachten (dann z.B. was in C)
- Eine Collection von primitiven Arrays. Du erstellst z.B. immer ein Array das die Daten einer Sekunde fassen kann, wenn das voll ist erstellst du ein neues. Die ganzen Arrays sammelst du wiederum in einer Collection. Falls Collections keine Arrays mögen, müsstest du diese evtl. noch kapseln.

Dieser Beitrag wurde von G.I.Joe bearbeitet: 18. August 2007 - 18:43

Eingefügtes Bild Eingefügtes Bild
0

#7 Mitglied ist offline   Braumeister-S 

geschrieben 12. September 2007 - 20:04

Hi, ich bin zwar nur auf der Suche nach was Anderem über dieses Thema gestolpert, aber vielleicht kannst Du was mit einer "IntegerFactory" erreichen. Wenn Du für jeden Wert nur eine Integer Instanz hast, kannst Du Deinen Ressourcenverbrauch einschränken.

Für die meist verwendeten Werte (falls es sowas gibt, hier wohl eher nicht) könntest du dort auch Konstanten definieren.

Für den Rest müsstest Du dir einen Cache implementieren.

Hier mit Objekten bzw. deren Referenzen zu arbeiten macht eher Sinn, wie jedes mal eine Instanz eines primitiven Datentyps zu erstellen.

Vielleicht kann man auf diese Art was erreichen.

Ach ja, Du schreibst auch, dass du eigentlich nur 16 Bit benötigst (nur bei Berechnungen mehr). Wenn Du nur diese Werte cachest, hast Du für diesen Wertebereich max. 65Tsd Integer Instanzen a 60 Byte. Also max. ca. 4MB belegt, die Du komplett im Cache halten kannst.

Gruß Stefan

Dieser Beitrag wurde von Braumeister-S bearbeitet: 12. September 2007 - 20:13

0

Thema verteilen:


Seite 1 von 1

1 Besucher lesen dieses Thema
Mitglieder: 0, Gäste: 1, unsichtbare Mitglieder: 0