Bruker du filer for IPC for delt minne, er minnekartlegging et krav?

stemmer
19

Det er noen få prosjekter der ute som bruker MappedByteBuffers returnert av Java's FileChannel.map () som en måte å ha delt IPC-minne mellom JVMer på samme vert (se Chronicle Queue, Aeron IPC, etc.). Så vidt jeg kan si, denne apien bare sitter på toppen av mmap-samtalen. Implementering av Java tillater imidlertid ikke anonyme (ikke-støttede) mappinger.

Mitt spørsmål er, på Java (1.8) og Linux (3.10), er MappedByteBuffers virkelig nødvendige for å implementere delt minne IPC, eller vil noen tilgang til en felles fil gi den samme funksjonaliteten? (Dette spørsmålet er ikke opptatt av resultatimplikasjonen ved å bruke en MappedByteBuffer eller ikke.)

Her er min forståelse:

  1. Når Linux laster inn en fil fra disken, kopierer den innholdet i filen til sider i minnet. Den delen av minnet kalles sidebufferen. Så vidt jeg kan si, gjør det dette uavhengig av hvilken Java-metode (FileInputStream.read (), RandomAccessFile.read (), FileChannel.read (), FileChannel.map ()) eller native metode som brukes til å lese filen ( obsevet med "gratis" og overvåking av "cache" -verdien).
  2. Hvis en annen prosess prøver å laste den samme filen (mens den fremdeles er bosatt i cachen), oppdager kjernen denne og trenger ikke å laste inn filen på nytt. Hvis sidebufferen blir full, blir sider slettet - skitne blir skrevet ut til disken. (Sider blir også skrevet ut hvis det er en eksplisitt skylle til disk, og med jevne mellomrom med en kjernetråd).
  3. Å ha en (stor) fil allerede i hurtigbufferen er et betydelig ytelsesøkning, mye mer enn forskjellene basert på hvilke Java-metoder vi bruker for å åpne / lese den filen.
  4. AC-program som ringer mmap-systemanropet kan gjøre en ANONYMT kartlegging, som i hovedsak tildeler sider i cachen som ikke er støttet av en faktisk fil (så det er ikke nødvendig å gi ut faktiske skrivinger til disken), men Java ser ikke ut å tilby det (vil kartlegging av en fil i tmpfs oppnå det samme?)
  5. Hvis en fil lastes ved hjelp av mmap-systemanropet (C) eller via FileChannel.map () (Java), lastes egentlig filens sider (i hurtigbufferen) direkte inn i prosessens adresseområde. Ved å bruke andre metoder for å åpne en fil, lastes filen inn på sider som ikke er i prosessens adresseområde, og deretter de forskjellige metodene for å lese / skrive den filen kopierer noen byte fra / til disse sidene i en buffer i prosessens adresseområde . Det er en åpenbar ytelsesfordel å unngå kopien, men spørsmålet mitt er ikke opptatt av ytelse.

Så hvis jeg forstår riktig - hvis kartlegging gir en ytelsesfordel, virker det ikke som om det tilbyr noen "delt minne" -funksjonalitet som vi ikke allerede får, bare fra Linux-typen og sidebufferen.

Så la meg få vite hvor min forståelse er av.

Takk.

Publisert på 22/05/2020 klokken 21:20
kilden bruker
På andre språk...                            


2 svar

stemmer
0

Verdt å nevne tre punkter: ytelse, samtidige endringer, og minneutnyttelse.

Du har rett i vurderingen at MMAP-basert vanligvis vil tilby ytelsesfordel fremfor filbasert IO. Spesielt er ytelsesfordelen betydelig hvis koden utfører mye liten IO på filosofiens punkt.

vurder å endre N-byte: med mmap buffer[N] = buffer[N] + 1 , og med filbasert tilgang trenger du (minst) 4 systemanrop feilkontroll:

   seek() + error check
   read() + error check
   update value
   seek() + error check
   write + error check

Det stemmer at antallet faktiske IO (til disken) mest sannsynlig er det samme.

Det andre poenget som er verdt å merke seg samtidig tilgang. Med filbasert IO, må du bekymre deg for potensiell samtidig tilgang. Du må utstede eksplisitt låsing (før avlesningen) og låse opp (etter skrivingen), for å forhindre at to prosesser får feil tilgang til verdien samtidig. Med delt minne kan atomoperasjoner eliminere behovet for ekstra lås.

Det tredje punktet er faktisk minnebruk. I tilfeller der størrelsen på de delte objektene er betydelig, kan bruk av delt minne tillate et stort antall prosesser å få tilgang til dataene uten å tildele ekstra minne. Hvis systemer som er begrenset av minne, eller system som trenger å gi ytelse i sanntid, kan dette være den eneste måten å få tilgang til dataene på.

Svarte 29/05/2020 kl. 10:35
kilden bruker

stemmer
0

Mitt spørsmål er, på Java (1.8) og Linux (3.10), er MappedByteBuffers virkelig nødvendige for å implementere delt minne IPC, eller vil noen tilgang til en felles fil gi den samme funksjonaliteten?

Det kommer an på hvorfor du vil implementere IPC med delt minne.

Du kan tydelig implementere IPC uten delt minne; f.eks over stikkontakter. Så hvis du ikke gjør det av ytelsesgrunner, er det ikke nødvendig å gjøre IPC med delt minne i det hele tatt!

Så ytelse må være roten til enhver diskusjon.

Tilgang ved bruk av filer via Java classic io eller nio API-er gir ikke delt minnefunksjonalitet eller ytelse.

Hovedforskjellen mellom vanlig fil I / O eller Socket I / O versus delt minne IPC er at førstnevnte krever at applikasjonene eksplisitt lager read og write syscalls for å sende og motta meldinger. Dette innebærer ekstra syscalls, og innebærer kjernen kopiering data. Videre, hvis det er flere tråder, trenger du enten en egen "kanal" mellom hvert trådpar eller noe for å multipleksere flere "samtaler" over en delt kanal. Det siste kan føre til at den delte kanalen blir en flaskehals samtidig.

Merk at disse overheadene er ortogonale i forhold til Linux-sidebufferen.

Derimot, med IPC implementert med delt minne, er det ingen read og write syscalls, og ingen ekstra kopieringstrinn. Hver "kanal" kan ganske enkelt bruke et eget område av den kartlagte bufferen. En tråd i en prosess skriver data inn i det delte minnet, og det er nesten umiddelbart synlig for den andre prosessen.

Forbeholdet er at prosessene må 1) synkronisere, og 2) implementere minnebarrierer for å sikre at leseren ikke ser foreldede data. Men disse kan begge implementeres uten syscalls.

I oppvaskingen er IPC med delt minne med minnekartlagte filer >> raskere << enn å bruke konvensjonelle filer eller stikkontakter, og det er grunnen til at folk gjør det.


Du spurte også implisitt om delt minne IPC kan implementeres uten minnekartlagte filer.

  • En praktisk måte ville være å lage en minnekartet fil for en fil som lever i et minnesfilsystem; f.eks. en "tmpfs" i Linux.

    Teknisk sett er det fortsatt en minnekartlagt fil. Imidlertid påfører du deg ikke kostnader for å spyle data til disk, og du unngår den potensielle sikkerhetsproblemet ved at private IPC-data havner på disken.

  • Du kan i teorien implementere et delt segment mellom to prosesser ved å gjøre følgende:

    • I overordnet prosess, bruk mmap for å lage et segment med MAP_ANONYMOUS | MAP_SHARED .
    • Gaffelbarn prosesser. Disse vil ende opp med at alle deler segmentet med hverandre og foreldreprosessen.

    Imidlertid ville det ... være utfordrende å implementere det for en Java-prosess. AFAIK, Java støtter ikke dette.

Referanse:

Svarte 31/05/2020 kl. 06:17
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more