gint profile(double* time_usr, double* time_sys, double* memory, double* correctness, gint suiteSize, gint isStd){ double tusr=0, tsys=0, correctness_t=0; double stdTime=0; gint stdMemory=0; gint memory_new_one=0; double memory_new=0; allRequestPeak=0; noe=0; gchar* line; gchar* filename=g_malloc(128*sizeof(gchar)); gchar* append=g_malloc(8*sizeof(gchar)); if(isStd) g_snprintf(append, 32, ".s"); else append[0]='\0'; gint i, j, k, length=g_list_length(testcases); //gint fullTest=1; gint* testSuite=g_malloc0(length*sizeof(gint)); double* testResults=g_malloc0(length*sizeof(double)); gint* testMemory=g_malloc0(length*sizeof(gint)); gint flippedSize, index; FILE* resultsFile; if(isStd>0 || suiteSize<=0 || suiteSize>length){ suiteSize=length; for(i=0; i<suiteSize; i++){ testSuite[i]=1; } } else{ // randomly sample testcases if(suiteSize>length/2){ flippedSize=length-suiteSize; } else{ flippedSize=suiteSize; } index=0; for(i=0; i<flippedSize; i++){ j=g_rand_int_range(randomUtility, 1, length+1-i); while(j>0){ index++; if(index>=length){ index-=length; } if(testSuite[index]==0){ j--; } } testSuite[index]=1; } if(flippedSize!=suiteSize){ for(i=0; i<length; i++){ testSuite[i]=1-testSuite[i]; } } } // read testResults file if(!isStd){ g_snprintf(filename, 128, "%stestResults.txt", CURRDIR); resultsFile=fopen(filename, "r"); for(i=0; i<length; i++){ fgets(filename, 128, resultsFile); sscanf(filename, "%lf\t%d", &testResults[i], &testMemory[i]); if(testSuite[i]){ stdTime+=testResults[i]; stdMemory+=testMemory[i]; } } fclose(resultsFile); } // clean the output files for(i=0; i<length; i++){ g_snprintf(filename, 128, "%sout%d%s", CURRDIR, i, append); if(g_file_test(filename, G_FILE_TEST_EXISTS)){ g_remove(filename); } } line=g_malloc(512*sizeof(gchar)); gchar **cmdv=NULL; gint pid, mpid; FILE *mfp; tusr=0; tsys=0; double tmp_double; gint tmp_int, timeout=1; struct rusage usage; struct timespec sleepUnit; sleepUnit.tv_sec=0; sleepUnit.tv_nsec=SLEEP_UNIT*1000; gint stdEvalTimes; if(isStd){ stdEvalTimes=STD_EVALUATION_TIMES; } else{ stdEvalTimes=1; } for(k=0; k<stdEvalTimes; k++){ for(i=0; i<length; i++){ if(testSuite[i]==0){ continue; } j=i; g_snprintf(filename, 128, "%sout%d%s", CURRDIR, j, append); g_snprintf(line, 512, "subject %s%s", TESTCASEDIR, (char*)g_list_nth_data(testcases, j)); g_shell_parse_argv(line, NULL, &cmdv, NULL); if((pid=fork())<0){ g_printf("fork() for subject execution failed.\n"); exit(0); } if(pid==0){ if(g_freopen(filename, "w", stdout)==NULL) perror("redirect to file failed."); g_snprintf(filename, 128, "%sprocMemory%d", CURRDIR, j); if(g_freopen(filename, "w", stderr)==NULL) perror("redirect stderr to file failed."); execv("subject", cmdv); fprintf(logfp, "execv() failed.\n"); fflush(logfp); exit(0); } g_strfreev(cmdv); // parent process, wait for pid if(isStd){ wait4(pid, &tmp_int, 0, &usage); } else{ timeout=(gint)(timeout_sec*1000000/SLEEP_UNIT); while(timeout>0 && wait4(pid, &tmp_int, WNOHANG, &usage)==0){ timeout--; nanosleep(&sleepUnit, NULL); } if(timeout<=0){ kill(pid, SIGKILL); waitpid(pid, &tmp_int, 0); break; } } #ifdef CUSTOM_EXTRA_SAVING CUSTOM_EXTRA_SAVING; #endif //g_spawn_close_pid(pid); memory_new_one=readProcMemory(j); if(isStd && k==0){ testMemory[i]=memory_new_one; } memory_new+=memory_new_one; tmp_double=usage.ru_utime.tv_sec+(usage.ru_utime.tv_usec)/(double)1000000; if(isStd){ testResults[i]+=tmp_double; } tusr+=tmp_double; tmp_double=usage.ru_stime.tv_sec+(usage.ru_stime.tv_usec)/(double)1000000; if(isStd){ testResults[i]+=tmp_double; } tsys+=tmp_double; // when the total execution time exceeds time limit, directly return if(isStd==0){ g_snprintf(filename, 128, "%sout%d", CURRDIR, j); g_snprintf(line, 128, "%sout%d.s", CURRDIR, j); if(cmpOutput(filename, line) || tusr+tsys>timeout_sec){ timeout=-1; break; } } } } // cmp the output and summarise the correctness if(timeout<=0){ correctness_t=i+1; } else{ tusr/=stdEvalTimes; tsys/=stdEvalTimes; memory_new/=stdEvalTimes; if(isStd==0){ #ifdef CUSTOM_CORRECTNESS CUSTOM_CORRECTNESS; #else for(i=0; i<length; i++){ if(testSuite[i]==0){ continue; } g_snprintf(filename, 128, "%sout%d", CURRDIR, i); g_snprintf(line, 128, "%sout%d.s", CURRDIR, i); correctness_t+=cmpOutput(filename, line); } #endif tusr/=stdTime; tsys/=stdTime; memory_new/=stdMemory; } else{ g_snprintf(filename, 128, "%stestResults.txt", CURRDIR); resultsFile=fopen(filename, "w+"); for(i=0; i<length; i++){ g_fprintf(resultsFile, "%lf\t%d\n", testResults[i]/stdEvalTimes, testMemory[i]); } fclose(resultsFile); memory_new/=1024; } } g_free(filename); g_free(append); g_snprintf(line, 128, "%lf %lf %lf %lf\n", tusr, tsys, memory_new, correctness_t); gint lineLength=strlen(line); write(STDOUT_FILENO, line, lineLength); //g_printf("%d\n", allRequestPeak/stdEvalTimes); g_free(line); g_free(testSuite); g_free(testResults); g_free(testMemory); *time_usr=tusr; *time_sys=tsys; *memory=memory_new/(double)1024; *correctness=correctness_t; return 0; }
int main(int argc, char *argv[]) { #ifdef _WIN32 // on Windows we have a hard time showing stuff printed to stdout/stderr to the user. // because of that we write it to a log file. char datetime[20]; dt_gettime(datetime, sizeof(datetime)); // make sure to not redirect output when the output is already being redirected, either to a file or a pipe. int out_type = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)); int err_type = GetFileType(GetStdHandle(STD_ERROR_HANDLE)); gboolean redirect_output = ((out_type != FILE_TYPE_DISK && out_type != FILE_TYPE_PIPE) && (err_type != FILE_TYPE_DISK && err_type != FILE_TYPE_PIPE)); for(int k = 1; k < argc; k++) { // For simple arguments do not redirect stdout if(!strcmp(argv[k], "--help") || !strcmp(argv[k], "-h") || !strcmp(argv[k], "/?") || !strcmp(argv[k], "--version")) { redirect_output = FALSE; break; } } if(redirect_output) { // something like C:\Users\username\AppData\Local\Microsoft\Windows\Temporary Internet Files\darktable\darktable-log.txt char *logdir = g_build_filename(g_get_user_cache_dir(), "darktable", NULL); char *logfile = g_build_filename(logdir, "darktable-log.txt", NULL); g_mkdir_with_parents(logdir, 0700); g_freopen(logfile, "a", stdout); dup2(fileno(stdout), fileno(stderr)); // We don't need the console window anymore, free it // This ensures that only darktable's main window will be visible FreeConsole(); g_free(logdir); g_free(logfile); // don't buffer stdout/stderr. we have basically two options: unbuffered or line buffered. // unbuffered keeps the order in which things are printed but concurrent threads printing can lead to intermangled output. ugly. // line buffered should keep lines together but in my tests the order of things no longer matches. ugly and potentially confusing. // thus we are doing the thing that is just ugly (in rare cases) but at least not confusing. setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); printf("========================================\n"); printf("version: %s\n", darktable_package_string); printf("start: %s\n", datetime); printf("\n"); } #endif if(dt_init(argc, argv, TRUE, TRUE, NULL)) exit(1); dt_gui_gtk_run(darktable.gui); #ifdef _WIN32 if(redirect_output) { dt_gettime(datetime, sizeof(datetime)); printf("\n"); printf("end: %s\n", datetime); printf("========================================\n"); printf("\n"); } #endif exit(0); }