3ds-Loader (Performance)



  • Hallo,
    ich habe einen 3ds-Loader geschrieben. Nun würde ich gerne wissen, ob er "schnell" genug ist. Der Loader liest alle Objekte, Mappingkoordinaten, Vertices, Objektnamen und Faces. Bei einem Model mit 50643 Punkten und 74508 Faces braucht er im Durchschnitt bei einem Debugbuild um die 7.20ms. Ist das schnell oder eher langsam? Das Model ist zwar schon groß, aber immerhin ist das auch fast 1 Sekunde.

    Ich hoffe auf hilfreiche Antworten, vielleicht ist ja auch jemand so gut und misst die vergangene Zeit bei seinem Loader.

    Vielen Dank im Voraus! 🙂



  • Kóyaánasqatsi schrieb:

    Bei einem Model mit 50643 Punkten und 74508 Faces braucht er im Durchschnitt bei einem Debugbuild um die 7.20ms. [..] Das Model ist zwar schon groß, aber immerhin ist das auch fast 1 Sekunde.

    Warum sind 7 Millisekunden fast 1 Sekunde?



  • Wie hast du denn das gemessen? 7 komma 2 msec?! 😕 Oder ist das ein Mittelwert? (edit) ok, steht ja da 😡
    Und was hast du für Hardware? Ich würd erstmal sagen, das das ganz gut ist. Wenn du mir das Model irgendwo hochlädst kann ich das mal mit meinem 3ds Loader vergleichen, wenn du willst.



  • 1. 7ms ist ziemlich weit weg von 1s
    2. Messungen im Debug Mode sind nahezu ohne Aussage



  • @TyRoXx, this->that
    Verzeiht mir die Aussage, wie ihr seht ist der Thread morgens um 4 Uhr entstanden 🙄

    @Cpp_Junky
    Hey, das wäre nett wenn du es mal durch deinen Loader jagen würdest. Hier der Link:
    http://download399.mediafire.com/3vyfwklbfctg/jjxmzyuqiym/3D-trees-plants-set2.rar ("tree_in_vase2.3ds")
    Ich habe einen "normalen" Intel Core 2 Duo mit á 2,4GHz. 4GB RAM und 64-Bit Vista. Danke im Voraus deswegen!

    Wenn ich es im Releasebuild messe, dauert es im Schnitt 2.30ms.



  • Kóyaánasqatsi schrieb:

    ...
    @Cpp_Junky
    Hey, das wäre nett wenn du es mal durch deinen Loader jagen würdest. Hier der Link:
    http://download399.mediafire.com/3vyfwklbfctg/jjxmzyuqiym/3D-trees-plants-set2.rar ("tree_in_vase2.3ds")
    Ich habe einen "normalen" Intel Core 2 Duo mit á 2,4GHz. 4GB RAM und 64-Bit Vista. Danke im Voraus deswegen!

    Wenn ich es im Releasebuild messe, dauert es im Schnitt 2.30ms.

    Also meiner macht im Schnitt als Release ~60 msec bei dem Model. Ich lade Vertices, Normals, Faces und Materialdaten (Ohne Texturen natürlich).
    Hm, dein Model ist ~1,7 MB gross, das bedeutet deine Platte hat einen effektiven Durchsatz von (1000 / 7) x 1,7 MB >= 240 MB/Sek ? Ist das nicht etwas viel? Die Differenz könnte natürlich auch an meiner schlimmst fragmentierten Mühle hier liegen (Ist ein Intel E5800 3,2ghz, 2GB Ram, Windows XP)



  • Cpp_Junky schrieb:

    Hm, dein Model ist ~1,7 MB gross, das bedeutet deine Platte hat einen effektiven Durchsatz von (1000 / 7) x 1,7 MB >= 240 MB/Sek ? Ist das nicht etwas viel?

    Er hat gar keine Festplatte erwähnt, also ist das Laden der Datei in der gemessenen Zeit wohl nicht enthalten.

    EDIT @Kóyaánasqatsi: Warum zeigst du nicht einfach deinen Code?



  • TyRoXx schrieb:

    ...Er hat gar keine Festplatte erwähnt, also ist das Laden der Datei in der gemessenen Zeit wohl nicht enthalten....

    Kann mir nicht vorstellen, wie man einen 3DS Loader testen will, ohne die Datei dabei auszulesen 😕 Viel zu berechnen gibts da nämlich nicht



  • TyRoXx schrieb:

    Cpp_Junky schrieb:

    Hm, dein Model ist ~1,7 MB gross, das bedeutet deine Platte hat einen effektiven Durchsatz von (1000 / 7) x 1,7 MB >= 240 MB/Sek ? Ist das nicht etwas viel?

    Er hat gar keine Festplatte erwähnt, also ist das Laden der Datei in der gemessenen Zeit wohl nicht enthalten.

    EDIT @Kóyaánasqatsi: Warum zeigst du nicht einfach deinen Code?

    Darauf wollte ich eigentlich verzichten. Naja egal, hier der Code:

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <sstream>
    #include <cassert> 
    #include <vector>
    #include <conio.h>
    
    //>----- Entry point (Primary Chunk at the start of the file ----------------
    #define           PRIMARY                 0x4D4D
    
    //>----- Main Chunks --------------------------------------------------------
    #define           EDIT3DS                 0x3D3D  // Start of our actual objects
    #define           KEYF3DS                 0xB000  // Start of the keyframe information
    
    //>----- General Chunks -----------------------------------------------------
    #define           VERSION           0x0002
    #define           MESH_VERSION      0x3D3E
    #define           KFVERSION         0x0005
    #define           COLOR_F           0x0010
    #define           COLOR_24          0x0011
    #define           LIN_COLOR_24      0x0012
    #define           LIN_COLOR_F       0x0013
    #define           INT_PERCENTAGE    0x0030
    #define           FLOAT_PERC        0x0031
    #define           MASTER_SCALE      0x0100
    #define           IMAGE_FILE        0x1100
    #define           AMBIENT_LIGHT     0X2100
    
    //>----- Object Chunks -----------------------------------------------------
    #define           NAMED_OBJECT      0x4000
    #define           OBJ_MESH          0x4100
    #define           MESH_VERTICES     0x4110
    #define           VERTEX_FLAGS      0x4111
    #define           MESH_FACES        0x4120
    #define           MESH_MATER        0x4130
    #define           MESH_TEX_VERT     0x4140
    #define           MESH_XFMATRIX     0x4160
    #define           MESH_COLOR_IND    0x4165
    #define           MESH_TEX_INFO     0x4170
    #define           HEIRARCHY         0x4F00
    
    //>----- Material Chunks ---------------------------------------------------
    #define           MATERIAL          0xAFFF
    #define           MAT_NAME          0xA000
    #define           MAT_AMBIENT       0xA010
    #define           MAT_DIFFUSE       0xA020
    #define           MAT_SPECULAR      0xA030
    #define           MAT_SHININESS     0xA040
    #define           MAT_FALLOFF       0xA052
    #define           MAT_EMISSIVE      0xA080
    #define           MAT_SHADER        0xA100
    #define           MAT_TEXMAP        0xA200
    #define           MAT_TEXFLNM       0xA300
    
    #define           OBJ_LIGHT         0x4600
    #define           OBJ_CAMERA        0x4700
    
    //>----- KeyFrames Chunks --------------------------------------------------
    #define           ANIM_HEADER       0xB00A
    #define           ANIM_OBJ          0xB002
    
    #define           ANIM_NAME         0xB010
    #define           ANIM_POS          0xB020
    #define           ANIM_ROT          0xB021
    #define           ANIM_SCALE        0xB022
    
    namespace Modelloader
    {
    
    class Vector3f
    {
    	public:
    		float m_x;
    		float m_y;
    		float m_z;
    
    		Vector3f( ) { }
    		Vector3f( const float x, const float y, const float z );
    };
    
    class Vector3i
    {
    	public:
    		int m_x;
    		int m_y;
    		int m_z;
    
    		Vector3i( ) { }
    		Vector3i( const int x, const int y, const int z );
    };
    
    class Vector3i16
    {
    	public:
    		short m_x;
    		short m_y;
    		short m_z;
    
    		Vector3i16( ) { }
    		Vector3i16( const int x, const int y, const int z );
    };
    
    class Vector2f
    {
    	public:
    		float m_x;
    		float m_y;
    
    		Vector2f( ) { }
    		Vector2f( const float x, const float y );
    };
    
    class C3dsInStream 
    {
    	protected:
    		std::ifstream m_Stream;
    		std::stringstream m_StringStream;
    		bool m_AbleToOpen;
    
    		C3dsInStream( const char *Filename );
    		~C3dsInStream( );
    
    		void CharToInt32( const char *Buffer, int &Int32 ) const;
    		void CharToUInt32( const char *Buffer, unsigned int &UInt32 ) const;
    		void CharToInt16( const char *Buffer, short &Int16 ) const;
    		void CharToUInt16( const char *Buffer, unsigned short &UInt16 ) const;
    		void CharToFloat( const char *Buffer, float &Float );
    		void CharToLong( const char *Buffer, long &Long );
    		void CharToDouble( const char *Buffer, double &Double );
    		void CharToString( const char *Buffer, std::string &String );
    };
    
    struct Faces : public Vector3i16
    {
    	unsigned short m_Flags;
    };
    
    struct ObjectBlock
    {
    	std::string m_ObjectName;
    	std::vector< Vector3f > m_Vertices;
    	std::vector< Faces > m_Faces;
    	std::vector< Vector2f > m_MappingCoords;
    };
    
    struct Chunk
    {
    	short m_ID;
    	unsigned int m_Length;
    };
    
    class C3dsLoader : public C3dsInStream
    {
    	public:
    		C3dsLoader( const char *Filename );
    		~C3dsLoader( );
    
    	private:
    		Chunk m_ActChunk;
    		char m_Buffer2[ 2 ];
    		char m_Buffer4[ 4 ];
    		std::vector< ObjectBlock > m_Objects;
    
    		void ReadChunkHeader( );
    		void SkipChunk( const unsigned int Length );
    		void ReadChunkID( );
    		void ChunkLoop( );
    
    		// Notice the hierarchy below
    		void ReadObjectChunk( unsigned int Length );
    			void ReadMeshData( unsigned int Length );
    				void ReadVertices( ObjectBlock &ActObj, unsigned int Length );
    				void ReadFaces( ObjectBlock &ActObj );
    				void ReadMappingCoords( ObjectBlock &ActObj );
    };
    
    }
    #include "3dsLoader.h"
    
    namespace Modelloader
    {
    
    Vector3f::Vector3f( const float x, const float y, const float z ) :
    	m_x( x ),
    	m_y( y ),
    	m_z( z )
    { }
    
    Vector3i::Vector3i( const int x, const int y, const int z ) :
    	m_x( x ),
    	m_y( y ),
    	m_z( z )
    { }
    
    Vector2f::Vector2f( const float x, const float y ) :
    	m_x( x ),
    	m_y( y )
    { }
    
    C3dsInStream::C3dsInStream( const char *Filename ) :
    	m_Stream( Filename, std::ifstream::binary )
    {
    	if( !m_Stream.is_open( ) && !m_Stream.good( ) )
    	{
    		m_AbleToOpen = false; // assert will be called
    		// Do something
    	}
    	else
    	{
    		m_AbleToOpen = true;
    	}
    }
    
    C3dsInStream::~C3dsInStream( )
    {
    	m_Stream.close( );
    }
    
    void C3dsInStream::CharToInt32( const char *Buffer, int &Int32 ) const
    {
    	Int32 = static_cast< int > 
    	( 
    		( static_cast< char > ( Buffer[ 3 ] ) << 24  ) |
    		( static_cast< char > ( Buffer[ 2 ] ) << 16 ) |
    	    ( static_cast< char > ( Buffer[ 1 ] ) << 8 ) |
    		( static_cast< char > ( Buffer[ 0 ] ) ) 
    	);
    }
    
    void C3dsInStream::CharToUInt32( const char *Buffer, unsigned int &UInt32 ) const
    {
    	UInt32 = static_cast< unsigned int > 
    	( 
    		( static_cast< unsigned char > ( Buffer[ 3 ] ) << 24 ) |
    		( static_cast< unsigned char > ( Buffer[ 2 ] ) << 16 ) |
    	    ( static_cast< unsigned char > ( Buffer[ 1 ] ) << 8 ) |
    		( static_cast< unsigned char > ( Buffer[ 0 ] ) ) 
    	);
    }
    
    void C3dsInStream::CharToInt16( const char *Buffer, short &Int16 ) const
    {
    	Int16 = static_cast< short >
    	(
    		( static_cast< unsigned char > ( Buffer[ 1 ] ) << 8  |
             static_cast< unsigned char > ( Buffer[ 0 ] ) )
    	);
    }
    
    void C3dsInStream::CharToUInt16( const char *Buffer, unsigned short &UInt16 ) const
    {
    	UInt16 = static_cast< unsigned short >
    	(
    		( static_cast< unsigned char > ( Buffer[ 1 ] ) << 8  ) |
            ( static_cast< unsigned char > ( Buffer[ 0 ] ) )
    	);
    }
    
    void C3dsInStream::CharToFloat( const char *Buffer, float &Float )
    {	
        ( ( char * ) &Float )[ 0 ] = Buffer[ 0 ];
        ( ( char * ) &Float )[ 1 ] = Buffer[ 1 ];
        ( ( char * ) &Float )[ 2 ] = Buffer[ 2 ];
        ( ( char * ) &Float )[ 3 ] = Buffer[ 3 ];
    }
    
    void C3dsInStream::CharToLong( const char *Buffer, long &Long )
    {
    	Long = ::atol( Buffer );
    }
    
    void CharToDouble( const char *Buffer, double &Double )
    {
    	Double = ::atof( Buffer );
    }
    
    void C3dsInStream::CharToString( const char *Buffer, std::string &String )
    {
    	for( unsigned int i( 0);
    					  i = ::strlen( Buffer );
    					  i++)
    	{
    		String.push_back( Buffer[ i ] );
    	}
    }
    
    C3dsLoader::C3dsLoader( const char *Filename ) :
    	C3dsInStream( Filename )
    {
    	if( !C3dsInStream::m_Stream.good( ) || C3dsInStream::m_Stream.fail( ) 
    		|| C3dsInStream::m_Stream.bad( ) )
    	{
    		throw std::runtime_error("Failed to operate with 3ds-File!");
    	}
    
    	ReadChunkHeader( );
    
    	if( static_cast< short > ( m_ActChunk.m_ID ) != PRIMARY )
    	{
    		std::cout<<"3ds-File is damaged!"<<std::endl;
    	}
    
    	C3dsInStream::m_Stream.seekg( 10, C3dsInStream::m_Stream.ios_base::cur ); // Skip the 10 useless byte
    
    	ChunkLoop( ); // Begin to read neccessary chunks
    }
    
    C3dsLoader::~C3dsLoader( )
    { }
    
    void C3dsLoader::ReadChunkHeader( )
    {
    	C3dsInStream::m_Stream.read( m_Buffer2, sizeof( m_ActChunk.m_ID ) );
    	C3dsInStream::CharToInt16( m_Buffer2, m_ActChunk.m_ID );
    
    	C3dsInStream::m_Stream.read( m_Buffer4, sizeof( m_ActChunk.m_Length ) );
    	C3dsInStream::CharToUInt32( m_Buffer4, m_ActChunk.m_Length );
    }
    
    void C3dsLoader::ReadChunkID( )
    {
    	C3dsInStream::m_Stream.read( m_Buffer2, sizeof( m_ActChunk.m_ID ) );
    	C3dsInStream::CharToInt16( m_Buffer2, m_ActChunk.m_ID );
    }
    
    void C3dsLoader::SkipChunk( const unsigned int Length )
    {
    	C3dsInStream::m_Stream.seekg
    	( 
    		m_ActChunk.m_Length - ( sizeof( m_ActChunk.m_ID ) + sizeof( m_ActChunk.m_Length ) ), // Subtract the ID + Length
    		C3dsInStream::m_Stream.ios_base::cur
    	);
    }
    
    void C3dsLoader::ChunkLoop( )
    {
    	while( !C3dsInStream::m_Stream.eof( ) )
    	{
    		ReadChunkHeader( );
    
    		switch( m_ActChunk.m_ID )
    		{
    			case static_cast< short > ( EDIT3DS ):
    				ReadObjectChunk( m_ActChunk.m_Length );
    				break;
    
    			default:
    				SkipChunk( m_ActChunk.m_Length );
    				break;
    		}
    	}
    
    	m_Objects;
    }
    
    void C3dsLoader::ReadObjectChunk( unsigned int Length )
    {
    	Length -= ( sizeof( m_ActChunk.m_ID ) + sizeof( m_ActChunk.m_Length ) );
    	const unsigned int ActPos = C3dsInStream::m_Stream.tellg( );
    
    	while( static_cast< unsigned int > ( C3dsInStream::m_Stream.tellg( ) ) != ( ActPos + Length ) )
    	{
    		ReadChunkHeader( );
    
    		switch( m_ActChunk.m_ID )
    		{
    			case static_cast< short > ( NAMED_OBJECT ):
    				ReadMeshData( m_ActChunk.m_Length );
    				break;
    
    			default:
    				SkipChunk( m_ActChunk.m_Length );
    				break;
    		}
    	}
    }
    
    void C3dsLoader::ReadMeshData( unsigned int Length )
    {
    	ObjectBlock NewObject;
    
    	Length -= ( sizeof( m_ActChunk.m_ID ) + sizeof( m_ActChunk.m_Length ) );
    	const unsigned int ActPos = C3dsInStream::m_Stream.tellg( );
    
    	// Read the object name
    	m_Buffer2[ 0 ] = -1;
    
    	while( m_Buffer2[ 0 ] != '\0' )
    	{
    		m_Buffer2[ 0 ] = C3dsInStream::m_Stream.get( );
    
    		NewObject.m_ObjectName.push_back( m_Buffer2[ 0 ] );
    	}
    
    	while( static_cast< unsigned int > ( C3dsInStream::m_Stream.tellg( ) ) != ( ActPos + Length ) )
    	{
    		ReadChunkHeader( );
    
    		switch( m_ActChunk.m_ID )
    		{
    		case static_cast< short > ( OBJ_MESH ):
    				ReadVertices( NewObject, m_ActChunk.m_Length );
    				break;
    
    			default:
    				SkipChunk( m_ActChunk.m_Length );
    		}
    	}
    
    	// When everything is read below this parent-chunk, save the object
    	m_Objects.push_back( NewObject );
    }
    
    void C3dsLoader::ReadVertices( ObjectBlock &ActObj, unsigned int Length )
    {
    	Length -= ( sizeof( m_ActChunk.m_ID ) + sizeof( m_ActChunk.m_Length ) );
    	const unsigned int ActPos = C3dsInStream::m_Stream.tellg( );
    
    	ReadChunkHeader( );
    
    	unsigned short NumVertices;
    	Vector3f Vertices;
    
    	C3dsInStream::m_Stream.read( m_Buffer2, sizeof( NumVertices ) );
    	C3dsInStream::CharToUInt16( m_Buffer2, NumVertices );
    
    	for( unsigned short i( 0 ); i != NumVertices; ++i )
    	{
    		C3dsInStream::m_Stream.read( m_Buffer4, sizeof( float ) );
    		C3dsInStream::CharToFloat( m_Buffer4, Vertices.m_x );
    
    		C3dsInStream::m_Stream.read( m_Buffer4, sizeof( float ) );
    		C3dsInStream::CharToFloat( m_Buffer4, Vertices.m_y );
    
    		C3dsInStream::m_Stream.read( m_Buffer4, sizeof( float ) );
    		C3dsInStream::CharToFloat( m_Buffer4, Vertices.m_z );
    
    		ActObj.m_Vertices.push_back( Vertices );
    	}
    
    	while( static_cast< unsigned int > ( C3dsInStream::m_Stream.tellg( ) ) != ( ActPos + Length ) )
    	{
    		ReadChunkHeader( );
    
    		switch( m_ActChunk.m_ID )
    		{
    			case static_cast< short > ( MESH_FACES ):
    				ReadFaces( ActObj );
    				break;
    
    			case static_cast< short > ( MESH_TEX_VERT ):
    				ReadMappingCoords( ActObj );
    				break;
    
    			default:
    				SkipChunk( m_ActChunk.m_Length );
    		}
    	}
    }
    
    void C3dsLoader::ReadFaces( ObjectBlock &ActObj )
    {
    	unsigned short NumFaces;
    	Faces Face;
    
    	C3dsInStream::m_Stream.read( m_Buffer2, sizeof( NumFaces ) );
    	C3dsInStream::CharToUInt16( m_Buffer2, NumFaces );
    
    	for( unsigned short i( 0 ); i != NumFaces; ++i )
    	{
    		C3dsInStream::m_Stream.read( m_Buffer2, sizeof( short ) );
    		C3dsInStream::CharToInt16( m_Buffer2, Face.m_x );
    
    		C3dsInStream::m_Stream.read( m_Buffer2, sizeof( short ) );
    		C3dsInStream::CharToInt16( m_Buffer2, Face.m_y );
    
    		C3dsInStream::m_Stream.read( m_Buffer2, sizeof( short ) );
    		C3dsInStream::CharToInt16( m_Buffer2, Face.m_z );
    
    		C3dsInStream::m_Stream.read( m_Buffer2, sizeof( short ) );
    		C3dsInStream::CharToUInt16( m_Buffer2, Face.m_Flags );
    
    		ActObj.m_Faces.push_back( Face );
    	}
    }
    
    void C3dsLoader::ReadMappingCoords( ObjectBlock &ActObj )
    {
    	unsigned short NumMappingCoords;
    	Vector2f MappingCoords;
    
    	C3dsInStream::m_Stream.read( m_Buffer2, sizeof( NumMappingCoords ) );
    	C3dsInStream::CharToUInt16( m_Buffer2, NumMappingCoords );
    
    	NumMappingCoords;
    
    	for( unsigned short i( 0 ); i != NumMappingCoords; ++i )
    	{
    		C3dsInStream::m_Stream.read( m_Buffer4, sizeof( float) );
    		C3dsInStream::CharToFloat( m_Buffer4, MappingCoords.m_x );
    
    		C3dsInStream::m_Stream.read( m_Buffer4, sizeof( float ) );
    		C3dsInStream::CharToFloat( m_Buffer4, MappingCoords.m_y );
    
    		ActObj.m_MappingCoords.push_back( MappingCoords );
    	}
    }
    }
    


  • void C3dsInStream::CharToString( const char *Buffer, std::string &String ) 
    { 
        for( unsigned int i( 0); 
                          i = ::strlen( Buffer ); 
                          i++) 
        { 
            String.push_back( Buffer[ i ] ); 
        } 
    }
    

    Das wird anscheinend nicht verwendet, denn der Fehler würde bei einem nicht-leeren String auffallen.
    Außerdem hat die Schleife eine quadratische Laufzeit (nach der Korrektur des Vergleichsoperators), was total unnötig ist.

    C3dsInStream::m_Stream.read( m_Buffer4, sizeof( float) ); 
            C3dsInStream::CharToFloat( m_Buffer4, MappingCoords.m_x ); 
    
    //warum nicht einfach das:
    
    C3dsInStream::m_Stream.read(reinterpret_cast<char *>(&MappingCoords.m_x), sizeof(MappingCoords.m_x));
    
    while( static_cast< unsigned int > ( C3dsInStream::m_Stream.tellg( ) ) != ( ActPos + Length ) )
    

    Sieht gefährlich aus. Bist du sicher, dass das bei einer beschädigten Datei keine Endlosschleife ergeben kann?

    Zum Thema Geschwindigkeit: Ich weiß nicht wie gut ifstream::read puffert, eine eigene Implementation könnte schneller sein.

    Falls C++11 zur Verfügung steht, würden sich Move-Operationen bei ObjectBlock lohnen.

    ActObj.m_MappingCoords.push_back( MappingCoords );
    

    Die Anzahl der "mapping coords" ist doch bekannt, also nimm resize oder reserve statt push_back (kommt mehrmals vor).

    for( unsigned short i( 0 ); i != NumFaces; ++i )
    

    Bringt nicht viel, sollte aber erwähnt werden: int kann schneller sein als short .



  • Also ich halte 7.2ms fuer ausreichend, da ein Laden des Modells im vergleich eher selten vorkommt. Darueber hinaus fallen natuerlich einige Inkonsistenten auf. CharToFloat unterscheidet sich stark von CharToDouble . Beim ersteren wird das Bitmuster direkt als Float interpretiert, beim letzteren wird von einem null-terminiertem String ausgegangen und konvertiert. Das passt nicht! Darueber hinaus wuerde ich fuer ersteres union verwenden und fuer letzteres stingstream .

    Was ist, wenn die Datei kleiner als der "Header" ist, also ReadChunkHeader nicht angewandt werden darf? Darueber hinaus gibt es Funktionen wie ReadChunkID , die nie verwendet werden.



  • Hallo,
    in dem Sinne "Danke" an die Verbesserungsvorschläge, aber es geht nicht um Fehler im Code. Wie ich bereits sagte, wollte ich den Code nicht posten, da er lange noch nicht fertig ist. Es geht rein um die Schnelligkeit. Und ob man nun 2 übersichtliche Funktionen oder eine zusammengehackte Funktion aufruft 🙄 Also bitte.



  • Du weisst, dass du verarscht wirst, wenn man dich fragt, ob ein debug Build schnell genug ist.



  • hmmmmmmmm schrieb:

    Du weisst, dass du verarscht wirst, wenn man dich fragt, ob ein debug Build schnell genug ist.

    Wo wurde ich das denn gefragt?



  • 7.2 ms klingt schon sehr schnell. Ich frag mich allerdings warum du 3ds verwendest, wenn du es offenbar auf maximale Ladegeschwindigkeit abgesehen hast. Ich würd da ein eigenes Format entwickeln, das mehr oder weniger einfach ein 1:1 Memory-Dump ist und die Datei dann evtl. gleich direkt in meinen Prozess mappen.



  • Kóyaánasqatsi schrieb:

    hmmmmmmmm schrieb:

    Du weisst, dass du verarscht wirst, wenn man dich fragt, ob ein debug Build schnell genug ist.

    Wo wurde ich das denn gefragt?

    Du hast das im ersten Beitrag gefragt:

    Nun würde ich gerne wissen, ob er "schnell" genug ist. ... bei einem Debugbuild um die 7.20ms.



  • Als Anwender ärgere ich mich eher, wenn ein Programm beim Modelle Laden abstürzt, als wenn es ein bisschen braucht.
    Abgesehen davon solltest du versuchen, die Festplatte anzubetteln, dass sie dir die Daten rechtzeitig rausrückt, anstatt Performancezuwachs im Millisekundenbereich aus deinem Code herausprügeln zu wollen.
    Endlosschleifen bei nichtleeren Strings oder semantisch inkonsistente Casts hingegen sind Sachen, die man vermeiden sollte, protected -Attribute sind nutzlos.
    Und was genau unterscheidet deine (fehlerhafte) CharToString-Methode eigentlich von std::string::append(const char*)?
    Ist lexical_cast (an den - bei dir dank der seltsamen Semantik schwer auszumachenden - entsprechenden Stellen) zu langsam, oder willst du Abhängigkeiten vermeiden? Trifft letzteres zu: Sind stringstreams zu langsam? Wieso übergibst du konstante Werte? Und, wenn man drauf steht, kann man doch solche Vektorfummeleien gar wunderbar in Templates auslagern.
    Und - ohne es genau sagen zu können - mich plagt das Gefühl, dass der Codeaufbau überdacht werden sollte, wenn man schon eine Aufrufstruktur durch Einrücken beschreiben muss, damit der Durchblick gewahrt werden kann.

    Nicht?



  • PS: Und da ist es auch ziemlich Schnurz, ob der Code noch lange nicht fertig ist. Wenn er noch nicht fertig ist, dann braucht dich Performance noch viel weniger zu interessieren als sowieso.


Anmelden zum Antworten