Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

Δημοσ.

Καλησπέρα,

 

Έχω ένα μεγάλο αρχείο(~100MB, ~2.1εκ γραμμές) κειμένου σε στυλ .csv.

 

Αυτό που κάνω είναι να το διαβάζω ολόκληρο μια φορά και να περναώ να δεδομένα του σε μια δομή που έχω. Η διαδικασία αυτή προς το παρόν κρατάει 9 δευτερόλεπτα.(~5 η αναγνωση χωρις την προσθηκη στην δομη)

 

Η ερώτηση μου ειναι αν μπορώ να το κάνω γρηγορότερα, γιατι νομίζω αυτό που κάνω ειναι κάπως χρονοβόρο.

 

Ο τρόπος που το κάνω ειναι ο εξής:

 

ifstream f(fileName, std::ios::in);	
string line;
vector<string> fields;

while(getline(f, line))
{
	string buf = "";
	for(unsigned int p = 0; p < line.length(); p++)
	{
		if(line[p] != ',')
			buf += line[p];

		if(line[p] == ',' || p == line.length() - 1)
		{
			fields.push_back(buf);
			buf.clear();
		}
	}

	int column = atoi(fields[0].c_str());
	//κτλ για τις αλλες στηλες

	//προσθήκη στην δομή		
	
	fields.clear();
}

 

 

Ευχαριστώ.

  • Απαντ. 30
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Δημοσ.

Το διαβασμα μπορεις να το επιταχυνεις διαβαζοντας Link.png Site: 4ΚΒ  αντι μια γραμμη καθε φορά.  

 

Ειχα κανει κατι πειραματα παλια, αν θυμαμαι καλα, 32μβ ειναι οτι καλυτερο.

 

Νομιζω οτι το καλυτερο ειναι να φορτωσεις ολο το αρχειο στη μνημη. Και μετα να κανεις parse

  • Like 1
Δημοσ.

Πως θα δουλευε να διαβάζω κατα xKΒ, δεν θα κοβονται γραμμές στην μέση;

 

Το να το διαβάσω όλο με την μια ακουγεται ενδιαφέρον, μεσα σε ενα string υποθετω. Θα το δοκιμασω

Δημοσ.

 

Ναι, αλλα μετα για να το διαβάσω το περναω σε string. Ή οχι;

 

Λοιπόν εκανα το εξής:

 

//οπως πριν

stringstream buffer;

buffer << f.rdbuf(); 

while(getline(buffer, line))
{

//οπως πριν

}
 

Αλλά είναι πιο αργό, στα 11 δευτερολεπτα.

Δημοσ.

To ifstream είναι ήδη buffered, δεν διαβάζει μόνο μια γραμμή κάθε φορά. Μπορείς να αλλάξεις το μέγεθος του buffer ως εξής:

char buffer[N];
f.rdbuf()->pubsetbuf(buffer, N);

Στην ταχύτητα του διαβάσματος θα παίξει ρόλο κυρίως η ποιότητα της standard library, οπότε χρησιμοποίησε ό,τι πιο καινούριο μπορείς σε compiler. Απο κει και πέρα το σωστό το πρόστυχο buffer size θα το βρεις πειραματικά, εμπειρικά γύρω στα 4-16KB είναι καλό μέρος να κοιτάξεις. Δυσκολεύομαι να πιστέψω τα 32MB του παπιού, αλλά πάντα εξαρτάται και από το workload που έχεις. Μη ξεχνάς ότι μεγάλα reads θα κάνουν ενδεχομένως τη CPU να βάλει την cache στον ποκοπίκο της, πράγμα που δε θέλεις.

 

Απο κει και πέρα μπορείς να προσπαθήσεις να κάνεις optimize το inner loop, π.χ. για non-trivial μήκη γραμμών μου φαίνεται πως θα κάνεις αχρείαστα πολλά reallocations -- δοκίμασε buf.reserve(128) μετά το reset.

 

Και τέλος, 5 sec για να διαβάσεις απλά 100MB από το δίσκο ακούγονται κάπως πολλά... 20mb/sec? Δυσκολεύομαι να πιστέψω ότι ο δίσκος δε μπορεί να κάνει κάτι καλύτερο.

Δημοσ.

Δοκίμασα και τα 2(χωριστά) και δεν είχαν ουσιαστική διαφορά (0.1-0.2 secs που μπορει να ειναι και τυχαια).

 

Στο buffer δοκιμασα 4ΚΒ, 8ΚΒ, 16ΚΒ και 32ΚB.

 

Στο reserve δοκιμασα εκτος απο 128 και 64(επειδη οι γραμμές ειναι παντα γυρω στους 40-50 χαρακτηρες) και περιέργως ηταν κοντα 1sec πιο αργό, ενώ με το 128 ηταν κανονικά.

 

edit:

Χρόνοι με βάση τον κωδικα μεσα στο while:

1. Αδειο while - 2.5 seconds*

2. Μονο το split στο κόμμα - 4.2 seconds

3. Split + μετατροπες των column απο string σε int κτλ - 4.9seconds

 

*Άρα, απλα διαβάζοντας και τίποτα αλλο εχουμε 40ΜΒ/s δισκου. Το Sata2 βλέπω ειναι 300ΜΒ/s. Χμ.

Δημοσ.

Από περιέργεια, δοκίμασα να διαβάσω σε ένα buffer ένα csv αρχείο 215+ Mb με περίπου 1.800.000 γραμμές, μονοκόμματα με fread() από C και το διάβασε σε λιγότερο από 1 δευτερόλεπτο.

 

Κατόπιν, έκανα allocate 1.800.000 50άδες από char pointers (δηλαδή 1.800.000 γραμμές με χώρο για 50 fields η καθεμιά τους, στην ορολογία που χρησιμοποίησες στο παράδειγμά σου), και τους γέμισα κάνοντας parse το buffer στη μνήμη. Αυτό διήρκεσε κάτι περισσότερο από μισό δευτερόλεπτο... Σύνολο και τα 2 μαζί, κάτω από 1.5 δευτερόλεπτο.

221535910 bytes read from file in: 0.734 secs
356428800 bytes parsed on mem  in: 0.641 secs (1782144 lines)
Press ENTER...
Όμως, δεν έκανα copy τα strings από το buffer στα fields. Έπιασα το buffer στη μνήμη από την αρχή κι όπου έβρισκα ',' ή '\n' τα μηδένιζα in-place με '\0', ενώ ταυτόχρονα τοποθετούσα τους char-pointers (δηλαδή τα fields) κι ενημέρωνα και τον μετρητή των γραμμών.

 

Με άλλα λόγια, αν ξέρεις τα όρια του csv αρχείου σου τόσο σε γραμμές, όσο και σε fields, τότε μπορείς να γλιτώσεις πολύ χρόνο δουλεύοντας κατά βάση στατικά αντί για δυναμικά, θυσιάζοντας λίγη (έως αρκετή) μνήμη (εννοώ π.χ για γραμμές που έχουν λιγότερα fields από το μάξιμουμ που έχεις υπολογίσει... αλλά κι αυτό μπορείς να το περιορίσεις, αν κάνεις pre-allocate τον μέσο αναμενόμενο όρο του πλήθους των fields σε κάθε γραμμή, και να το μεγαλώνεις μονάχα αν χρειαστεί... προφανώς θα θυσιάσεις λίγο χρόνο εκεί).

 

Επίσης, για το όριο των γραμμών, αν δεν το το ξέρεις καθόλου, τότε μπορεί να σε συμφέρει να παρσάρεις μια φορά το buffer μόνο και μόνο για να μετρήσεις πόσες γραμμές έχει, και μετά να το ξαναπαρσάρεις για να τραβήξεις τα fields της κάθε γραμμής. Πρέπει να το μετρήσεις και να δεις (συνήθως σε συμφέρει πάντως).

 

Παραθέτω και τον κώδικα σε spoiler...

 

Κώδικας

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <inttypes.h>

#define FNAME		"test2.csv"
#define MAX_LINES	1790000
#define MAX_LINE_FIELDS 50

typedef struct line {
	char *fields[MAX_LINE_FIELDS];
} Line;

/*********************************************************//** 
 *
 *************************************************************
 */
void press_enter( void )
{
	int c = '\0';
	printf( "Press ENTER..." );
	fflush( stdout );
	while ( '\n' != (c=getchar()) && EOF != c )
		;
}

/*********************************************************//**
 * @brief	Return the size of a file in bytes, or 0 on error
 *		(cannot be more than LONG_MAX).
 *************************************************************
 */
uintmax_t f_size( const char *fname )
{
	long int size;
	FILE 	*fp;

	if ( NULL == (fp = fopen(fname, "rb")) )	/* binary mode */
		return 0;

	if ( 0 != fseek(fp, 0, SEEK_END) ) {
		fclose(fp);
		return 0;
	}

	size = ftell(fp);
	fclose(fp);

	return (size < 0) ? 0 : (uintmax_t)size;
}

/*********************************************************//**
 * 
 *************************************************************
 */
char *new_buf_from_csvfile( const char *fname )
{
	uintmax_t fsize = f_size( fname );
	if ( 0 == fsize ) {
		return NULL;
	}

	char *buf = malloc( 1+fsize );
	if ( !buf ) {
		return NULL;
	}
	buf[ fsize ] = '\0';

	FILE *fp = fopen( fname, "r" );
	if ( !fp ) {
		free( buf );
		return NULL;
	}

	/* ------- TIME IT ------ */
	clock_t tend, tstart;
	double cpu_time_used = 0.0;
	tstart = clock();

	/* Code we want timed here */
	size_t n = fread( buf, 1, fsize, fp );
	if ( ferror(fp) ) {
		free( buf );
		fclose( fp );
		return NULL;
	}
	fclose( fp );
	buf[n] = '\0';

	tend = clock();
	cpu_time_used = ((double) (tend - tstart)) / CLOCKS_PER_SEC;
	printf(
		"%" PRIuMAX " bytes read from file in: %g secs\n",
		fsize,
		cpu_time_used
	);
	/* ---------------------- */

	return buf;
}

/*********************************************************//**
 * 
 *************************************************************
 */
bool buf_parse( char *buf, Line *lines, size_t *nlines )
{
	if ( !buf || !lines || !nlines ) {
		return false;
	}

	size_t l = 0, f = 0;
	char *cp = lines[l].fields[f] = buf;

	/* ------- TIME IT ------ */
	clock_t tend, tstart;
	double cpu_time_used = 0.0;
	tstart = clock();

	/* Code we want timed here */
	while ( *cp && l < MAX_LINES )
	{
		if ( ',' == *cp && f < MAX_LINE_FIELDS ) {
			*cp = '\0';
			lines[l].fields[++f] = cp + 1;
		}
		else if ( '\n' == *cp ) {
			*cp = '\0';
			f = 0;
			lines[++l].fields[f] = cp + 1;
		}
		cp++;	
	}

	tend = clock();
	cpu_time_used = ((double) (tend - tstart)) / CLOCKS_PER_SEC;
	/* ---------------------- */
	printf(
		"%zu bytes parsed on mem  in: %g secs (%zu lines) \n",
		l * sizeof(Line),
		cpu_time_used,
		l
	);

	*nlines = l;
	return true;
}

/*********************************************************//**
 * 
 *************************************************************
 */
int main( void )
{
	char *buf = NULL;
	Line *lines = NULL;
	size_t nlines = 0;
	char *fname = FNAME;

	// load csv file into buf
	buf = new_buf_from_csvfile( fname );
	if ( !buf ) {
		goto exit_failure;
	}

	// parse buf into lines & fields
	lines = calloc( MAX_LINES, sizeof(Line) );
	if ( !lines ) {
		goto exit_failure;
	}
	buf_parse( buf, lines, &nlines );

/*
	// print lines & fields
	for (size_t l=0; l < nlines && l < MAX_LINES; l++)
	{
		printf( "---- line: %zu ----\n", l+1 );
		for (size_t f=0; f < MAX_LINE_FIELDS; f++) {
			char *s = lines[l].fields[f];
			if ( s ) {
				puts( *s ? s : "\\0" );
			}
		}
	}
*/

	free( lines );
	free( buf );

	press_enter();

	return 0;

exit_failure:
	if (lines ) free( lines );
	if ( buf ) free(buf);
	puts( "*** error ***" );
	press_enter();
	return 1;
}

 

Το csv αρχείο που χρησιμοποίησα είναι αυτό που βάζω σε επισύναψη, αλλά πολλαπλασιασμένο με copy & paste μέχρι να φτάσει στα 215+ Mb.

countrylist.zip

  • Like 1
Δημοσ.

Αν θέλεις να το ψάξεις περισσότερο κάπου εδώ είναι η ώρα που πρέπει να αφήσουμε τη συζήτηση καφενείου και να αναφωνήσουμε όλοι μαζί "science, bitches": πρέπει να κάνεις profiling στο πρόγραμμά σου.

 

Υπάρχει πολύ πράγμα να ψάξεις από εργαλεία, αλλά για ένα quick start νομίζω το very sleepy είναι καλή επιλογή.

 

Αυτό που θέλεις είναι (κάνε κλικ στο δεύτερο screenshot δεξιά) να βρεις πράγματα που έχουν μεγάλο ποσοστό % inclusive και τα οποία μπορείς να αποφύγεις ή να κάνεις γρηγορότερα.

Δημοσ.

Πέρα από το file i/o που προφανώς αποτελεί βασική τροχοπέδη στους χρόνους, παίζει ρόλο και πως γίνεται το διάβασμα, αλλά και τι άλλες ενέργειες γίνονται κατά το διάβασμα.

 

Ξέρω πως σε γενικές γραμμές η συνηθισμένη τακτική είναι να διαβάζεται το αρχείο μονοκόμματα και μετά να παρσάρεται στη μνήμη. Χωρίς αυτό να σημαίνει πως είναι παντού ιδανικό. Στη γενική περίπτωση όμως είναι ταχύτερο από το να διαβάζεις και να παρσάρεις ταυτόχρονα γραμμή-γραμμή μέσα από το αρχείο.

 

Επίσης, αν δεν έχεις κάποιον ιδιαίτερο λόγο να κοπιάρεις ολόκληρες τις λέξεις (fields) στο άλλο data-structure, ο τρόπος που σου έδειξα είναι κατά πολύ ταχύτερος στο σετάρισμα, γιατί δεν κοπιάρει μνήμη. Δηλαδή να έχεις μεν το άλλο data-structure, αλλά να το βάλεις να δείχνει με δείκτες στα φορτωμένα data, αντί να τα αντιγράφεις (π.χ. το vector που έχεις αντί να περιέχει strings να περιέχει δείκτες προς το buffer που θα έχεις διαβάσει μονοκόμματα).

 

Αυτό δεν χρειάζεται να το μετρήσεις, είναι σίγουρο πως θα είναι πολύ ταχύτερο κατά το σετάρισμά του.

 

Πρέπει όμως να σταθμίσεις αν αυτό το στήσιμο σε εξυπηρετεί ή όχι και στα υπόλοιπα κομμάτια του προγράμματός σου (πέρα δηλαδή από το διάβασμα του αρχείο και το αρχικό σετάρισμα).

 

Από περιέργεια τροποποίησα τον κώδικα του περασμένου ποστ ώστε να κάνει malloc() τα fields και να κοπιάρει μέσα τους τα strings από το διαβασμένο buffer (αντί δηλαδή να βάζει δείκτες). Και παρόλο που βαρέθηκα να βάλω ελέγχους για αποτυχία αυτών των malloc(), η διαφορά είναι... χαώδης (όπως είναι αναμενόμενο)...

 

/* ------ cached with COPY ------- */

loading test2.csv...
219753766 bytes read from file in: 0.734 secs

parsing loaded data...
356428800 bytes (for 1782144 lines) created & filled on mem in: 5.75 secs
(194738470 additional bytes copied in all line fields)

cleaning up, please wait... Press ENTER...

/* ------ cached without COPY ------- */

loading test2.csv...
219753766 bytes read from file in: 0.718 secs

parsing loaded data...
356428800 bytes (for 1782144 lines) created & filled on mem in: 0.687 secs
(0 additional bytes copied in all line fields)

cleaning up, please wait... Press ENTER...
Μιλάω για τα δεύτερα νούμερα, αυτά που αναφέρονται στο "γέμισμα" των fields. Με copying κάνει συνολικά γύρω στα 6(-) secs, και χωρίς κάνει γύρω στο 1(-) δευτερόλεπτο.

 

* Εκείνο το "cached" αναφέρεται στο file-cache. Ότι δηλαδή το αρχείο είναι κασαρισμένο από το λειτουργικό (uncached, π.χ. απευθείας μετά από cold-boot, στο μηχανάκι με τα XP και τα 2G μνήμη κάνει γύρω στα 22 δευτερόλεπτα για φορτωθεί).

 

Βάζω και τον κώδικα σε spoiler, αν θες να κάνεις δικές σου δοκιμές (απλώς έβαλα τον "χρονομέτρη" να είναι συνάρτηση που δέχεται ως callback τη συνάρτηση που θέλουμε να μετρήσει... συν ότι σε αυτό τον κώδικα μετράω και τα memory allocations των buf και fileds, και το ανοιγοκλείσιμο του αρχείου (στον προηγούμενο κώδικα δεν τα μέτραγα αυτά).

 

Κώδικας:

 

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define COPY_STRINGS	0          // set it to 1 to enable data copying for fields

#define FNAME		"test2.csv"
#define MAX_LINES	1790000
#define MAX_LINE_FIELDS 50

typedef struct line {
	char *fields[MAX_LINE_FIELDS];
} Line;

typedef struct
{
	// used for reading the file in mem
	char *buf;
	char *fname;
	size_t fsize;
	size_t n;

	// used for parsing loaded data
	Line *lines;
	size_t nlines;
	size_t ncopied;

} CallbackData;

/*********************************************************//** 
 *
 *************************************************************
 */
void press_enter( void )
{
	int c = '\0';
	printf( "Press ENTER..." );
	fflush( stdout );
	while ( '\n' != (c=getchar()) && EOF != c )
		;
}

/*********************************************************//**
 * Duplicate a c-string.
 *************************************************************
 */
char *s_strdup( const char *src )
{
	char *s = NULL;
	size_t size = 0;

	/* sanity check */
	if ( !src ) {
		return NULL;
	}

	size = 1 + strlen( src );
	if ( !(s = malloc(size)) ) {
		return NULL;
	}

	return memcpy( s, src, size );
}

/*********************************************************//**
 * Return as secs, the cpu-time spent for executing the callback function.
 * On error, return -1.0
 *************************************************************
 */
double time_it( void *userdata, int (*callback)(void *userdata) )
{
	clock_t tend, tstart;
	tstart = clock();

	/* Code we want timed here */
	if ( 0 == (*callback)(userdata) ) {
		return -1.0;
	}

	tend = clock();
	return ((double) (tend - tstart)) / CLOCKS_PER_SEC;
}

/*********************************************************//**
 * @brief	Return the size of a file in bytes, or 0 on error
 *		(cannot be more than LONG_MAX).
 *************************************************************
 */
size_t f_size( const char *fname )
{
	long int size;
	FILE 	*fp;

	if ( NULL == (fp = fopen(fname, "rb")) )	/* binary mode */
		return 0;

	if ( 0 != fseek(fp, 0, SEEK_END) ) {
		fclose(fp);
		return 0;
	}

	size = ftell( fp );
	fclose( fp );

	return (size < 0) ? 0 : (size_t)size;
}

/*********************************************************//**
 * 
 *************************************************************
 */
int cb_read_csvfile_to_buf( void *data )
{
	CallbackData *d = (CallbackData *) data;

	d->fsize = f_size( d->fname );
	if ( 0 == d->fsize ) {
		return 0;
	}

	d->buf = malloc( 1 + d->fsize );
	if ( ! d->buf ) {
		return 0;
	}
	d->buf[ d->fsize ] = '\0';

	FILE *fp = fopen( d->fname, "r" );
	if ( !fp ) {
		free( d->buf );
		d->buf = NULL;
		return 0;
	}

	//setvbuf( fp, buf, _IONBF, fsize );

	d->n = fread( d->buf, 1, d->fsize, fp );
	if ( ferror(fp) ) {
		free( d->buf );
		d->buf = NULL;
		fclose( fp );
		return 0;
	}
	fclose( fp );
	d->buf[ d->n ] = '\0';

	return 1;
}

/*********************************************************//**
 * 
 *************************************************************
 */
int cb_parse_buf_to_lines( void *data )
{
	CallbackData *d = (CallbackData *) data;
	if ( !d->buf  ) {
		return 0;
	}

	d->lines = calloc( MAX_LINES, sizeof(Line) );
	if ( !d->lines ) {
		return 0;
	}

	size_t l = 0, f = 0;		// lines, fields counters
	char *cp = d->lines[l].fields[f] = d->buf;
	d->ncopied = 0;			// overall bytes copied in fields

#if COPY_STRINGS
	char *pre = d->buf;
	while ( *cp && l < MAX_LINES )
	{
		if ( ',' == *cp && f < MAX_LINE_FIELDS ) {
			*cp = '\0';
			d->lines[l].fields[f++] = s_strdup( pre );  // validation omitted
			d->ncopied += cp - pre;
			pre = cp + 1;
			//d->lines[l].fields[++f] = cp + 1;
		}
		else if ( '\n' == *cp ) {
			*cp = '\0';
			d->lines[l++].fields[f] = s_strdup( pre );  // validation omitted
			d->ncopied += cp - pre;
			pre = cp + 1;
			f = 0;
			//d->lines[++l].fields[f] = cp + 1;
		}
		cp++;	
	}
#else
	while ( *cp && l < MAX_LINES )
	{
		if ( ',' == *cp && f < MAX_LINE_FIELDS ) {
			*cp = '\0';
			d->lines[l].fields[++f] = cp + 1;
		}
		else if ( '\n' == *cp ) {
			*cp = '\0';
			f = 0;
			d->lines[++l].fields[f] = cp + 1;
		}
		cp++;	
	}
#endif

	d->nlines = l;
	return 1;
}

/*********************************************************//**
 * 
 *************************************************************
 */
void lines_destroy( Line *lines )
{
	if ( !lines ) {
		return;
	}

	for (size_t l=0; l < MAX_LINES; l++) {
		for (size_t f=0; f < MAX_LINE_FIELDS; f++) {
			if ( lines[l].fields[f] ) {
				free( lines[l].fields[f] );
			}
		}
	}
	free( lines );
}

/*********************************************************//**
 * 
 *************************************************************
 */
int main( void )
{
	double cputime = 0.0;
	CallbackData cd = {
		.buf = NULL,
		.fname = FNAME,
		.fsize = 0U,
		.n     = 0U,

		.lines = NULL,
		.nlines = 0U,
		.ncopied = 0U
	};

	// load csv file into memory buffer

	printf( "loading %s... ", cd.fname );
	fflush( stdout );

	cputime = time_it( (void *)&cd, cb_read_csvfile_to_buf );
	if ( -1.0 == cputime ) {
		goto exit_failure;
	}
	printf( "\n%zu bytes read from file in: %g secs\n\n", cd.n, cputime );

	// parse buf into lines & fields

	printf( "parsing loaded data... " );
	fflush( stdout );

	cputime = time_it( (void *)&cd, cb_parse_buf_to_lines );
	if ( -1.0 == cputime ) {
		goto exit_failure;
	}
	printf(
		"\n%zu bytes (for %zu lines) created & filled on mem in: %g secs\n",
		cd.nlines * sizeof(Line),
		cd.nlines,
		cputime
	);
	printf(	"(%zu additional bytes copied in all line fields)\n", cd.ncopied );

/*
	press_enter();

	// print lines & fields
	for (size_t l=0; l < nlines && l < MAX_LINES; l++)
	{
		printf( "---- line: %zu ----\n", l+1 );
		size_t i = 0;
		for (size_t f=0; f < MAX_LINE_FIELDS; f++) {
			char *s = lines[l].fields[f];
			if ( s ) {
				puts( *s ? s : "\\0" );
			}
			else {
				i++;
			}
		}
		printf( "+ %zu NULL fields\n", i );
	}
*/

	printf( "\ncleaning up, please wait... " );
	fflush( stdout );
	lines_destroy( cd.lines );
	free( cd.buf );

	press_enter();

	return 0;

exit_failure:
	puts( "*** error ***" );
	printf( "\ncleaning up, please wait... " );
	fflush( stdout );
	if ( cd.lines ) {
		lines_destroy( cd.lines );
	}
	if ( cd.buf ) {
		free( cd.buf);
	}

	press_enter();

	return 1;
}

 

Δημοσ.

Ευχαριστώ για τις απαντήσεις. Με βάση αυτές έφτιαξα το εξής:

 

 

 

ifstream f(fileName, std::ios::in);

int file_size;
char* file_contents;

if(f.is_open())
{
	f.seekg(0, std::ios::end);
	file_size = f.tellg();
	file_contents = new char[file_size];
	f.seekg(0, std::ios::beg);
	f.read(file_contents, file_size);
	f.close();
}

char fields[13][100];

int field_num = 0;
int field_pos = 0;

for(int p = 0; p < file_size; p++)
{
	if(file_contents[p] != ',')
	{
		fields[field_num][field_pos] = file_contents[p];
		field_pos++;
	}

	if(file_contents[p] == ',')
	{
		fields[field_num][field_pos] = '\0';
		field_num++;
		field_pos = 0;
	}

	if(file_contents[p] == '\n')
	{
		int col1 = atoi(fields[0]);
		//κτλ για τα υπόλοιπα cols

		//add στην βάση εδω

		field_num = 0;
		field_pos = 0;
	}
}

delete[] file_contents; 

 

 

Χρόνοι:

Χωρίς add στην βάση - 1.7secs

Με add στην βάση - 5.7secs

 

Νομίζω είναι μια χαρά. Παρ'όλα αυτά, αν βλέπετε χώρο για βελτιώση πείτε.

 

Η βάση είναι κάποιο map, θα δοκιμασω αυριο να δω αν μπορω να κανω καποιου ειδους reserve μηπως βελτιωθεί λιγο ακόμη.

 

 

Ευχαριστώ.

Δημοσ.

Χώρος για βελτίωση σίγουρα υπάρχει, αλλάζοντας τα if() if() if() με κάτι που δεν έχει conditional για να μην αφήσεις ποτέ τη CPU να κάνει λάθος branch prediction. Αλλά δε μπορώ να εκτιμήσω το πόση διαφορά θα κάνει και φανερά η δουλειά σου γίνεται ήδη, οπότε μιλάμε καθαρά για intellectual exercise μόνο για μερακλήδες.

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...