C# Fájlfelolvasás és String összehasonlítás gyorsítása

C# Fájlfelolvasás és String összehasonlítás gyorsítása
2017-11-12T04:49:32+01:00
2017-11-13T00:35:05+01:00
2022-10-15T21:36:14+02:00
L Maqvus
Sziasztok,

Van több szöveges fájl adatbázisom amibe termék adatokat tárolok. Egy sor egy termék adat. Az adatbázis fájlok 1,5gb-5gb-ig is terjedhetnek.

Próbálok írni egy kereső algoritmust, ami a termék szériaszáma alapján kikeresi a termék adatait. A termék szériaszáma az első 52 bájt, sztringként ábrázolva. 

A probléma:
Ha az adatbázist másolom a meghajtón pár perc alatt átmásolja, ha két meghajtó közt másolom akkor szintén hasonló idő alatt végigfut. Így gondolom a felolvasás is ilyen intervallum alatt kellene hogy végigfusson.

Egy másik adatfájlból felolvasott szériaszámokat szeretnék kikeresni. A termékadatokat tartalmazó fájlból. Ez olyan 50.000 termék, (Időintervallumos és speciális feltételeknek megfelelő szériaszámok, sajnos Stochasztikus és a nagy adatbázisban nem szekvenciálisan helyezkednek el ezek a termékek, így nem elég csak az elsőt kikeresni, és felolvasni az utána lévő 50.000 szériaszámot)

Viszont a program feldolgozási ideje órákban mérhető(6-8 óra!). Nem tudok rájönni mi lassítja be az algoritmust.

A felolvasásra Stream readert használok, ami soronként fut(ennek a másolásos teszt miatt nem szabadna lassunak lennie), utána levágom a stringből az első 52 karaktert. 

Utána végigfutok egy 50000 elemü tömbön amin összehasonlítja az adatokat. Ennek se kellene túl sokáig tartania, mégis összeségében nagyon mengő a feldolgozási idő, van ötletetek mit csinálok rosszul?

Előre is köszönöm a válaszokat!

String Line,Serial; long Proceed; using (StreamReader sr = new StreamReader(Filename)) { while (sr.Peek() >= 0) { Line = sr.ReadLine(); Serial= Line.Remove(0, 52); for (int i = 0; i < Serials.Length; i++) { if (Serials[i] == Serial) { File.AppendAllText("Founded", Line); textBox1.Invoke((MethodInvoker)(() => textBox1.Text = textBox1.Text + Line + "\n")); } } Proceed = Proceed + Line.Length + 1; } }
Előre is köszönöm!
Mutasd a teljes hozzászólást!
Valamiért meg akarják veled újra íratni, de igazából a .NET-nek van Dictionary(TKey, TValue) Class (System.Collections.Generic) -je.
A kulcs típust passzintsd az ID-d formátumához. Ha az pl. egy String, ne akarjál belőle mindenáron számot készíteni, mert még ha itt és most sikerülne is, a jövőben bármikor visszaüthet - hagyd meg Stringnek.
Mutasd a teljes hozzászólást!

  • Ez nem túl optimális megoldás. Szedd két részre és az eredményeket külön tárold. De miért nem generálsz indexfájlt hozzá amiben kereshetsz? (serial,fájlnév,offset). Gyakran változnak a fájlok amiben keresel?
    Mutasd a teljes hozzászólást!
  • Nem dolgozom C#-ban, de rákerestél már?
    Ha nem ez a problémád, akkor
    Mutasd a teljes hozzászólást!
  • for (int i = 0; i < Serials.Length; i++) if (Serials[i] == Serial){ ... }
    Ez a borzalmasan lassu resz. Amikor 50ezer dolog kozul linearisan keresel es ezt vegrehajtod 100millioszor.

    Tobb lehetoseg is van:
    - rendezed a Serials listat es binarisan keresel benne. (25ezer osszehasonlitas helyett csak 16)
    - A serial-bol generalsz egy 32bites hash-t es az alapjan keresel binarisan. Vegul kezeled az esetleges tobb talalatot.
    - 20bites hash-t generalsz es egyszeruen lookup-olsz egy array-bol. A tobbes talalatokat itt is kezelni kell, de nagy valoszinuseggel az 50ezer elem az 1millio elemu tombben szépen elosztva talál magának helyet.
    - Ha a serial-ban rengetek allando karakter van, de bizonyos karakterhelyek nagyon is divergensek, azokat eleve fel lehetne hasznalni hash kepzeshez, ekkor nem muszaj valami lassabb algot hasznalni.

    Szoval aggodalomra nincs ok, mert sok lehetoseg van még ebben...
    Mutasd a teljes hozzászólást!
  • A fájlok fixek viszont van már belőle 25GB :)
    Nem látom mitől lenne az indexfájlos megoldás gyorsabb? Hisz ott is hasonló struktúrában kellene tárolnom. Ott is fel kellene olvasnom, és ott is ciklusonként kellene 50ezer keresést megvalósítanom.
    Mutasd a teljes hozzászólást!
  • Sajnos nem ilyen egyszerű, az adatok hash-ét is tartalmazza, hogy megelőzhető lehessen az adatmanipuláció, az egyediséget pedig a dátum/idő biztosítja, viszont ez is a hash része...



    Elfelejtettem említeni, hogy a szériaszám 20 bájtos. 
    1. opciós lehetőség: 
      a, 20 bájtot számként kezelem(biginteger?), és növekvő sorrendben rendezem a Serial tömböt.
      b, Felolvasott szeriaszámot pedig intervallum felezéssel Keresem meg a tömbben. 
    Itt a kérdés, hogy egy byte array -> Bigintegeres konverzió mennyire gyors?

    2. opciós lehetőség
    Ugyan az mint az 1 csak sima integert képzek belőle. És valósznüleg int=int összehasonlítás gyorsabb mint a String = String, így nembaj ha végigfutok rajta. Viszont nem ismerek ilyen algoritmust ami stringből csinál int-et.

    3. lehetőség viszont nem jött át.
    Mutasd a teljes hozzászólást!
  • Fel tudsz rakni a netre példa adatokat?
    (Pár10 MB a source file-bol es a Serials lista.)

    "Viszont nem ismerek ilyen algoritmust ami stringből csinál int-et." Én, meg jópáran itt viszont ismerünk. Ha pedig látnánk minta adatokat, akkor egyszerûbb lenne konkrétabb módszert is ajánlunk neked.
    Mutasd a teljes hozzászólást!
  • Az indexeléssel pont azt nyered hogy az rendezhető is meg kevesebb adatmennyiség
    Mutasd a teljes hozzászólást!
  • Valamiért meg akarják veled újra íratni, de igazából a .NET-nek van Dictionary(TKey, TValue) Class (System.Collections.Generic) -je.
    A kulcs típust passzintsd az ID-d formátumához. Ha az pl. egy String, ne akarjál belőle mindenáron számot készíteni, mert még ha itt és most sikerülne is, a jövőben bármikor visszaüthet - hagyd meg Stringnek.
    Mutasd a teljes hozzászólást!
  • Köszönöm szépen,



    Erre volt szükségem.
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd