Frage

Mein Ziel ist es, sicherzustellen, dass ein in Java zugewiesener Array für das zusammenhängende physische Gedächtnis zugewiesen wird. Das Problem, auf das ich betroffen bin, ist, dass die Seiten, über die ein Array ein Array zugewiesen wird, tendenziell nicht im physischen Gedächtnis angrenzt, es sei denn, ich habe ein wirklich großes Array zugewiesen.

Meine Fragen sind:

  • Warum sorgt ein wirklich großes Array Seiten, die im physischen Gedächtnis zusammenhängen?
  • Gibt es eine Möglichkeit, sicherzustellen, dass ein Array im physischen Gedächtnis zugewiesen wird, was das Array nicht wirklich groß macht?
  • Wie kann ich feststellen, in welcher Seite oder in welcher physischen Adresse ein Java -Objekt/-array vorhanden ist, ohne Cache -Hits/Cache -Misses zu messen?

Ich suche keine Antworten, um zu fragen, warum ich das in Java mache. Ich verstehe, dass C "mein Problem lösen" würde und dass ich gegen die grundlegende Natur von Java gehe. Trotzdem habe ich einen guten Grund dafür.

Die Antworten müssen nicht ständig garantiert werden. Ich suche nach Antworten, die die meiste Zeit funktionieren. Zusätzliche Punkte für kreative, außergewöhnliche Antworten, die kein vernünftiger Java-Programmierer jemals schreiben würde. Es ist in Ordnung, plattformspezifisch zu sein (x86 32-Bit 64-Bit).

War es hilfreich?

Lösung

Angesichts der Tatsache, dass der Müllsammler Objekte im (logischen) Speicher bewegt, werden Sie denke, Sie werden kein Glück mehr haben.

Über das Beste, was Sie tun können, ist zu verwenden Bytebuffer.allocatedirect. Das wird (in der Regel) nicht durch das GC (logische) Speicher bewegt, aber es kann in physischem Gedächtnis oder sogar in die Disc bewegt werden. Wenn Sie bessere Garantien wünschen, müssen Sie das Betriebssystem treffen.

Wenn Sie jedoch die Seitengröße so groß wie Ihr Haufen festlegen können, sind alle Arrays notwendigerweise physikalisch zusammenhängend (oder ausgetauscht).

Andere Tipps

Nr. Physical zusammenhängende Speicher erfordert eine direkte Interaktion mit dem Betriebssystem. Die meisten Anwendungen, JVM, enthalten nur praktisch zusammenhängende Adressen. Und ein JVM kann Ihnen nicht geben, was es nicht vom Betriebssystem bekommt.

Warum willst du es außerdem? Wenn Sie DMA -Transfers einrichten, verwenden Sie wahrscheinlich sowieso Techniken neben Java.

Ein bisschen Hintergrund:

Der physische Speicher in einem modernen PC ist in der Regel eine flexible Menge, bei austauschbaren DIMM -Modulen. Jedes Byte hat eine physische Adresse, sodass das Betriebssystem während des Bootes feststellt, welche physischen Adressen verfügbar sind. Es stellt sich heraus, dass die Anwendungen besser ausgehen, indem sie diese Adressen nicht direkt verwenden. Stattdessen verwenden alle modernen CPUs (und deren Caches) virtuelle Adressen. Es gibt eine Zuordnungstabelle für physische Adressen, die jedoch nicht abgeschlossen sein muss - Swap zu Festplatte wird durch die Verwendung von virtuellen Adressen aktiviert, die nicht den physischen Adressen zugeordnet sind. Ein weiteres Maß an Flexibilität wird durch eine Tabelle pro Prozess mit unvollständigen Zuordnungen gewonnen. Wenn der Prozess A eine virtuelle Adresse hat, die zu der physischen Adresse X ist, aber Prozess B nicht, kann der Prozess b auf keinen Fall an die physische Adresse X schreiben, und wir können diesen Speicher als exklusiv für den Prozess A. Offensichtlich betrachten. Damit dies sicher ist, muss das Betriebssystem den Zugriff auf die Kartierungstabelle schützen, aber alle modernen Osen.

Die Mapping -Tabelle funktioniert auf Seitenebene. Eine Seite oder eine zusammenhängende Untergruppe physischer Adressen wird einer zusammenhängenden Teilmenge virtueller Adressen zugeordnet. Der Kompromiss zwischen Gemeinkosten und Granularität hat dazu geführt, dass 4 KB Seiten eine gemeinsame Seitengröße sind. Da jedoch jede Seite ihre eigene Zuordnung hat, kann man nicht über diese Seitengröße hinausgehen. Insbesondere wenn Seiten aus dem physischen Gedächtnis vertrieben, auf die Festplatte ausgetauscht und wiederhergestellt werden, ist es durchaus möglich, dass das Ende einer neuen physischen Speicheradresse endet. Das Programm bemerkt nicht, da sich die virtuelle Adresse nicht ändert, nur die OS-verwaltete Zuordnungstabelle.

Ich würde denken, dass Sie verwenden möchten sun.java.unsafe.

Es kann Möglichkeiten geben, ein bestimmtes JVM dazu zu bringen, das zu tun, was Sie wollen, aber diese wären wahrscheinlich zerbrechlich, kompliziert und höchstwahrscheinlich sehr spezifisch für die JVM, seine Version, das Betriebssystem, auf dem es ausgeführt wird. Mit anderen Worten, verschwendete Anstrengung.

Ohne mehr über Ihr Problem zu wissen, denke ich, dass jemand helfen kann. Es gibt sicherlich keine Möglichkeit, dies in Java im Allgemeinen zu tun, höchstens bei einem bestimmten JVM.

Eine Alternative vorschlagen:

Wenn Sie wirklich Daten im zusammenhängenden Speicher speichern müssen, warum tun Sie dies nicht in einer kleinen C -Bibliothek und rufen Sie diese über JNI an?

Wie ich es sehe. Sie müssen noch erklären, warum

  • Diese primitiven Arrays sind im Gedächtnis nicht kontinuierlich. Ich verstehe nicht, warum sie im virtuellen Gedächtnis nicht kontinuierlich wären. (CF -Arrays des Objekts sind unwahrscheinlich, dass seine Objekte im Speicher kontinuierlich sind)
  • Ein Array, das im physischen Speicher nicht kontinuierlich ist (RAM, dh zufällig Zugriffsspeicher), hätte einen signifikanten Leistungsunterschied. zB messbare Unterschiede in der Leistung Ihrer Anwendung.

Es scheint, dass Sie wirklich nach einer niedrigen Möglichkeit suchen, Arrays zuzuweisen, da Sie es gewohnt sind, dies in C zu tun, und die Leistung ist ein Anspruch darauf, dies zu tun.

Übrigens: Zugriff auf bytebuffer.allocatedirect () mit Say getDouble ()/putDouble () kann langsamer sein, wenn nur ein Doppel [] verwendet wird, da er erstere JNI -Anrufe beinhaltet und letzteres gar keinen Anruf optimieren kann.

Der Grund, warum es verwendet wird, ist der Austausch von Daten zwischen den Räumen Java und C. zB nio Anrufe. Es funktioniert nur gut, wenn das Lesen/Schreiben auf ein Minimum gehalten wird. Ansonsten sind Sie besser dran, etwas im Java -Raum zu verwenden.

dh es sei denn, Sie sind klar, was Sie tun und warum Sie tun es, Sie können eine Lösung haben, mit der Sie sich besser fühlen, aber tatsächlich komplizierter ist und schlechtere Leistungen erbringen als die einfache Lösung.

Notiz Diese Antwort zu einer verwandten Frage, in der das System erörtert wird. IdentityHashCode () und die Identifizierung der Speicheradresse des Objekts. Das Fazit ist, dass Sie die Standard-Array-HashCode () -implementierung verwenden können, um die ursprüngliche Speicheradresse des Arrays zu identifizieren (vorbehaltlich der Anpassung in einem INT/32-Bit)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top