Optimieren?



  • Hi,

    wie kann ich diesen code noch optimieren?

    if ((((*this).m_player.getArmor())%mod) == 0)
    	for (int i=0; i<120; ++i)
    	{
    		drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0);
    		drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0);
    	}
    	else
    	for (int i=0; i< ((*this).m_player.getArmor())%mod; ++i)
    	{
    		drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0);
    		drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0);
    	}
    


  • du könntest wenn es möglich ist die Berechnung aus der Schleifen Condition rausnehmen, da der Compiler nicht unbedingt dies automatisch machen kann!

    Optimieren lohnt sich eigentlich nur, wenn du vorher deinen Code mit einem Profiler durchgesehen hast und die Flaschenhälse ausführlich analysierst, der Rest ist Blödsinn und Zeitverschwendung (siehe 80:20-Regel)

    und lass das (*this). weg, dass macht deinen Code extrem unleserlich. Wenn du schon unbedingt explizit this schreiben willst, dann nimm doch this-> und lass das m_ weg, da dass dann wohl eh eindeutig ist 🙄



  • OC++ schrieb:

    Hi,

    wie kann ich diesen code noch optimieren?

    ich würde es selber nicht tun, aber wenn du willst:

    int armor = m_player.getArmor();
    int ii;
    int i4;
    int i;
    
    if (!(armor % mod))
    {
    	for (i = 0; i < 120; ++i) 
    	{ 
    		ii = i > 25 ? 25 :i;
    		i4 = 477 - (i*4);
    		drawLineRight (2, i4, 16, 255, ii, 0); 
    		drawLineRight (2, i4 + 1, 16, 255, ii, 0); 
    	} 
    }
    else 
    {
    	for (i = 0, len = armor % mod; i < len ; ++i) 
    	{ 
    		ii = i > 25 ? 25 :i;
    		i4 = 477 - (i*4);
    		drawLineRight (2, i4, 16, 255, ii, 0); 
    		drawLineRight (2, i4, 16, 255, ii, 0); 
    	}
    }
    

    du kannst auch über Duff's device lesen :
    http://www.cuj.com/documents/s=7990/cujcexp1910alexandr/
    http://www.lysator.liu.se/c/duffs-device.html



  • Die Frage kann man so nicht beantworten. Optimieren hinsichtlich was? Speicherbedarf? Geschwindigkeit? Wartbarkeit? ...



  • Kann mir jemand nen guten Profiler empfehlen? Ich hatte den von AMD (hab ja nen AMD Prozessor), aber der zeigte mir keine Informationen zu meinem Programm an und war somit (für mich) Nutzlos.



  • @Ichie
    dann benutzt du den wohl falsch 🙂 Ansonsten kann ich dir gprof empfehlen

    @ssm
    wenn, kannst du auch %mod rausnehmen, weil % ist ja eine relativ ``teure'' Operation



  • @kingruedi

    es ist ein Scherz?



  • ssm schrieb:

    @kingruedi

    es ist ein Scherz?

    meins? Nein oder übersehe ich wieder was

    int armor=m_player.getArmor()%mod;
    if(!armor)
      //...
    else
      for(int i=0;i<armor;++i)
        //...
    


  • ssm schrieb:

    int armor = m_player.getArmor(); 
    int ii; 
    int i4; 
    int i;
    

    falsch. die lokalen variablen ein wenig globaler machen kann selbst der dümmste optimierer. aber andersrum muß er schon klüger sein. also lass den unfug. macht den code nur gefährlich und bringt keinen speed.

    OC++ schrieb:

    wie kann ich diesen code noch optimieren?

    damit diese optimierungen was bringen, muß drawLineRight aber schweineschnell sein.

    ich kenne von der bedeutung her mod nicht. wie kingruedi ansprach, ist % die relativ teuer.

    mir scheint, leichtes umstellen in tausend schritten führt wiedermal zu einem erfolg.

    if ((((*this).m_player.getArmor())%mod) == 0) 
        for (int i=0; i<120; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
            drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
        } 
    else 
        for (int i=0; i< ((*this).m_player.getArmor())%mod; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
            drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
        }
    

    man zuerst wieder auf kingruedi hören und die sache nur lesbarer machen.

    if (m_player.getArmor()%mod == 0) 
        for (int i=0; i<120; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
            drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
        } 
    else 
        for (int i=0; i< m_player.getArmor())%mod; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
            drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
        }
    

    dann die doppelberechnung von m_player.getArmor())%mod zusammenfassen.

    int len=m_player.getArmor()%mod;
    if (len == 0) 
        for (int i=0; i<120; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
            drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
        } 
    else 
        for (int i=0; i< len; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
            drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
        }
    

    dann feststellen, daß das if eigentlich nur len auf 120 setzt, wenn len dummerweise 0 war.

    int len=m_player.getArmor()%mod;
    if(len==0)
       len=120;
    for (int i=0; i< len; ++i) 
    { 
        drawLineRight (2,477-(i*4),16, 255,(i>25 ? 25 :i),0); 
        drawLineRight (2,478-(i*4),16, 255,(i>25 ? 25 :i),0); 
    }
    

    jetzt kann man anfangen, die schleife zu betrachten.
    der fünfte parameter hat ne kappung bei 25. dann können wir die schleife auch leicht anpassen.

    int len=m_player.getArmor()%mod;
    if(len==0)
       len=120;
    for (int i=0; i< 25; ++i) 
    { 
        drawLineRight (2,477-(i*4),16, 255,i,0); 
        drawLineRight (2,478-(i*4),16, 255,i,0); 
    }
    for (int i=25; i< len; ++i) 
    { 
        drawLineRight (2,477-(i*4),16, 255,25,0); 
        drawLineRight (2,478-(i*4),16, 255,25,0); 
    }
    

    toll, gell? und nur ein wenig falsch.

    //vorschlag K
    int len=m_player.getArmor()%mod;
    if(len==0)
       len=120;
    int min_len_25=min(len,25);
    for (int i=0; i< min_len_25; ++i) 
    { 
        drawLineRight (2,477-(i*4),16, 255,i,0); 
        drawLineRight (2,478-(i*4),16, 255,i,0); 
    }
    for (int i=min_len_25; i< len; ++i) 
    { 
        drawLineRight (2,477-(i*4),16, 255,25,0); 
        drawLineRight (2,478-(i*4),16, 255,25,0); 
    }
    

    ui, da wird mir ja übel. und das liegt nicht allein an den 2l joghurt, de ich gerade aß.

    int len=m_player.getArmor()%mod;
    if(len==0)
       len=120;
    if(len<=25)
    {
        for (int i=0; i< len; ++i) 
        { 
            drawLineRight (2,477-(i*4),16, 255,i,0); 
            drawLineRight (2,478-(i*4),16, 255,i,0); 
        }
    }
    else
    {
        for (int i=0; i< 25; ++i) //S1
        { 
            drawLineRight (2,477-(i*4),16, 255,i,0); 
            drawLineRight (2,478-(i*4),16, 255,i,0); 
        }
        for (int i=min_len_25; i< len; ++i) //S2
        { 
            drawLineRight (2,477-(i*4),16, 255,25,0); 
            drawLineRight (2,478-(i*4),16, 255,25,0); 
        }
    }
    

    ja, diese richtung ist gut.
    noch 10 oder 20 umformungen, und man hat code, den man mit ein wenig toleranz stehen lassen kann.

    aber sag mal, besteht die möglichkeit, für die beiden verschiedenen schleifen (S1 und S2) zwei kleine inlinefunktionen zu machen? das könnte zu einem wiedererstehen des vorschlags K führen. der hatte eh irgendwas faszinierendes an sich.

    hab zwar keine genaue ahnung, was der code macht, aber malt der nicht zuerst ne rampe bis maximal 25 und ab dann nen balken bis zum ende?

    int endOfBar=m_player.getArmor()%mod;
    if(endOfBar==0)
       endOfBar=120;
    int endOfRamp=min(endOfBar,25);
    drawRamp(0,endOfRamp);
    drawBar(endOfRamp,endOfBar);
    

    das if gefällt mir gar nicht. aber das kriege ich ncht billig weg.

    int endOfBar=m_player.getArmor()%mod;
    if(endOfBar==0)
       endOfBar=120;
    int endOfRamp=min(endOfBar,25);
    drawRamp(0,endOfRamp);
    drawBar(endOfRamp,endOfBar);
    

    jetzt darf man sich überlegen, ob man die draw-funktionen überhaupt auf leere intervalle loslassen möchte.

    int endOfBar=m_player.getArmor()%mod;
    if(endOfBar==0)
       endOfBar=120;
    int endOfRamp=min(endOfBar,25);
    drawRamp(0,endOfRamp);
    if(endOfBar>25)
       drawBar(endOfRamp,endOfBar);
    

    oder

    void drawRamp(int left,int right)
    {
        for (int i=left; i< right; ++i)
        { 
            drawLineRight (2,477-(i*4),16, 255,i,0); 
            drawLineRight (2,478-(i*4),16, 255,i,0); 
        }
    }
    void drawBar(int left,int right)
    {
        for (int i=left; i< right; ++i)
        { 
            drawLineRight (2,477-(i*4),16, 255,25,0); 
            drawLineRight (2,478-(i*4),16, 255,25,0); 
        }
    }
    ...
    int endOfBar=m_player.getArmor()%mod;
    if(endOfBar==0)
       endOfBar=120;
    if(endOfBar<=25)
       drawRamp(0,endOfBar);
    else
    {
       drawRamp(0,25);
       drawBar(25,endOfBar);
    }
    

    jo, auf einmal mit der inlinefunktiondarf man hier wieder mehr komplexität zulassen, ohne daß einem übel wird. das ist ja ein klasse trick.

    ob der compiler klug genug ist, die berechnung aus der schleife zu holen, weiß ich nicht. ich wage es zu bezweifeln. also noch

    void drawBar(int left,int right)
    {
        int gleft=447-left*4;
        int gright=447-left*4;
        for (int i=gleft; i> gright; i-=4)
        { 
            drawLineRight (2,i,16, 255,25,0); 
            drawLineRight (2,i+1,16, 255,25,0); 
        }
    }
    

    andererseits sollte 447-left*4 auch sehr schnell gehen.

    man könnte die for-schleifen durch do-schleifen ersetzen, um den ersten test zu sparen, denn der aufrufer garantier ja, daß immer ein schleifendurchlaif passieren wird.

    hab ich was schlimmes übersehen (außer, daß die funktion gar keinen optimierungsbedarf hatte)?


Log in to reply