Toon posts:

[C] File I/O cachen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik heb een programma geschreven wat MP3 inleest. Dit gaat een beetje traag en nu is een mogelijkheid om het te optimaliseren de volgende:
Nu lees ik het bestand van de disk, maar ik kan ook het hele bestand in het geheugen lezen en dan uit het geheugen lezen. Per bestand lees ik zo'n 15.000 keer een bitje en ik doe zo'n 5.000 keer een fseek. Ik heb het nog niet in mijn programma getest, maar in een testprogramma wat gewoon een groot bestand leest geeft dit een goede tijdswinst. In mijn programma kan ik echter niet het hele bestand in het geheugen lezen, want het bestand zou wel eens te groot kunnen zijn. Natuurlijk kan ik wel blokjes van 100KB ofzo per keer in het geheugen zetten.

Nu vroeg ik me alleen af of niemand dit al eerder bedacht heeft, of het al in het OS zit of dat ik het als library/programma/code kan downloaden.

  • bille
  • Registratie: Mei 2000
  • Laatst online: 05-08 23:45

bille

Don't call me Buff

ehm.. misschien kan je ffies uitleggen wat de bedoeling is van je programma.. want als je een TAG lezer aan het maken bent dan zit je wel een beetje op het verkeerde spoor geloof ik..

Ik neem aan dat je een soort Buffered Filereader wilt hebben? Zoals je begrijpt zijn er legio mensen die dat al eens gemaakt én gedeelt hebben.. dus ff goed zoeken op een opensource C site.

Ultra Pilammo 6666Mhz AMD, 4251Mbit/s RAM, Gefors V6666 MegaTurbo, 43" TFS, Ultra 80Gig Firewire netwerkkaart en 5D geluid met 66 speakers in 5 dimensies


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

De meeste file operaties zijn wel buffered. Ze lezen dan in blokjes van een bepaalde grootte, zoiets als 4k (de page-grootte) of de sector-grootte.

Maar zelf de hele tijd seeken is ook niet echt handig. Waarom zou je dat willen doen? Ik neem aan dat je alles wel sequentieel nodig hebt

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Mijn programma (mpck) leest alle frames in een MP3 bestandje.

Wat ik verder geprobeerd heb is de leesbuffer vergroten met setvbuf, maar dat gaf geen snelheidsverbetering. Het seeken doe ik om een frame over te slaan; het programma leest een frame header en evt. een checksum, doet daar wat mee en gaat dan naar de volgende header, die dus 417 bytes (ofzo) verderop ligt. Dit gebeurt met seeken. De frames zelf worden alleen ingelezen als de checksum gecontroleerd moet worden.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 01:56
Wellicht gaat een (absolute?) seek voorbij aan de gechachede data? Of is dat onzin? Ik denk dat dat soort aspecten nogal afhankelijk zijn van het platform en de gebruikte C library implementatie. Je kunt dus proberen of het helpt om relatief te seeken, in de hoop dat dan de achterliggende buffers gebruikt worden.

Als je een concrete verbetering constateert als je het bestand in één keer (of in grote blokken) inleest, dan is dat misschien de meest handige oplossing. Een buffer van een paar kilobyte voor het hele programma lijkt me niet echt een groot probleem. Je moet dan in plaats van te seeken echt vooruit lezen.

[ Voor 12% gewijzigd door Soultaker op 07-09-2003 21:15 ]


Verwijderd

Topicstarter
Ik dacht aan een buffer van 100 tot 1000 kilobyte, waarbij ik het implementeer door functies zoals cfopen, cfread, cfseek, cftell en cfclose te maken. cfseek verplaatst dan gewoon alleen een pointer als de data in de huidige buffer zit, en anders laad hij de goede data in de buffer en zet de pointer op de goede plek.

De standaard buffer size in Linux (waarop ik programmeer) met glibc is 8 KB, maar als ik dat vergroot merk ik niet echt verschil. Als ik daarentegen mijn buffer van 100KB gebruik gaat het wel een stuk sneller.

Ik wilde hier eerst even vragen hoe andere mensen erover dachten voordat ik heel mijn programma ga aanpassen. Als ik werkende gebufferde I/O heb laat ik wel even weten hoe het uitpakt.

Verwijderd

In principe heeft de kernel ook wel een gebufferde reader. read()/write() e.d. zijn standaard gebuffered met enkele kB (zie boven). Als je handmatig een buffer wilt aanmaken, doe dat dan vooral niet in userspace, omdat je dan data in userspace moet zetten, en dat is niet de bedoeling (kost extra CPU). Je kan handmatig een buffer opzetten met mmap(), en dan kan je zelf ook de grootte bepalen, en het is allemaal nog wel via de kernel. Ik denk dat dat is wat je zoekt.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

5000 fseeks per file is van lotje getikt en zal je inderdaad weinig performance opleveren. Ik zou het hele ding gewoon per definitie in 1 keer het geheugen intanken: je opmerking dat het bestand wel eens te groot zou kunnen zijn lijkt me knap vergezocht gezien dat de gemiddelde mp3-file 5-8Mb is en ik al jaren geen computer meer heb gezien met minder dan 64Mb RAM (waarbij bakken met zo weinig geheugen meestal ook nog 200+Mb pagefile hebben). Gewoon intanken en in 1 klap je proggel 10+ keer sneller maken dus.

Professionele website nodig?


Verwijderd

Topicstarter
curry684 schreef op 08 September 2003 @ 11:02:
je opmerking dat het bestand wel eens te groot zou kunnen zijn lijkt me knap vergezocht
MP3tjes van 80 MB ofzo komen wel eens voor, en ik durf er niet garant voor te staan dat iedereen 80 MB vrij geheugen in zijn computer heeft.

Mmap is inderdaad een goede oplossing om het bestand in het geheugen te laden, alleen moet ik het nog steeds zelf oplossen als het een erg groot bestand is.

  • CyBeR
  • Registratie: September 2001
  • Niet online

CyBeR

💩

Je programma leest dus alle frames in een mp3 file in, en doet er iets mee? Ik neem aan (afgeleid van de naam) dat ie ze checked op fouten?

Ik zou dan zelf gewoon elke aparte frame in een buffer opslaan, en er mee aan de gang gaan. Frame klaar? Volgende frame in buffer., etc. Nu moet je bij MPEG1 layer III ook rekening houden met inter-frame data, dus afhankelijk van wat je er mee doet kun je mischien het beste altijd 2 opvolgende frames in je buffer hebben staan.

All my posts are provided as-is. They come with NO WARRANTY at all.


Verwijderd

Topicstarter
CyBeR schreef op 08 September 2003 @ 17:48:
Je programma leest dus alle frames in een mp3 file in, en doet er iets mee? Ik neem aan (afgeleid van de naam) dat ie ze checked op fouten?

Ik zou dan zelf gewoon elke aparte frame in een buffer opslaan, en er mee aan de gang gaan. Frame klaar? Volgende frame in buffer., etc. Nu moet je bij MPEG1 layer III ook rekening houden met inter-frame data, dus afhankelijk van wat je er mee doet kun je mischien het beste altijd 2 opvolgende frames in je buffer hebben staan.
Ja, mijn programma leest frames uit een mp3 en controleert die op fouten. Voordat je een frame in een buffer op kan slaan moet je eerst bepalen of het een frame is. Dat doe ik nu door een byte voor byte te kijken of deze overeenkomen met een mp3 header. Een frame in een buffer opslaan heeft niet zoveel zin, omdat ik de inhoud van de frames niet echt gebruik; ik seek er overheen. Ik gebruik dus alleen 4 bytes per frame.

Ik denk dat ik toch een soort paging systeem ga schrijven, wat 100KB per keer in een buffer stopt.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Verwijderd schreef op 08 September 2003 @ 17:19:
[...]
MP3tjes van 80 MB ofzo komen wel eens voor, en ik durf er niet garant voor te staan dat iedereen 80 MB vrij geheugen in zijn computer heeft.
Nog nooit zo'n geschift grote MP3 gezien, en incluis swap heeft zelfs de meest verstokte 16mb Win95 gebruiker genoeg geheugen.

Maja als jij de moeite wil doen via memorymapped files te werken: go ahead :P

* curry684 zou het persoonlijk in C++ met een FileProvider interface oplossen waar je afhankelijk van de systeemmogelijkheden een langzame of all-in-memory methode achter instantieert, ben je meteen klaar voor iedere communicatiemechanisme :z

Professionele website nodig?


  • Apache
  • Registratie: Juli 2000
  • Laatst online: 17-08 14:28

Apache

amateur software devver

curry684 schreef op 08 September 2003 @ 18:30:
[...]

Nog nooit zo'n geschift grote MP3 gezien, en incluis swap heeft zelfs de meest verstokte 16mb Win95 gebruiker genoeg geheugen.
....
carl_cox-essential_mix-2001-04-01 - 164MB

en k'heb er een 15 tal die > 100MB zijn vnl livesets.

Zoiezo zou ik eerst kijken naar de filesize en aan de hand daarvan de ideale buffer size bepalen.

een hele mp3 inlezen als hij onder de 10 MB is en anders in blokken.

If it ain't broken it doesn't have enough features


  • Varienaja
  • Registratie: Februari 2001
  • Laatst online: 14-06-2025

Varienaja

Wie dit leest is gek.

Wat doen jullie allemaal moeilijk.

Je moet van voor naar achter dat bestand door. Waarom lees je niet gewoon (in stukjes) het hele bestand, en negeer je de stukken die niet nodig zijn? Dan rag je met tientallen Mb's per seconde door zo'n mp3-tje heen.

Siditamentis astuentis pactum.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Apache schreef op 08 September 2003 @ 19:15:
Zoiezo zou ik eerst kijken naar de filesize en aan de hand daarvan de ideale buffer size bepalen.
vreemd, een buffergrootte heeft namelijk an sich niets te maken met de filegrootte. Zoals ik bovenin deze topic postte kun je beter rekening houden met onderliggende hardware, en bijvoorbeeld page sizes (4k) of sector sizes van je hdd gebruik maken.
Vooral die sector size is nuttig, omdat je hdd op sector-niveau leest, en niet op byte-niveau, dus hoe je ook leest, je haalt altijd blokken van sectoren op

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Varienaja schreef op 08 September 2003 @ 19:20:
Wat doen jullie allemaal moeilijk.

Je moet van voor naar achter dat bestand door. Waarom lees je niet gewoon (in stukjes) het hele bestand, en negeer je de stukken die niet nodig zijn? Dan rag je met tientallen Mb's per seconde door zo'n mp3-tje heen.
mijn idee...en anders blokken van 1 mb per keer lezen...

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • Apache
  • Registratie: Juli 2000
  • Laatst online: 17-08 14:28

Apache

amateur software devver

.oisyn schreef op 08 September 2003 @ 19:23:
[...]


vreemd, een buffergrootte heeft namelijk an sich niets te maken met de filegrootte. Zoals ik bovenin deze topic postte kun je beter rekening houden met onderliggende hardware, en bijvoorbeeld page sizes (4k) of sector sizes van je hdd gebruik maken.
Vooral die sector size is nuttig, omdat je hdd op sector-niveau leest, en niet op byte-niveau, dus hoe je ook leest, je haalt altijd blokken van sectoren op
klopt, maar als je de hele mp3 gaat inlezen en je komt er dan eentje tegen van 160MB op een machine met 128MB geheugen gaat hij vast als een gek swappen, daarom bepaald je een aparte size (10MB bvb) waardoor hij 17x een blok kan lezen en daarop al z'n bewerkingen uitvoeren.

If it ain't broken it doesn't have enough features


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 04:06

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ja, daarom moet je ook blokken gebruiken, wat dat betreft zijn we het eens, maar jij zei dat je die buffergrootte moet af laten hangen van de filegrootte, wat ik dus nogal vreemd vond. Aan een buffergrootte die rekening houdt met de hardware heb je veel meer

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Verwijderd

Topicstarter
Grote bestanden in blokken inlezen en kleine bestanden in zijn geheel inlezen gebeurt natuurlijk vanzelf. Namelijk als je blokken van bijvoorbeeld 5 MB gebruikt, dan wordt alles onder de 5 MB in zijn geheel ingelezen.

De tips om een buffergrootte vast te stellen zijn een goed idee. Is de sectorgrootte bij alle harde schijven gelijk?

Ik heb nu een beetje moeite met de implementatie, want mmap werkt niet met fopen, en met open weet ik geen manier om achter de grootte van het bestand te komen. Moet ik het dan eerst stat-ten? De grootte van het bestand is namelijk wel handig, als ik weet waar ik op moet houden met lezen. Mmap vertelt me namelijk niet hoeveel er over is of hoeveel er overgeplaatst is. Misschien is een implementatie met fread iets in een buffer plaatsen aangemaakt met malloc toch makkelijker, maar mmap is dan weer sneller. Iemand ideeen hierover?

Verwijderd

Verwijderd schreef op 08 september 2003 @ 17:19:
Mmap is inderdaad een goede oplossing om het bestand in het geheugen te laden, alleen moet ik het nog steeds zelf oplossen als het een erg groot bestand is.
Hoezo? Zeg dat je een buffer van 100kB (+/- 25 frames) pakt, je hebt toch maximaal 1 frame per keer nodig, dus hoef je al geen backward seeks meer te doen. Desnoods in Linux 2.6.x met O_STREAM openen in open() (disablet de backward seek cache, die heb je niet meer nodig) en je bent klaar. Uiteraard kun je meerdere delen van het bestand tegelijk mappen als je dat wilt. Als je aan het einde van de buffer bent, kun je een nieuwe map maken en zo kun je vliegensvlug door het bestand bladeren.

Dan hoef je (eventueel) slechts een flinterdun filesize-over-mmap-position+size-wrapper over mmap() heen te schrijven, en je bent klaar. Toch? :?.

[edit]
Verwijderd schreef op 08 September 2003 @ 22:16:
Ik heb nu een beetje moeite met de implementatie, want mmap werkt niet met fopen, en met open weet ik geen manier om achter de grootte van het bestand te komen. Moet ik het dan eerst stat-ten? De grootte van het bestand is namelijk wel handig, als ik weet waar ik op moet houden met lezen. Mmap vertelt me namelijk niet hoeveel er over is of hoeveel er overgeplaatst is. Misschien is een implementatie met fread iets in een buffer plaatsen aangemaakt met malloc toch makkelijker, maar mmap is dan weer sneller. Iemand ideeen hierover?
:?. Man fileno. En met open+fstat kun je dat inderdaad ook vinden. :).

[edit2]
dotcode schreef op 09 September 2003 @ 16:47:
Je kan toch gewoon testen of je genoeg geheugen hebt voor het hele file. Als je dat niet hebt doe je de niet efficente manier. Anders lees je gewoon het hele file in.
Geheugenverspilling, lelijke code, dubbele code, foeilelijk concept, error prone, bovendien is de "niet-efficiente manier" net zo efficient als de file in een keer inlezen (erger nog, omdat je minder geheugen gebruikt is het nog efficienter), mits je het goed implementeert.

[ Voor 45% gewijzigd door Verwijderd op 09-09-2003 17:39 ]


  • dotcode
  • Registratie: Augustus 2003
  • Laatst online: 14-08 11:19

dotcode

///\00/\\

Je kan toch gewoon testen of je genoeg geheugen hebt voor het hele file. Als je dat niet hebt doe je de niet efficente manier. Anders lees je gewoon het hele file in.
Pagina: 1