vector<T>::push_back() Performance



  • Hi,
    für ein kleines 2D Spiel habe ich eine Figur, die per *.png Frames in 8 Richtungen animiert wird. Zu diesem Zweck lade ich die Frames in einen Vector, der denselben dann an die Klasse der Figur zurückgibt.

    std::vector<sf::Image> CImageManager::LoadImages(std::string path, int numOfFrames)
    {
    	std::string file;
    	std::vector<sf::Image> vReturn;
    
    	sf::Image tempImage;
    
    	char buffer[3];
    	int temp;
    
    	vReturn.reserve(numOfFrames);
    
    	for(int i = 1; i <= numOfFrames; i++) {
    		temp = i;
    
    		file.append(path);
    		file.append(itoa(temp, buffer, 10));
    		file.append(".png");
    
    		if(!tempImage.LoadFromFile(file))
    			printf("Unable to load Frame\n");
    
    		vReturn.push_back(tempImage);
    
    		file.clear();
    	}
    
    	return vReturn;
    }
    

    Jetzt ist es so, dass pro push_back() etwa 0.12 Sekunden vergehen. Bei derzeit 112 Frames macht das 13 Sekunden Ladezeit nur für die Bilder (+ Ladezeit für tempImage.LoadFromFile(file);)

    Gibt es irgendeine Möglichkeit das zu optimieren? Oder vielleicht einen ganz anderen Weg, um da Zeit einzusparen.

    Wäre für eure Hilfe sehr dankbar.



  • Vielleicht hast du sogar eine ganz grosse Kopie beim Rückgabetyp. Tendenziell eher einen Output-Parameter nehmen (um auf der sicheren Seite zu sein, vielleicht optimiert dein Compiler die Kopie weg):

    ImageManager::LoadImages(std::string path, int numOfFrames, std::vector<sf::Image>& out)
    

    Dann sf::Image zuerst mit push_back() einfügen, und dann über back() anschliessend innerhalb des Containers bearbeiten.

    Im Weiteren würde ich zum String-Zusammenbasteln std::stringstream nehmen.



  • NRVO erwarte ich heutzutage eigentlich von jedem Compiler. Meine Vermutung ist, dass die Kope des sf::Image-Objekts jeweils so lange dauert, wenn es an den Vektor angehängt wird.

    Da sf::Image DefaultConstructible zu sein scheint, ginge es vielleicht so:

    std::vector<sf::Image> CImageManager::LoadImages(std::string path, int numOfFrames)
    {
        std::ostringstream fmt;
        std::vector<sf::Image> vReturn(numOfFrames);
    
        vReturn.reserve(numOfFrames);
    
        for(int i = 0; i < numOfFrames; i++) {
            fmt.clear();
            fmt.str(path);
            fmt << i + 1 << ".png";
    
            if(!vReturn[i].LoadFromFile(fmt.str())) {
                std::cerr << "Unable to load Frame" << std::endl;
            }
        }
    
        return vReturn;
    }
    


  • Bah. Flüchtigkeitsfehler: Die Zeile

    vReturn.reserve(numOfFrames);
    

    ist dann unnötig.



  • Okay,
    hab das umgesetzt, hat einiges gebracht.
    Habe die Bilder noch etwas zusammengeschnitten, habe gemerkt, dass der Großteil der Frames aus Transparenz besteht, also habe ich die Teile weggeschnitten.
    Die 114 Frames laden dauert nun keine Sekunde mehr.

    Danke für die allgemein sehr hilfreichen Tipps! 🙂



  • Nur um mal sicher zu gehen: du hast Optimierungen bei deinem Compiler angeschaltet?



  • Athar schrieb:

    Nur um mal sicher zu gehen: du hast Optimierungen bei deinem Compiler angeschaltet?

    Ich vermute eher Debug-Build ohne Optimierungen.


Anmelden zum Antworten