Wie heißt der Nachfolger ...



  • Naja! ...wenn ich j bis 400000 statt bis 200000 laufen lasse, dann steigt die Zeit bei beiden Programmen linear an. Bis wo soll ich j denn laufen lassen, damit du davon überzeugt bist, dass der GC sehr aktiv gewesen sein muss?

    ...im Übrigen stimme ich nicht damit überein, dass der GC insgesamt mehr Zeit brauchen muss. Er kann alle Objekte auf einmal behandeln. Sowas kann von vorteil sein. Außerdem defragmentiert der GC nicht. Der Speicher wird einfach nicht fragmentiert. Der GC muss also garnicht defragmentieren.



  • 136055, also 2:16 min. Der Flaschenhals liegt irgendwo anders.

    mit eigenem op new/delete:
    5748

    uih, was hätte ich viel rausholen können, wenn ich damals den messages noch nen richtigen allocator verpaßt hätte. so hab ich nur in die doku geschrieben, daß meine nachfolger das mal machen sollten, die habens aber sicherlich nicht getan.

    also sowas darf man mit ungetuntem c++ ja gar nicht machen. und ich hatte immer angenommen, der msvc würde bereits für kleine objekte sonderbehandlungen machen.

    also ich gebe zu, daß der user bei java mit dem gc keinen bedarf hat, sich irgendwelche gedanken zu machen, obs schneller ginge, man nimmt die standard-sachen und hat bereits was sehr sehr gutes.

    in c++ ohne gc kann man schneller sein, aber zu vielfachem programmieraufwand. den irgendjemand mal macht, und man inkludiert dann das zeugs. ich vermute jetzt, daß es nicht wirklich am gc liegt, sondern daß java nen small object allocator hat, der immer gleich nen batzen auf einmal vom bs holt (4096 bytes wäre wohl klug, weils eine speicherseite ist), und dann da die neu zu erzeugenden objekte einfach reinsetzt wie in ein array. das sollte eigentlich völlig ausreichen, um die hier sichtbare performance zu bringen.

    @hume: dein loki-port ist so vollständig, daß der small object allocator klappt?



  • Original erstellt von volkard:
    ich vermute jetzt, daß es nicht wirklich am gc liegt, sondern daß java nen small object allocator hat, der immer gleich nen batzen auf einmal vom bs holt (4096 bytes wäre wohl klug, weils eine speicherseite ist), und dann da die neu zu erzeugenden objekte einfach reinsetzt wie in ein array.

    Ich weiß nicht genau, wie Java das macht. Aber zumindest gibt Java Speicher, den es einmal hat, nicht mehr so schnell an das Betriebssystem zurück. Der Speicher wird dann wohl nur Java-intern frei gemacht. ...und unter Umständen irgendwann wieder belegt. Vielleicht reicht das schon aus.



  • @hume: dein loki-port ist so vollständig, daß der small object allocator klappt?

    Jo. Der sollte problemlos funktionieren. Nur haben mir mittlerweile einige Experten mitgeteilt, dass der Allokator nicht so toll sein soll, wie man sich das wünscht. Ich habe das irgendwann auch mal getestet, kann mich aber nicht mehr wirklich an das Ergebnis erinnern. Vom Hocker gehauen hat's mich aber auf jeden Fall nicht.

    Man müsste mal schauen, wie schnell die Boost pool-Allokatoren sind.

    [ Dieser Beitrag wurde am 27.11.2002 um 01:48 Uhr von HumeSikkins editiert. ]



  • Original erstellt von Gregor:
    Bis wo soll ich j denn laufen lassen, damit du davon überzeugt bist, dass der GC sehr aktiv gewesen sein muss?

    Er wurde aktiv, keine Frage! Wäre er nicht aktiv geworden, wärste voll in den Speicherflaschenhals gerannt. Mag sein, daß er weiß, wie groß der Cache ist, und bei new aufgerufen wird, wenn der Cache voll ist, damit top performance bei solchen Anwendungen garantiert ist. Ich traue da Deinem GC inzwischen viele tolle Tricks zu.

    ...im Übrigen stimme ich nicht damit überein, dass der GC insgesamt mehr Zeit brauchen muss. Er kann alle Objekte auf einmal behandeln. Sowas kann von vorteil sein.

    Kann sein, weil die Schleifen schneller brummen, wenn sie nicht auch noch mit Anwendungscode durchsetzt sind. Und kann auf jeden Fall sein, wenns ein anderer Thread auf nem anderen Prozessor macht. Kann aber auch sein, daß bei sofortigem Löschen mehr Cache-Treffer passieren.

    Außerdem defragmentiert der GC nicht. Der Speicher wird einfach nicht fragmentiert. Der GC muss also garnicht defragmentieren.

    Für Top-Speed in dieser Anwendung muß ich erst nen small object allocator besorgen. Kann aber sein, daß ich erst einen selber bauen will, was dann bestimmt bis ins neue Jahr dauert. Ich melde mich auf jeden Fall wieder.

    Und dann wärs spannend, ne Anwendung zu bauen, die drauf ausgelegt ist, den Speicher gnadenlos zu fragmentieren, und mal zu gucken. Das könte dann den Beweis erbringen, daß es Anwendungen gibt, die nen echten GC wie in Java benötigen.



  • Original erstellt von volkard:
    **
    also ich gebe zu, daß der user bei java mit dem gc keinen bedarf hat, sich irgendwelche gedanken zu machen, obs schneller ginge, man nimmt die standard-sachen und hat bereits was sehr sehr gutes.
    **

    Bei anderen Dingen, die man programmiert ist es genau andersherum. Da ist man dann mit Java viel langsamer als mit C++, kann Java aber mit entsprechenden Optimierungen prozentual besser beschleunigen, als C++.

    Es wundert mich, dass folgender Hauptnachteil eines GC noch nicht genannt wurde:

    Wenn man einen GC hat, dann ist das Programm in dre Regel nicht echtzeitfähig, da der GC letztendlich jederzeit aktiv werden kann und so eine große Pause produzieren kann. Man kann sich zwar bemühen, den GC in Programmteilen aufzurufen, in denen man keine Performance braucht, IMHO kann man aber nicht 100%ig festlegen, dass der GC nicht irgendwann an einer Stelle aktiv wird, an der er nicht aktiv werden soll.



  • Original erstellt von volkard:
    **
    Für Top-Speed in dieser Anwendung muß ich erst nen small object allocator besorgen. Kann aber sein, daß ich erst einen selber bauen will, was dann bestimmt bis ins neue Jahr dauert. Ich melde mich auf jeden Fall wieder.

    Und dann wärs spannend, ne Anwendung zu bauen, die drauf ausgelegt ist, den Speicher gnadenlos zu fragmentieren, und mal zu gucken. Das könte dann den Beweis erbringen, daß es Anwendungen gibt, die nen echten GC wie in Java benötigen.**

    Da bin ich mal gespannt! 🙂



  • Ist es in Java auch möglich den GC abzustellen und sich selbst um die Speicherfreigabe zu kümmern?



  • Original erstellt von <Selbst ist der Mann>:
    Ist es in Java auch möglich den GC abzustellen und sich selbst um die Speicherfreigabe zu kümmern?

    Nein! ...da mußt du wohl D nehmen! 🙂 ...bei Java kannst du aber zwischen verschiedenen GCs umschalten. Es gibt da verschiedene Taktiken, sowas zu implementieren. Habe ich aber noch nicht gemacht und ich kenne die Möglichkeiten auch nicht genau. Es soll z.B. nen GC geben, der sehr gut auf Multiprozessorsysteme ausgerichtet ist.

    [ Dieser Beitrag wurde am 27.11.2002 um 02:06 Uhr von Gregor editiert. ]



  • Das ist ja wirklich schade, das man nicht selbst Hand anlegen darf. 😡
    Na ja, aber dann nehm ich doch lieber C anstatt D. 😃 😃



  • 11 sekunden

    #include <iostream>
    #include <stdlib.h>
    #include <ctime>
    #include <deque>
    
    std::deque<int> pool;
    
    class TestClass
    {
       private :
       int number;
    
       public :
    
       TestClass (int i)
       : number (i)
       {
       }
    
       int getNumber ()
       {
          return number;
       }
    
       void setNumber (int i)
       {
          number = i;
       }
    
       void * operator new (size_t)
       {
           pool.push_back(0);
           return &pool.back();
       }
    
       void operator delete(void * s)
       {
           if(&pool.front() == s) // ohne das brauche es 19 sek
               pool.pop_front();
           else
               for(std::deque<int>::iterator i = pool.begin(); i != pool.end(); ++i)
                       // kann man bestimt noch schneller lösen
               {
                   if(&(*i) == s)
                   {
                       pool.erase( i );
                       break;
                   }
               }
       }
    };
    
    int main(int argc, char *argv[])
    {
      int size = 500;
      long  sum = 0;
      clock_t time;
    
      TestClass ** array = new TestClass* [size];
      int i,j;
    
      time = clock();
      for (j = 0 ; j < 200000 ; ++j)
      {
        for (i = 0 ; i < size ; ++i)
        {
          array[i] = new TestClass(i);
        }
        for (int i = 0 ; i < size ; ++i)
        {
          sum += array[i]->getNumber ();
          delete array[i];
        }
      }
      delete [] array;
      std::cout << clock() - time;
    
      system("PAUSE");   
      return 0;
    }
    

    der Allocator aus Loki brachte nichts



  • for(std::deque<int>::iterator i = pool.begin(); i != pool.end(); ++i)
    

    Meinst du mit "kann man sicherlich noch schneller machen" den schleifenkopf? wenn ja, wie soll man das noch schneller machen können?



  • Übrigens : Mein Profiler hat mir eben verraten, dass beim Java-Programm etwa 10% der Zeit für den GC benötigt wird. Das Löschen der Objekte scheint also tatsächlich deutlich schneller zu gehen als das Erzeugen der Objekte.

    EDIT : @ Dimah : Ist der Rechner vergleichbar zu Volkards und meinem? 🙂 😃

    [ Dieser Beitrag wurde am 27.11.2002 um 02:36 Uhr von Gregor editiert. ]



  • Was habt ihr beiden den für Rechner? (Prozessor, Speicher)



  • Volkard : 400 MHz Celeron
    Gregor : 1,2 GHz P4M
    ...beide hierbei mehr oder weniger gleich schnell.

    [ Dieser Beitrag wurde am 27.11.2002 um 02:49 Uhr von Gregor editiert. ]



  • Hatte gerade mal Dimah's Code ausprobiert. Erst hab ich es im Debug-Modus getestet und mich gewundert, warum es garnicht fertig wurde. Das ist ja ein riesen Unterschied zwischen Release und Debug:

    Release: 4426
    Debug: 164837

    😮



  • Bei mir braucht Dimahs Code 5878ms.

    [ Dieser Beitrag wurde am 27.11.2002 um 06:59 Uhr von Gregor editiert. ]



  • Original erstellt von <codezitat>:
    Meinst du mit "kann man sicherlich noch schneller machen" den schleifenkopf? wenn ja, wie soll man das noch schneller machen können?

    ich meine das ding algemein, z.b. duch binäre suche oder so

    Original erstellt von Gregor:
    **EDIT : @ Dimah : Ist der Rechner vergleichbar zu Volkards und meinem? 🙂 😃
    **

    700 Mhz AMD und 312 MB 133 Mhz RAM (wobei ich glaube ich lasse die auf 100 laufen), aber ich hatte gestern noch edonkey an

    vielleicht sollte ich noch was zum code sagen, er ist mist, nicht thread sicher, zugeschnitten nur auf diesen einen test.
    Ich denke mit ein guten Allocator läst sich da noch was raushollen, aber auf der andern seite müsste er etwas algemeiner werden und würde da durch wieder speed verlieren



  • Original erstellt von Gregor:
    Es wundert mich, dass folgender Hauptnachteil eines GC noch nicht genannt wurde:
    Wenn man einen GC hat, dann ist das Programm in dre Regel nicht echtzeitfähig, da der GC letztendlich jederzeit aktiv werden kann und so eine große Pause produzieren kann.

    Windows kann meiner Anwendung auch jederzeit mal ein halbes Sekündchen Pause schenken. Echte Echtzeit gibts ja zum Teil nicht mehr, stattdessen "Quasi-Echtzeit", daß man bei ner Aufgabe, die sekündliche Antworten braucht ein System hinstellt, das die Anfragen "normalerweise" in 1ms beantworten kann, zwar nicht nachweilslich immer schnell genug antwortet, aber sicher genug schnell genug ist, daß man seinen Kopf dafür hinhalten kann.


Anmelden zum Antworten