Skip to content

Commit 788c611

Browse files
committed
Fix reading of csv-files, including caching and tranposing variables for increased performance
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@18423 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
1 parent 6e97464 commit 788c611

File tree

5 files changed

+107
-21
lines changed

5 files changed

+107
-21
lines changed

Compiler/runtime/SimulationResults.c

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ typedef struct {
3535
#endif
3636
ModelicaMatReader matReader;
3737
FILE *pltReader;
38-
FILE *csvReader;
38+
struct csv_data *csvReader;
3939
} SimulationResult_Globals;
4040

4141
static SimulationResult_Globals simresglob = {
@@ -48,7 +48,7 @@ static void SimulationResultsImpl__close(SimulationResult_Globals* simresglob)
4848
switch (simresglob->curFormat) {
4949
case MATLAB4: omc_free_matlab4_reader(&simresglob->matReader); break;
5050
case PLT: fclose(simresglob->pltReader); break;
51-
case CSV: fclose(simresglob->csvReader); break;
51+
case CSV: omc_free_csv_reader(simresglob->csvReader); simresglob->csvReader=NULL; break;
5252
default: break;
5353
}
5454
simresglob->curFormat = UNKNOWN_PLOT;
@@ -103,7 +103,7 @@ static PlotFormat SimulationResultsImpl__openFile(const char *filename, Simulati
103103
}
104104
break;
105105
case CSV:
106-
simresglob->csvReader = fopen(filename, "r");
106+
simresglob->csvReader = read_csv(filename);
107107
if (simresglob->csvReader==NULL) {
108108
msg[1] = filename;
109109
c_add_message(NULL,-1, ErrorType_scripting, ErrorLevel_error, gettext("Failed to open simulation result %s: %s"), msg, 2);
@@ -119,6 +119,7 @@ static PlotFormat SimulationResultsImpl__openFile(const char *filename, Simulati
119119
simresglob->curFormat = format;
120120
simresglob->curFileName = strdup(filename);
121121
#if !defined(__MINGW32__) && !defined(_MSC_VER)
122+
stat(filename, &buf);
122123
simresglob->mtime = buf.st_mtime;
123124
#endif
124125
// fprintf(stderr, "SimulationResultsImpl__openFile(%s) => %s\n", filename, PlotFormatStr[curFormat]);
@@ -216,7 +217,7 @@ static int SimulationResultsImpl__readSimulationResultSize(const char *filename,
216217
return size;
217218
}
218219
case CSV: {
219-
size = read_csv_dataset_size(filename);
220+
size = simresglob->csvReader ? simresglob->csvReader->numsteps : -1;
220221
msg[0] = filename;
221222
if (size == -1) c_add_message(NULL,-1, ErrorType_scripting, ErrorLevel_error, gettext("Failed to read readSimulationResultSize from file: %s\n"), msg, 1);
222223
return size;
@@ -246,15 +247,14 @@ static void* SimulationResultsImpl__readVars(const char *filename, SimulationRes
246247
return read_ptolemy_variables(filename);
247248
}
248249
case CSV: {
249-
int length = 0;
250-
char **variables = read_csv_variables(simresglob->csvReader,&length);
251-
if (variables) {
250+
if (simresglob->csvReader && simresglob->csvReader->variables) {
251+
char **variables = simresglob->csvReader->variables;
252252
int i;
253-
for (i=length-1; i>=0; i--) {
254-
res = mk_cons(mk_scon(variables[i]),res);
255-
GC_free(variables[i]);
253+
for (i=simresglob->csvReader->numvars-1; i>=0; i--) {
254+
if (variables[i][0] != '\0') {
255+
res = mk_cons(mk_scon(variables[i]),res);
256+
}
256257
}
257-
GC_free(variables);
258258
}
259259
return res;
260260
}
@@ -349,7 +349,7 @@ static void* SimulationResultsImpl__readDataset(const char *filename, void *vars
349349
while (RML_NILHDR != RML_GETHDR(vars)) {
350350
var = RML_STRINGDATA(RML_CAR(vars));
351351
vars = RML_CDR(vars);
352-
vals = read_csv_dataset(filename,var,dimsize);
352+
vals = simresglob->csvReader ? read_csv_dataset(simresglob->csvReader,var) : NULL;
353353
if (vals == NULL) {
354354
msg[1] = var;
355355
msg[0] = filename;

SimulationRuntime/c/util/read_csv.c

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static void add_variable(void *data, size_t len, void *t)
8181
head->buffer_size = head->buffer_size ? 2*head->buffer_size : 512;
8282
head->variables = GC_realloc(head->variables, sizeof(char*)*head->buffer_size);
8383
}
84-
head->variables[head->size++] = data ? GC_strdup(data) : data;
84+
head->variables[head->size++] = GC_strdup(data ? data : "");
8585
}
8686

8787
static void row_count(int c, void *t)
@@ -149,17 +149,18 @@ char** read_csv_variables(FILE *fin, int *length)
149149
static void add_cell(void *data, size_t len, void *t)
150150
{
151151
struct csv_body *body = (struct csv_body*) t;
152-
char *endptr;
152+
char *endptr = "";
153153
if (!body->found_first_row) {
154154
body->cur_size++;
155155
body->row_length++;
156156
return;
157157
}
158158
if (body->size+1 >= body->buffer_size) {
159-
body->buffer_size = body->buffer_size ? 2*body->buffer_size : body->row_length*1024; /* Guess it's 1024 time points; we could also take the size of the file or something, but this is cool too */
159+
body->buffer_size = body->res ? 2*body->buffer_size : body->row_length*1024; /* Guess it's 1024 time points; we could also take the size of the file or something, but this is cool too */
160+
body->buffer_size = body->buffer_size > 0 ? body->buffer_size : 1024;
160161
body->res = body->res ? (double*)GC_realloc(body->res, sizeof(double)*body->buffer_size) : (double*) GC_malloc_atomic(sizeof(double)*body->buffer_size);
161162
}
162-
body->res[body->size++] = strtod((const char*)data,&endptr);
163+
body->res[body->size++] = data ? strtod((const char*)data,&endptr) : 0;
163164
if (*endptr) {
164165
printf("Found non-double data in csv result-file: %s\n", (char*) data);
165166
body->error = 1;
@@ -177,7 +178,7 @@ static void add_row(int c, void *t)
177178
}
178179
}
179180

180-
double* read_csv_dataset(const char *filename, const char *var, int dimsize)
181+
double* read_csv_dataset_var(const char *filename, const char *var, int dimsize)
181182
{
182183
const int buf_size = 4096;
183184
char buf[4096];
@@ -203,8 +204,82 @@ double* read_csv_dataset(const char *filename, const char *var, int dimsize)
203204
csv_fini(&p,add_cell,add_row,&body);
204205
csv_free(&p);
205206
fclose(fin);
206-
if (!body.error) {
207+
if (body.error) {
207208
return NULL;
208209
}
209210
return body.res;
210211
}
212+
213+
struct csv_data* read_csv(const char *filename)
214+
{
215+
const int buf_size = 4096;
216+
char buf[4096];
217+
char **variables;
218+
int dummy;
219+
struct csv_parser p;
220+
struct csv_body body = {0};
221+
struct csv_data *res = GC_malloc(sizeof(struct csv_data));
222+
FILE *fin = fopen(filename, "r");
223+
if (!fin) {
224+
return NULL;
225+
}
226+
variables = read_csv_variables(fin,&dummy);
227+
if (!variables) {
228+
return NULL;
229+
}
230+
fseek(fin,0,SEEK_SET);
231+
232+
csv_init(&p, CSV_STRICT | CSV_REPALL_NL | CSV_STRICT_FINI | CSV_APPEND_NULL | CSV_EMPTY_IS_NULL);
233+
csv_set_realloc_func(&p, GC_realloc);
234+
csv_set_free_func(&p, GC_free);
235+
do {
236+
size_t len = fread(buf, 1, buf_size, fin);
237+
if (len != buf_size && !feof(fin)) {
238+
csv_free(&p);
239+
fclose(fin);
240+
return NULL;
241+
}
242+
csv_parse(&p,buf,len,add_cell,add_row,&body);
243+
} while (!body.error && !feof(fin));
244+
csv_fini(&p,add_cell,add_row,&body);
245+
csv_free(&p);
246+
fclose(fin);
247+
if (body.error) {
248+
return NULL;
249+
}
250+
matrix_transpose(body.res,body.row_length,body.size);
251+
res->variables = variables;
252+
res->data = body.res;
253+
res->numvars = body.row_length;
254+
res->numsteps = body.size / body.row_length;
255+
/* printf("num vars %d in %s num steps %d\n", body.row_length, filename, res->numsteps); */
256+
return res;
257+
}
258+
259+
double* read_csv_dataset(struct csv_data *data, const char *var)
260+
{
261+
int i,found=-1;
262+
for (i=0; i<data->numvars; i++) {
263+
if (0==strcmp(data->variables[i],var)) {
264+
found=i;
265+
break;
266+
}
267+
}
268+
if (found == -1) {
269+
return NULL;
270+
}
271+
return data->data + i*data->numsteps;
272+
}
273+
274+
void omc_free_csv_reader(struct csv_data *data)
275+
{
276+
int i;
277+
for (i=0; i<data->numvars; i++) {
278+
GC_free(data->variables[i]);
279+
}
280+
GC_free(data->variables);
281+
GC_free(data->data);
282+
data->variables = 0;
283+
data->data = 0;
284+
GC_free(data);
285+
}

SimulationRuntime/c/util/read_csv.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,19 @@
3232
#ifndef OMC_READ_CSV_H
3333
#define OMC_READ_CSV_H
3434

35+
struct csv_data {
36+
char **variables;
37+
double *data;
38+
int numvars;
39+
int numsteps;
40+
};
41+
3542
int read_csv_dataset_size(const char* filename);
3643

3744
char** read_csv_variables(FILE *fin, int *length);
3845

39-
double* read_csv_dataset(const char *filename, const char *var, int dimsize);
46+
struct csv_data* read_csv(const char *filename);
47+
double* read_csv_dataset(struct csv_data *data, const char *var);
48+
void omc_free_csv_reader(struct csv_data *data);
4049

4150
#endif

SimulationRuntime/c/util/read_matlab4.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ double* omc_matlab4_read_vals(ModelicaMatReader *reader, int varIndex)
447447
return reader->vars[ix];
448448
}
449449

450-
static void transpose(double *m, int w, int h)
450+
void matrix_transpose(double *m, int w, int h)
451451
{
452452
int start, next, i;
453453
double tmp;
@@ -495,7 +495,7 @@ int omc_matlab4_read_all_vals(ModelicaMatReader *reader)
495495
tmp[i] = ((float*)tmp)[i];
496496
}
497497
}
498-
transpose(tmp,reader->nvar,reader->nrows);
498+
matrix_transpose(tmp,reader->nvar,reader->nrows);
499499
/* Negative aliases */
500500
for (i=0; i<reader->nrows*reader->nvar; i++) {
501501
tmp[reader->nrows*reader->nvar + i] = -tmp[i];

SimulationRuntime/c/util/read_matlab4.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ void omc_matlab4_print_all_vars(FILE *stream, ModelicaMatReader *reader);
6565
double omc_matlab4_startTime(ModelicaMatReader *reader);
6666

6767
double omc_matlab4_stopTime(ModelicaMatReader *reader);
68+
void matrix_transpose(double *m, int w, int h);
69+
6870
#ifdef __cplusplus
6971
} /* extern "C" */
7072
#endif

0 commit comments

Comments
 (0)