Strona 3 z 4

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: piątek, 8 stycznia 2010, 14:29
przez Cyfrowy Baron
Robię to tak:

Kod: Zaznacz cały
    int iFileHandle;
   int iFileLength;
   int iBytesRead;
   int iBytesWrite = 0;
   char *pszBuffer;
   wstring wstr;

   locale loc(".ACP");
   const ctype<wchar_t> &ct = use_facet<ctype<wchar_t> >(loc);

    if(OpenDialog1->Execute())
    {
     try
      {
       iFileHandle = FileOpen(OpenDialog1->FileName, fmOpenRead);
       iFileLength = FileSeek(iFileHandle, 0, 2);
      FileSeek(iFileHandle, 0, 0);
      pszBuffer = new char[iFileLength+1];

      iBytesRead = FileRead(iFileHandle, pszBuffer, iFileLength);
      FileClose(iFileHandle);

      wstr.reserve(iBytesRead);
      for(unsigned i = 0; i < iBytesRead; ++i)
      {
      wchar_t wc = ct.widen(pszBuffer[i]);
      bool ok = ct.is(ctype<wchar_t>::alpha | ctype<wchar_t>::digit | ctype<wchar_t>::punct,wc);
      if(!ok) wc = 0x2588;
      wstr[i] += wc;
      }

      Memo1->Lines->SetText( const_cast<wchar_t*>( wstr.c_str() ) );
      delete [] pszBuffer;
       }
       catch(...)
      {
       Application->MessageBox( L"Can't perform one of the following file operations: Open, Seek, Read, Close.", L"File Error", IDOK);
      }
   }


Wczytywanie rzeczywiście przebiega dość szybko. Jak sie okazało u mnie program antywirusowy generował opóźnienie.

Różnica pomiędzy wstring i UnicodeString jest niewielka. Plik 20 MB - wstring = 26,217 sek.; UnicodeString = 26.648 sek.
Jak widać moje wyniki różnią się od waszych, gdyż UnicodeString jest wolniejszy. Są to oczywiście tylko pomiary porównawcze, gdyż w tle pracowały inne programu, które angażowały procesor w około 20 procentach, ale to tylko pokazuje, że nie ma większego znaczenia którego typu się użyje.

Lepsze wyniki uzyskałem stosując funkcję SetTexBuf zamiast SetText - wstring = 25,979 sek.

Kod: Zaznacz cały
Memo1->SetTextBuf(const_cast<wchar_t*>( wstr.c_str() ));


Jeszcze lepsze wyniki wstring = 22,368 sek. uzyskałem zastępując Memo obiektem RichEdit z WordWrap i PlainText ustawionymi na false.

Co ciekawe samo wykonanie kodu, bez przepisywania do Memo czy RichEdit na pliku 20 MB trwało około 6 sek.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: sobota, 9 stycznia 2010, 12:20
przez Witold
polymorphism napisał(a):Czyli wstring jest prawie 2x szybszy od VCL-owej wersji stringa.


przepraszam, pomyliłem się, zrobiłem tamten test w Debug + CodeGuard, nie w Release.
Poprawka (po 3 testy):

UnicodeString:
us.c_str()[i] + SetLength(): 687, 688, 687
us+=: 1875, 1812, 1796
us[i+1] + SetLength(): 922, 938, 937


wstring:
ws+= + Reserve(): 2157, 2203, 2203, ,873
ws[i] + Resize(): 688, 672, 672, 547
ws.at(i) + Resize(): 703, 704, 703

Na czerwono wstring w DEBUG, nie rozumiem tego :shock:

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: sobota, 9 stycznia 2010, 13:23
przez polymorphism
No faktycznie, coś dziwne te czasy. Nie spotkałem się jeszcze z czymś takim, żeby wersja release była ponad 2x wolniejsza od wersji debug.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: sobota, 9 stycznia 2010, 13:32
przez Cyfrowy Baron
No faktycznie, coś dziwne te czasy. Nie spotkałem się jeszcze z czymś takim, żeby wersja release była ponad 2x wolniejsza od wersji debug.


To chyba tylko u was. U mnie release jest 3.5 raza szybsze od debug.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: sobota, 9 stycznia 2010, 13:38
przez polymorphism
Nie "u was", bo u mnie różnica między debug a release jest około sekundowa (10MB), na korzyść tej drugiej oczywiście.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: niedziela, 10 stycznia 2010, 15:28
przez Witold
Poprzestawiałem jakoś niechcący ustawiania dla Release i wyszły mi głupoty. Utworzyłem nowy projekt i teraz wyniki powinny być dobre:

UnicodeString:
us.c_str()[i] + SetLength(): 422
us+=: 1516
us[i+1] + SetLength(): 609


wstring:
ws+= + Reserve(): 562
ws[i] + Resize(): 453
ws.at(i) + Resize(): 472

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: niedziela, 10 stycznia 2010, 19:29
przez polymorphism
O, teraz ma to sens. Jak widać, UnicodeString gorzej zarządza pamięcią, jest prawie 3x wolniejszy od wstringa.



Tak nawiasem:
us.c_str()[i] = ...

ta konstrukcja jest zła.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: poniedziałek, 11 stycznia 2010, 10:30
przez Witold
polymorphism napisał(a):Tak nawiasem:
us.c_str()[i] = ...

ta konstrukcja jest zła.


wiem , ale brak const (w opisie jest w deklaracji/kodzie - nie) przy wchar_t* może zachęcać to takich eksperymentów ;) i jest zastanawiający. Chciałem sprawdzić ile "kosztuje" to co jest w operatorze []:

Kod: Zaznacz cały
   wchar_t& __fastcall operator [](const int idx)
    {
      ThrowIfOutOfRange(idx);   // Should Range-checking be optional to avoid overhead ??
      Unique();                 // Ensure we're not ref-counted (and Unicode)
      return Data[idx-1];
    }


To co jest w helpie można przetłumaczyć jako zakaz ;) ?
The System::UnicodeString::c_str method is intended primarily for reading the value of the System::UnicodeString. To modify the System::UnicodeString’s value, use the [] operator or System::UnicodeString methods such as System::UnicodeString::Insert and System::UnicodeString::Delete.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: poniedziałek, 11 stycznia 2010, 13:02
przez polymorphism
Żeby było zabawniej metoda data zwraca to samo co c_str, tyle że const, choć sama nie jest const, w przeciwieństwie do c_str. Gdzie tu logika? :shock:

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: poniedziałek, 11 stycznia 2010, 16:22
przez Witold
polymorphism napisał(a):Żeby było zabawniej metoda data zwraca to samo co c_str, tyle że const, choć sama nie jest const, w przeciwieństwie do c_str. Gdzie tu logika? :shock:


Podejrzewam że dodali const gdzie mogli,tzn gdzie ta zmiana nie wpływała by na konieczność zmian w kodzie dla podobnych do tego:

Kod: Zaznacz cały
 
TFileStream *fs = new TFileStream(FileName, fmOpenread |
                                    fmShareDenyNone);
  try
    {
      AnsiString S;
      S.SetLength(fs->Size);
      fs->ReadBuffer(S.c_str(), fs->Size);
    }
  __finally
  {
    delete fs;
  }

Podobnie (SetLength(), .c_str()) można by robić dla WinApi.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: poniedziałek, 11 stycznia 2010, 17:19
przez polymorphism
Problem w tym, że ten const niczego nie zmienia, wnosi jedynie chaos.
Kod: Zaznacz cały
void foo(const AnsiString &str)
{
    str.c_str()[0] = 0;
}

wywołanie c_str dla obiektu stałego jest poprawne, zmiana zawartości str także, pomimo że jest to obiekt stały. Coś tu chyba nie gra...

Z tego co się orientuje, AnsiString/UnicodeString ma wbudowany mechanizm copy-on-write, i pytanie, co będzie zawierał string B:
Kod: Zaznacz cały
AnsiString A,B;
A = "X";
B = A;
A.c_str()[0] = 'Y';
cout << B.c_str(); <--- ???

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: wtorek, 12 stycznia 2010, 01:26
przez Witold
polymorphism napisał(a):wywołanie c_str dla obiektu stałego jest poprawne, zmiana zawartości str także, pomimo że jest to obiekt stały. Coś tu chyba nie gra...


myślę że mogli dać:
const char* c_str() const
char* c_str()

polymorphism napisał(a):Z tego co się orientuje, AnsiString/UnicodeString ma wbudowany mechanizm copy-on-write


A.Unique() powinno pomóc, może dla takich przypadków ta metoda jest dostępne w publicznym interfejsie ;)

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: wtorek, 12 stycznia 2010, 11:33
przez polymorphism
myślę że mogli dać:
const char* c_str() const
char* c_str()

Dokładnie ;)

A.Unique() powinno pomóc, może dla takich przypadków ta metoda jest dostępne w publicznym interfejsie ;)

Czyli B zawiera 'Y'? Jeśli chodzi o Unique, zapewne jest tak jak piszesz, tylko wydaje mi się, że mechanizm copy-on-write powinien być niewidoczny dla użytkownika.

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: wtorek, 12 stycznia 2010, 20:03
przez Witold
polymorphism napisał(a):
Czyli B zawiera 'Y'?


Tak jak założyłeś B zawiera "Y". Próbowałem szukać kodów które zapisują do String'a przez .c_str() i niewiele znalazłem. Nie wiem czemu c_str() nie zwraca const * char/const *wchar . Myślę że mogli to dodać ten const przy przechodzeniu na UnicodeString (wtedy i tak trzeba często dostosowywać stary kod).

Re: Wczytywanie plików binarnych do obiektu Memo - wg. pomysłu k

Nowy postNapisane: niedziela, 17 stycznia 2010, 16:14
przez mko000
Ok wszystko pięknie ładnie ale jak próbuje skompilować kod który Cyfrowy Baron podał wyżej wywala mi mnóstwo błędów. Jakie biblioteki należy dodać do tego kodu?