Lazarus (FPC) vs Java

LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

Hej! Pewnie takich porównań było już dużo, ale czy ktoś ma doświadczenie z Lazarusem w połączeniu z bazami danych? Czy to lepiej funkcjonuje niż Java + Appache Derby? Lazarus przypomina bardzo Delphi i C++ Buildera i widzę ciekawe komponenty bazodanowe, tylko pytanie jak to realnie działa?
P.S. Z ciekawości przerobiłem taki programik z Javy do Lazarusa i okazało się że np. program w Javie tą samą operacje wykonuje 6 sekund, a wersja napisana w Lazarusie 2,5 sekundy...

msm
Kwestia optymalizacji, założę się że niektórzy daliby radę przyśpieszyć Javę do 2 albo 1 sekundy.
0

A kod napisany w c plus wykonuje się około 20 razy szybciej.. To sprawka przenosnosci kodu itd. pomimo tego wolałbym javę.. Lazarus to padaka.

vpiotr
Jakieś konkrety pls, "padaka" i "cool" nie są dobrym określeniem funkcjonalności / wydajności / popularności softu.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

Będę mieć chwilę czasu to przerobie kod na C++ (biblioteka wxWidgets) i na C# Podejrzewam, że C# będzie trochę szybszy od Javy, a C++ najszybszy

Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:19 minut
0

Kilka uwag:

  1. Na Ubuntu Java lata sporo szybciej niż Mono: Ubuntu 32-bit Core 2 Quad Ubuntu 64-bit Core 2 Quad
  2. H2 Database powinno być ok 2x szybsze niż Apache Derby: http://www.h2database.com/html/performance.html
  3. GUI w Javie możesz spróbować zaklepać w JavieFX 2.0 - jest wtyczka (do NetBeansa przynajmniej) dodająca wsparcie dla tej wersji JavyFX
  4. Musiałeś skopać implementację w Javie, wątpliwe by kod Pascalowy był szybszy od Javowego (tzn porównujemy kompilatory/ maszyny wirtualne)

"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
edytowany 1x, ostatnio: Wibowit
02
  • Rejestracja:prawie 14 lat
  • Ostatnio:około 8 lat
  • Postów:1176
0

Jakiej bazy danych użyłeś w przypadku Lazarusa i w przypadku Javy? Tej samej czy czegoś innego?
Baza danych to najczęściej wąskie gardło aplikacji, więc jeżeli użyłeś różnych baz danych to raczej to jest główna przyczyna w różnicach w wydajności.

edytowany 1x, ostatnio: 0x200x20
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

Tzn. akurat ten program to nie jest typowo bazodanowy...
Kod zamieniający znaki w plikach :

Kopiuj
 
procedure TForm1.Zamien_BitBtnClick(Sender: TObject);
var PlikWejsciowy, PlikWyjsciowy : TextFile;
var TekstZPliku, WczytanyTekst, TekstPoZmianach : string;
var czas1, czas2 : Int64;
begin
  czas1 := GetMsCount;
  Zamien_BitBtn.Enabled := false;
  Application.ProcessMessages;
  Screen.Cursor := crHourGlass;
  Application.ProcessMessages;
  TekstPoZmianach:='';
  TekstZPliku := '';
  if ((PlikWejsciowy_Edit.Text <> '') and (PlikWyjsciowy_Edit.Text <> ''))  then
  begin
          AssignFile(PlikWejsciowy, PlikWejsciowy_Edit.Text);
          Reset(PlikWejsciowy);
          while not (EOF(PlikWejsciowy)) do
          begin
               ReadLn(PlikWejsciowy, WczytanyTekst);
               TekstZPliku := TekstZPliku + WczytanyTekst + #13+#10;
          end;
          CloseFile(PlikWejsciowy);
          TekstPoZmianach := StringReplace(TekstZPliku, ZnakDoZnalezienia1_Edit.Text, ZnakDoZamiany1_Edit.Text, [rfReplaceAll]);
          TekstPoZmianach := StringReplace(TekstPoZmianach, ZnakDoZnalezienia2_Edit.Text, ZnakDoZamiany2_Edit.Text, [rfReplaceAll]);
  end;

  AssignFile(PlikWyjsciowy, PlikWyjsciowy_Edit.Text);
  Rewrite(PlikWyjsciowy);
  Write(PlikWyjsciowy, TekstPoZmianach);
  Flush(PlikWyjsciowy);
  CloseFile(PlikWyjsciowy);
  Zamien_BitBtn.Enabled := true;
  Application.ProcessMessages;
  Screen.Cursor := crDefault;
  Application.ProcessMessages;
  czas2 := GetMsCount;
  ShowMessage('Zamiany dokonano w czasie : ' + IntToStr(czas2-czas1) + ' ms'); 

Kod java :

Kopiuj
/**
 * Funkcja zamieniająca podany łańcuch znaków na inny
 * @param builder łańcuch (ciąg) znaków, w którym będzie zamiana
 * @param from łańcuch (ciąg) znaków, który jest poszukiwany do zamiany
 * @param to łańcuch (ciąg) znaków, na który ma być zamieniony
 */
public static void replaceAll(StringBuilder builder, String from, String to)
{
    int index = builder.indexOf(from);
    while (index != -1)
    {
        builder.replace(index, index + from.length(), to);
        index += to.length(); // Move to the end of the replacement
        index = builder.indexOf(from, index);
    }

public class ZamianaTekstu_Watek extends Thread {
    public void run() {
        // Spradzamy czy wprowadzono ścieżkę i nazwę pliku
        // Jeśli nie to jest wyświetlany komunikat
        if ((PlikWejsciowy_jTextField.getText().equals("") == true) || (PlikWyjsciowy_jTextField.getText().equals("") == true))
        {
            JOptionPane.showMessageDialog(null, "Proszę wybrać plik wejściowy i wyjściowy! ", "Ostrzeżenie", JOptionPane.WARNING_MESSAGE);           
        } // jeśli wprowadzonn nazwy plików
        else
        {
        // ustaw klepsydrę jako kursor
        Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR);
        setCursor(hourglassCursor);
        // odśmiecamy pamieć tj. wymuszenie uruchomienia Garbage Collectora
          System.gc();
          long start,koniec,czas;
           start = java.lang.System.currentTimeMillis(); // bieżący czas w ms

        {
         try
             {
              // otwieramy plik - nazwa pliku jest już w kontrolce GUI TextField
             File file = new File(PlikWejsciowy_jTextField.getText());
             // przygytowanie do odczytu
             BufferedReader reader = new BufferedReader(new FileReader(file));
             String line = "";
             String oldtext = "";
             // w pętli odczytujemy linijka po linijce do końca pliku
             while((line = reader.readLine()) != null)
                 {
                 oldtext += line + "\r\n";
             }
             reader.close(); // zamykamy strumień
             // w celu szybszego działania zamianu używamk klasy StringBuilder
            StringBuilder sb_oldtext = new StringBuilder(oldtext); 
            // zamiana (funkcja do operacji na StringBuilder)
            replaceAll(sb_oldtext, ZnakiDoZnalezienia1_jTextField.getText(), ZnakiDoZamiany1_jTextField.getText()); 
            replaceAll(sb_oldtext,ZnakiDoZnalezienia2_jTextField.getText(), ZnakiDoZamiany2_jTextField.getText());  
            // zapis do pliku 
            FileWriter writer = new FileWriter(PlikWyjsciowy_jTextField.getText());
            writer.write(sb_oldtext.toString());
            // zapizs bufor
            writer.flush();
            // zamknięcie uchwytu pliku
            writer.close();

         }
         catch (IOException ioe)
             {
              JOptionPane.showMessageDialog(null, ioe.toString(), "Błąd", JOptionPane.ERROR_MESSAGE);

         }
     }
        // przywracamy kursor
        Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
        setCursor(normalCursor);
        koniec = java.lang.System.currentTimeMillis(); // bieżący czas w ms
        czas = koniec - start;//czas działań w ms
        double czas_w_sekundach = czas / 1000;
        double czas_w_minutach = czas_w_sekundach / 60;
             JOptionPane.showMessageDialog(null, "Dokonano zamiany w czasie  " + String.format("%.0f", czas_w_sekundach)                  
                + " sekund" + "( "+ Double.toString(czas_w_minutach) + " minut)" , "Komunikat", JOptionPane.INFORMATION_MESSAGE);
        // zamknięcie okna dialogowego z komunikatem o oczekiwaniu i animacją
        // wcześniej okno zostało pokazane przed wejściem w ten wątek
        OknoOczekiwaniaDialog.setVisible(false);
        }
 
1

Ten fragment jest wyjątkowo źle napisany

Kopiuj
             String oldtext = "";
             // w pętli odczytujemy linijka po linijce do końca pliku
             while((line = reader.readLine()) != null)
                 {
                 oldtext += line + "\r\n";
             }

Zmienna oldtext winna być typu StringBuilder lub StringBuffer.

Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:19 minut
0
  1. Użyj String.replaceAll() zamiast tej swojej funkcji replaceAll()
  2. W pętli while dalej używasz konkatenacji Stringów zamiast StringBuildera.
  3. Po co w ogóle ładować wszystko naraz, skoro można odczytywać te linie pojedynczo, modyfikować i od razu zapisywać?

"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
02
3. może chce mieć możliwość replace'a znaków nowych lini (i to co po nich nastąpi)
Wibowit
No w sumie tak, brałem to przez chwilę pod uwagę, ale wydawało mi się to zbyt dziwne :]
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

String.ReplaceAll działa w przypadku tylko stringa, nie działa w przypadku StringBuffer lub StringBuilder... Tzn, nie ma takiego samego zaczenia co String.ReplaceAll... Stąd ten własny kod.
Hmm jak chce zmienic na :

Kopiuj
             StringBuilder line = "";
             StringBuilder oldtext = "";
             // w pętli odczytujemy linijka po linijce do końca pliku
             while((line = reader.readLine()) != null)
                 {
                 oldtext += line + "\r\n";
             }

to kompilator rzuca błedy niezgodnosci typow.... :/

Niemniej moim skromnym zdaniem ObjectPascal jakiś bardziej przejrzysty mi się wydaje i bardziej "humanistyczny" niż Java...

edytowany 1x, ostatnio: LOSMARCELOS
0

Przy takiej znajomości i rozumieniu Javy nie powinieneś się wypowiadać na jej temat.

Kopiuj
             String line = "";
             StringBuilder oldtext = new StringBuilder("");
             // w pętli odczytujemy linijka po linijce do końca pliku
             while((line = reader.readLine()) != null)
                 {
                 oldtext.append(line + "\r\n");
             }
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0
bo napisał(a)

Przy takiej znajomości i rozumieniu Javy nie powinieneś się wypowiadać na jej temat.

Kopiuj
             String line = "";
             StringBuilder oldtext = new StringBuilder("");
             // w pętli odczytujemy linijka po linijce do końca pliku
             while((line = reader.readLine()) != null)
                 {
                 oldtext.append(line + "\r\n");
             }

Aaaa.. dzieki :)

Po zmianach znów zrobie porównianie...
Zmieniłem kod... No teraz po kilku próbach program w Javie okazał... się minimalnie szybszy niż ten skompilowany w FPC :)
Czyli przekonałem się na własnej skórze, ile zależy od umiejętności wykorzystania języka...
:)
Będę mieć chwilę czasu przepisze kod na C/C++

edytowany 2x, ostatnio: LOSMARCELOS
0

Na mojej maszynie stosunek czasów wykonania poniższych funkcji

Kopiuj
    String s="A";
    int ile=100000;
    String powiel1(String s,int ile)
    {
        String zwrot="";
        for (int i=1;i<=ile;i++)
        {
            zwrot+=s;
        }
        return zwrot;
    }
    String powiel2(String s,int ile)
    {
        StringBuffer zwrot=new StringBuffer("");
        for (int i=1;i<=ile;i++)
        {
            zwrot.append(s);
        }
        return new String(zwrot);
    }

wynosi około 7000.

LO
O kurcze... nie sądziłem, że to aż tak duża różnica będzie.... Ciekawe jak C# i C++ są szybkie w porównaniu do Javy i FPC na tym przykładzie... Zgodnie ze stereotypem C++ powinien być najszybszy.
msm
Administrator
  • Rejestracja:około 16 lat
  • Ostatnio:5 miesięcy
0

Na mojej maszynie stosunek czasów wykonania poniższych funkcji
...
wynosi około 7000.

Nikt nie powiedział więc może dopowiem żeby nikt nie wyciągnął błędnych wniosków. Ta różnica wynika nie z tego że konkatenacja stringów w Javie jest taka wolna, ale z ich niezmienności.
To znaczy że 100000 wywołanie str += "a"; Powoduje utworzenie 100000 instancji Stringa. Inaczej mówiąc, w pamięci będą siedziały napisy "a", "aa", "aaa", "aaaa" i tak aż do "a" * 100000 z czego używany będzie tylko ten ostatni.

edytowany 1x, ostatnio: msm
bogdans
Moim zdaniem, to że siedzą w pamięci napisy "A", "AA",.. jest mało istotne (może zresztą nie siedzą bo zajął się nimi GC). Istotne jest to, że każda kolejna konkatenacja wymaga skopiowania całego napisu w nowe miejsce. W podanym przykładzie kopiowany napis ma kilkadziesiąt tysięcy bajtów.
msm
Racja, ale chciałem tylko zobrazować to co się dzieje, to że je trzeba kopiować tłumaczy się chyba samo przez się.
02
nie zdziwiłbym się, jakby konkatenacja stringów była ładnie zoptymalizowana w JVM. Gdzieś nawet czytałem, że obecnie nawet nie warto używać StringBuilderów bo to utrudnia optymalizację, ale to było daaawno temu jak jeszcze klepałem w Javie ;)
bogdans
A ja bym się zdziwił, wspomniany program skompilowałem na nowo i jeszcze raz uruchomiłem. Java 1.7, ten sam stosunek czasów.
msm
W tym przypadku teoretycznie możliwa jest optymalizacja, ale co gdyby 'zwrot' była polem w klasie a program był wielowątkowy?
Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:19 minut
0

String.ReplaceAll działa w przypadku tylko stringa, nie działa w przypadku StringBuffer lub StringBuilder... Tzn, nie ma takiego samego zaczenia co String.ReplaceAll... Stąd ten własny kod.

To jakie ma znaczenie? Jedyna różnica to taka, że String.replaceAll() traktuje parametry jako regexy, ale przecież możesz sobie wyescapować znaki kontrolne.

Kopiuj
public class Main {

    public static void replaceAll(StringBuilder builder, String from, String to) {
        int index = builder.indexOf(from);
        while (index != -1) {
            builder.replace(index, index + from.length(), to);
            index += to.length(); // Move to the end of the replacement
            index = builder.indexOf(from, index);
        }
    }

    void run() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 123456; i++) {
            sb.append(i);
        }
        long time1 = System.currentTimeMillis();
        String wynik1 = sb.toString().replaceAll("1", "2").substring(5, 15);
        System.out.printf("Czas: %8d " + wynik1 + "\n", System.currentTimeMillis() - time1);
        long time2 = System.currentTimeMillis();
        replaceAll(sb, "1", "2");
        String wynik2 = sb.toString().substring(5, 15);
        System.out.printf("Czas: %8d " + wynik2 + "\n", System.currentTimeMillis() - time2);
    }

    public static void main(String[] args) {
        new Main().run();
    }
}

Daje taki wynik:

Kopiuj
run:
Czas:       65 5678920222
Czas:    21021 5678920222
BUILD SUCCESSFUL (total time: 22 seconds)

Format wyniku: Czas w milisekundach + wycinek z wynikowego Stringa.

Wynikowy String jest taki sam, niestety twój kod się kwadraci. Dla 10x większego Stringa długość wykonania twojej procedury replaceAll rośnie 100x. String.replaceAll() jest za to liniowy.

Wniosek: w zależności od długości plików wejściowych twój program można przyspieszyć od kilkudziesięciu razy do kilkuset milionów razy.


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

Zainstalowałem Jave 1.7 SDK i najnowszego NetBeansa i przerobiłem projekt wg wskazówek...

Kopiuj
 
public class ZamianaTekstu_Watek extends Thread {
    public void run() {
        // Spradzamy czy wprowadzono ścieżkę i nazwę pliku
        // Jeśli nie to jest wyświetlany komunikat

        if ((PlikWejsciowy_jTextField.getText().equals("") == true) || (PlikWyjsciowy_jTextField.getText().equals("") == true))
        {
            JOptionPane.showMessageDialog(null, "Proszę wybrać plik wejściowy i wyjściowy! ", "Ostrzeżenie", JOptionPane.WARNING_MESSAGE);           
        } // jeśli wprowadzono nazwy plików
        else
        {
        // ustaw klepsydrę jako kursor
        Cursor hourglassCursor = new Cursor(Cursor.WAIT_CURSOR);
        setCursor(hourglassCursor);
        // odśmiecamy pamieć tj. wymuszenie uruchomienia Garbage Collectora
          System.gc();
          long start,koniec,czas;
           start = java.lang.System.currentTimeMillis(); // bieżący czas w ms

        {
         try
             {
              // otwieramy plik - nazwa pliku jest już w kontrolce GUI TextField
             File file = new File(PlikWejsciowy_jTextField.getText());
             // przygytowanie do odczytu
             BufferedReader reader = new BufferedReader(new FileReader(file));
             String line = "";
             StringBuilder oldtext = new StringBuilder("");
             String TekstPoZmianach = "";
             // w pętli odczytujemy linijka po linijce do końca pliku
             while((line = reader.readLine()) != null)
                 {
                 line = line + "\r\n";
                 oldtext.append(line);
             }
             reader.close(); // zamykamy strumień
             // w celu szybszego działania zamiany używamy klasy StringBuilder
            StringBuilder sb_oldtext = new StringBuilder(oldtext); 
            // zamiana (funkcja do operacji na StringBuilder)
            TekstPoZmianach = sb_oldtext.toString().replace(ZnakiDoZnalezienia1_jTextField.getText(), ZnakiDoZamiany1_jTextField.getText());
            // dodatkowy obiekt typu StringBuilder w którym przechowujemy tekst po pierwszej zamianie
            StringBuilder sb_oldtext2 = new StringBuilder(TekstPoZmianach);
            // kolejna zamiana tekstu... 
            TekstPoZmianach = sb_oldtext2.toString().replace(ZnakiDoZnalezienia2_jTextField.getText(), ZnakiDoZamiany2_jTextField.getText());
            // zapis do pliku 
            FileWriter writer = new FileWriter(PlikWyjsciowy_jTextField.getText());
            //writer.write(sb_oldtext.toString());
            writer.write(TekstPoZmianach);
            // zapisz bufor
            writer.flush();
            // zamknięcie uchwytu pliku
            writer.close();

         }
         catch (IOException ioe)
             {
              JOptionPane.showMessageDialog(null, ioe.toString(), "Błąd", JOptionPane.ERROR_MESSAGE);

         }
     }
        // przywracamy kursor
        Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
        setCursor(normalCursor);
        koniec = java.lang.System.currentTimeMillis(); // bieżący czas w ms
        czas = koniec - start;//czas działań w ms
        double czas_w_sekundach = czas / 1000;
        double czas_w_minutach = czas_w_sekundach / 60;
             JOptionPane.showMessageDialog(null, "Dokonano zamiany w czasie  " + String.format("%.0f", czas_w_sekundach)                  
                + " sekund" + "( "+ Double.toString(czas_w_minutach) + " minut)" , "Komunikat", JOptionPane.INFORMATION_MESSAGE);
             System.gc();
        // zamknięcie okna dialogowego z komunikatem o oczekiwaniu i animacją
        // wcześniej okno zostało pokazane przed wejściem w ten wątek
        OknoOczekiwaniaDialog.setVisible(false);
        }


    }
}

Efekt jest taki, że plik 1 mb w programie skompilowany w Lazarusie (FPC) przetwarza się ok 5 minut, a w Javie 1 sekunde...
Ciekawe czy kod Pascala da się jakoś zoptymalizować....
Będę mięć czas to przepisze kod na C++ i C# (swoją drogą ciekawe czy będzie mieć znaczenie czy użyje w przypadku C++ biblioteki QT albo wxWidgets, skoro kompilator jest ten sam - MinGW).

Wibowit
  • Rejestracja:około 20 lat
  • Ostatnio:19 minut
0

Wszystko da się zoptymalizować. Kod w FPC nie powinien być dużo wolniejszy od Javowego, na pewno jeżeli jest więcej niż kilka razy wolniejszy to jest to wina kiepsko napisanego kodu. Podobnie jeżeli kod Javowy jest wolniejszy od C++owego więcej niż kilka razy to też zwykle jest to wina kiepsko napisanego kodu (rzadziej: innymi czynnikami, typu przebijanie się przez JNI czy JNA, lub niska ilość RAMu).


"Programs must be written for people to read, and only incidentally for machines to execute." - Abelson & Sussman, SICP, preface to the first edition
"Ci, co najbardziej pragną planować życie społeczne, gdyby im na to pozwolić, staliby się w najwyższym stopniu niebezpieczni i nietolerancyjni wobec planów życiowych innych ludzi. Często, tchnącego dobrocią i oddanego jakiejś sprawie idealistę, dzieli od fanatyka tylko mały krok."
Demokracja jest fajna, dopóki wygrywa twoja ulubiona partia.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0
Wibowit napisał(a)

Wszystko da się zoptymalizować. Kod w FPC nie powinien być dużo wolniejszy od Javowego, na pewno jeżeli jest więcej niż kilka razy wolniejszy to jest to wina kiepsko napisanego kodu. Podobnie jeżeli kod Javowy jest wolniejszy od C++owego więcej niż kilka razy to też zwykle jest to wina kiepsko napisanego kodu (rzadziej: innymi czynnikami, typu przebijanie się przez JNI czy JNA, lub niska ilość RAMu).

Czyli tak na prawdę to wiele jest stereotypów typu, że programy w C++ z reguły są szybsze niż pisane w Javie albo C# ?
Kiedyś nawet uruchamiałem Quake2, który został napisany w Javie (przepisany z C++) i działał tak samo szybko jak ten w C++. Jednak javowa wersja Quake2 była uruchomiona na współczesnym (w miarę) procesorze, bo dwurdzeniowym itp.
Podejrzewam, że Quake 2 w wersji napisanej w Javie uruchomiony na komputerze z epoki kiedy się ta gra była nowością to, była by wolniejsza niż ta napisana w C++ ale przy obecnych sprzętach różnica szybkości między Java a C++ się zaciera...
Tutaj link do Quake 2 w Javie (za free wersja demo)
http://www.bytonic.de/html/jake2.html

edytowany 2x, ostatnio: LOSMARCELOS
Zobacz pozostałe 5 komentarzy
Wibowit
Na pewno wolniej, chociażby z tego względu, że Java nie jest dobrze zintegrowana ze sterownikami 3D (czy to DirectX czy OpenGL). Poza tym sposób współpracy z bibliotekami natywnymi wymusza pewien sposób pisania kodu, przez co wygoda pisania generalnie wcale nie musi być dużo większa niż przy pisaniu bezpośrednio w C++ (oczywiście mówię o jakiejś w miarę nowej implementacji C++ oraz dostępie do bibliotek czy frameworków typu Boost, Bullet, itp ułatwiających tworzenie gier). OpenGL czy DirectX nie wspierają odśmiecania pamięci, więc trzeba martwić się dealokacją, jak w C++.
LO
Czyli tak w skrócie- Java jak najbardziej do aplikacji bazodanowych, programów sieciowych, aplety, programy obliczeniowe, finansowe, jakieś narzędziowe, gry 2D i prostsze 3D, a C++ nadal do zaawansowanej grafiki, multimediów, oprogramowania systemowego, narzędziowego..
Wibowit
Narzędziowe masz w obydwu kategoriach :P W zasadzie jak na chwilę obecną nikt w Javie wielkich gier 3D nie robi, bo to nie ma sensu, zwłaszcza po wyjściu C++11 oraz ze względu na to, że w Javie jest mało frameworków do pisania gier, w przeciwieństwie do C++. Programy do obróbki multimediów (które przecież nie wymagają jakiegoś super czasu reakcji, jak w Counter-Strike) można by generalnie stworzyć w Javie, z użyciem np OpenCL. Java jak na razie ma brak typów unsigned, przy obróbce surowych danych to czasem przeszkadza.
LO
Tzn. narzędziowe w C/C++ takie typowo powiązane z systemem, np. oprogramowanie do audytu odczytujące jakie są zasoby sprzętowe, oprogramowanie itp.
Wibowit
Jeśli większość funkcjonalności programu nie jest przenośna to jest to argument za tym, aby nie pisać go w Javie. Do zabawy z bebechami systemu, C++ na chwilę obecną bardzo dobrze się nadaje.
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

Czyli tak na prawdę to wiele jest stereotypów typu, że programy w C++ z reguły są szybsze niż pisane w Javie albo C# ?

To nie jest kwestia języka, tylko kompilatora (i w przypadku C# i Javy - maszyny wirtualnej). Jednym z założeń C++ jest, że ma być szybki: i na to nakłada się największy nacisk w pisaniu kompilatorów. Ale Jak tu niedawno ze zdziwieniem ktoś zauważył, nowe wersje Delphi są zadziwiająco szybkie...

za to FreePascala (Lazarusa) uważam za raczej powolnego, przy tym samym kodzie co w Delphi - sromotnie przegrywa.

edytowany 1x, ostatnio: Azarien
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

Przepisałem kod na C++ (skompilowany przy użyciu MS Visual C++ 2010 Express) jako aplikacja konsolowa.
Wynik dla Java przy 1 mb pliku - 1 sekunda, dla C++ 9 sekund (ten sam plik)
Kod w C++

Kopiuj
 
#include "stdafx.h"


using namespace std;




int _tmain(int argc, _TCHAR* argv[])
{
	   int liczba_zamian = 0;

	int czas1, czas2;
    czas1=clock();  // za czas1 zostanie wstawiony czas w milisekundach od momentu wlaczenia programu
    string wczytany_tekst2 = "";
    string line;
  ifstream myfile ("test1.txt", ifstream::in);
  if (myfile.is_open())
  {
	  cout << "Otworzono plik! ";
	  cout << endl;
    while ( myfile.good() )
    {
      getline (myfile,line);
	  //wczytany_tekst2.append(wczytany_tekst2);
      wczytany_tekst2.append(line);
	  wczytany_tekst2.append("\r\n");
    }
    myfile.close();
	cout << "Wczytano plik !" << endl;
  }
 
size_t j;
string find = "[";
string replace = "{";
cout << "Dokonywanie zamiany... ";
for ( ; (j = wczytany_tekst2.find( find )) != string::npos ; ) {
wczytany_tekst2.replace( j, find.length(), replace );
}
find = "]";
replace = "}";
for ( ; (j = wczytany_tekst2.find( find )) != string::npos ; ) {
wczytany_tekst2.replace( j, find.length(), replace );
}
cout << "OK!" << endl;
cout << "Zapis do pliku... " ;
ofstream myfile2 ("test1.txt");
  if (myfile2.is_open())
  {
    myfile2 << wczytany_tekst2;
    myfile2.close();
  }
cout << "OK!" << endl;

    czas2=clock();
    czas2=czas2-czas1;
   cout << "Czas zamiany wynosi : " << czas2 << " ms (" << czas2/1000 << " sekund)";

   system ("pause");
  

	return 0;
}

Korzystając z biblioteki wxWidgets + kompilator MingGW 3.4.5 (wxDevCpp) to czas zamiany wynosił 19 sekund... (metoda Replace klasy wxString).

Pytanie jest o samo wyszukiwanie i zamianę stringów... bo ten algorytm jest powolny...

edytowany 1x, ostatnio: LOSMARCELOS
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:3 minuty
0

Przepisałem kod na C++
ten kod to taki trochę WTF-owy był, porównaj czas z tym:

Kopiuj
#include <iostream> 
#include <fstream>
#include <ctime>
#include <string>
using namespace std;

int main(int argc, char argv[])
{
	clock_t timeStart, timeTotal;
	timeStart=clock();
	ifstream inputFile("test1.txt", ios::in);
	ofstream outputFile("test2.txt", ios::out);
	if (!inputFile || !outputFile)
	{
		cout << "Kupa."<<endl;
		exit(1);
	}
	string line;
	while (getline(inputFile,line))
	{
		int len = line.length();
		for (int i=0; i<len; i++)
		{
			if (line[i]=='[')
				line[i]='{';
			else if (line[i]==']')
				line[i]='}';
		}
		outputFile << line << '\n';
	}
	inputFile.close();
	outputFile.close();
	timeTotal=clock()-timeStart;
	cout << "Czas zamiany wynosi : " << timeTotal << " ms (" << timeTotal/1000 << " sekund)";
	system ("pause");
	return 0;
}

EDIT: a jeżeli mamy wyszukiwać całe stringi to i tak nie trzeba "appendować" całego pliku do jednego długiego stringa, można czytać i zapisywać linia po linii. to się tyczy każdego języka.

edytowany 3x, ostatnio: Azarien
bogdans
Pod warunkiem, że szukany String nie jest rozdzielony między kilka linii.
LO
  • Rejestracja:prawie 20 lat
  • Ostatnio:ponad 4 lata
0

No działa zdecydowanie szybciej. Tylko czy da się tak zrobić, żeby zmieniać nie tylko pojedynczy znak, ale np. kilka znaków zastąpić innymi? A może linijka po linijce wyszukiwać i wtedy korzystać z funkcji dostępnej w danym frameworku, niż w całym ogromnym stringu?

paulus
  • Rejestracja:prawie 21 lat
  • Ostatnio:ponad 11 lat
  • Postów:57
0

Proszę użyć funkcji StrReplaceCS z biblioteki JEDI pobrany z http://www.koders.com/delphi/fidCFF482EC7371D43AAF1241D90C486EDE5F0F568A.aspx

Kopiuj
procedure StrReplaceCS(var S: AnsiString; const Search, Replace: AnsiString; Flags: TReplaceFlags);
var
  ResultStr: string;     { result string }
  SourcePtr: PChar;      { pointer into S of character under examination }
  SourceMatchPtr: PChar; { pointers into S and Search when first character has }
  SearchMatchPtr: PChar; { been matched and we're probing for a complete match }
  ResultPtr: PChar;      { pointer into Result of character being written }
  SearchLength,          { length of search string }
  ReplaceLength,         { length of replace string }
  ResultLength: Integer; { length of result string (maximum, worst-case scenario) }
  C: Char;               { first character of search string }
begin
  //if (S = '') or (Search = '') then Exit;
  { avoid having to call Length() within the loop }
  SearchLength := Length(Search);
  ReplaceLength := Length(Replace);
  { initialize result string to maximum (worst case scenario) length }
  if Length(Search) >= ReplaceLength then
    ResultLength := Length(S)
  else
    ResultLength := ((Length(S) div Length(Search)) + 1) * Length(Replace);
  SetLength(ResultStr, ResultLength);
  { get pointers to begin of source and result }
  ResultPtr := PChar(ResultStr);
  SourcePtr := PChar(S);
  C := Search[1];
  { while we haven't reached the end of the string }
  while True do
  begin
    { copy characters until we find the first character of the search string }
    while (SourcePtr^ <> C) and (SourcePtr^ <> #0) do
    begin
      ResultPtr^ := SourcePtr^;
      Inc(ResultPtr);
      Inc(SourcePtr);
    end;
    { did we find that first character or did we hit the end of the string? }
    if SourcePtr^ = #0 then
      Break
    else
    begin
      { continue comparing, +1 because first character was matched already }
      SourceMatchPtr := SourcePtr + 1;
      SearchMatchPtr := PChar(Search) + 1;
      while (SourceMatchPtr^ = SearchMatchPtr^) and (SearchMatchPtr^ <> #0) do
      begin
        Inc(SourceMatchPtr);
        Inc(SearchMatchPtr);
      end;
      { did we find a complete match? }
      if SearchMatchPtr^ = #0 then
      begin
        { append replace to result and move past the search string in source }
        Move((@Replace[1])^, ResultPtr^, ReplaceLength);
        Inc(SourcePtr, SearchLength);
        Inc(ResultPtr, ReplaceLength);
        { replace all instances or just one? }
        if not (rfReplaceAll in Flags) then
        begin
          { just one, copy until end of source and break out of loop }
          while SourcePtr^ <> #0 do
          begin
            ResultPtr^ := SourcePtr^;
            Inc(ResultPtr);
            Inc(SourcePtr);
          end;
          Break;
        end;
      end
      else
      begin
        { copy current character and start over with the next }
        ResultPtr^ := SourcePtr^;
        Inc(ResultPtr);
        Inc(SourcePtr);
      end;
    end;
  end;
  { append null terminator, copy into S and reset the string length }
  ResultPtr^ := #0;
  S := ResultStr;
  SetLength(S, StrLen(PChar(S)));
end;
 

Proszę podać czas operacji zamiany po zmianie funkcji.


--------------------------------------
E-Net czyli Edytor HTML, JavaScript, PHP
oraz dołączony parser PHP i serwer Apache
http://edytor.wri.pl

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.