aboutsummaryrefslogtreecommitdiff
path: root/libcrystfel/src
diff options
context:
space:
mode:
Diffstat (limited to 'libcrystfel/src')
-rw-r--r--libcrystfel/src/time-accounts.c260
-rw-r--r--libcrystfel/src/time-accounts.h75
2 files changed, 335 insertions, 0 deletions
diff --git a/libcrystfel/src/time-accounts.c b/libcrystfel/src/time-accounts.c
new file mode 100644
index 00000000..773debeb
--- /dev/null
+++ b/libcrystfel/src/time-accounts.c
@@ -0,0 +1,260 @@
+/*
+ * time-accounts.c
+ *
+ * Simple profiling according to wall clock time
+ *
+ * Copyright © 2016-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2016-2018 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <libcrystfel-config.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+
+#include "time-accounts.h"
+
+#define MAX_ACCOUNTS 256
+
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW (CLOCK_MONOTONIC)
+#endif
+
+struct _timeaccounts
+{
+ enum timeaccount accs[MAX_ACCOUNTS];
+ time_t sec[MAX_ACCOUNTS];
+ long nsec[MAX_ACCOUNTS];
+ int n_accs;
+ enum timeaccount cur_acc;
+ time_t cur_sec;
+ long cur_nsec;
+};
+
+
+TimeAccounts *time_accounts_init()
+{
+ TimeAccounts *accs = malloc(sizeof(struct _timeaccounts));
+ if ( accs == NULL ) return NULL;
+
+ accs->n_accs = 0;
+ accs->cur_acc = TACC_NOTHING;
+
+ return accs;
+}
+
+
+void time_accounts_free(TimeAccounts *accs)
+{
+ free(accs);
+}
+
+
+static int find_account(TimeAccounts *accs, enum timeaccount acc)
+{
+ int i;
+
+ for ( i=0; i<accs->n_accs; i++ ) {
+ if ( accs->accs[i] == acc ) return i;
+ }
+
+ if ( i == MAX_ACCOUNTS ) {
+ static int warned_toomany = 0;
+ if ( !warned_toomany ) printf("Too many time accounts used!\n");
+ warned_toomany = 1;
+ return MAX_ACCOUNTS;
+ }
+
+ /* This is the first time the account is used */
+ accs->accs[i] = acc;
+ accs->sec[i] = 0;
+ accs->nsec[i] = 0;
+ accs->n_accs++;
+ return i;
+}
+
+
+void time_accounts_reset(TimeAccounts *accs)
+{
+ accs->n_accs = 0;
+ accs->cur_acc = TACC_NOTHING;
+}
+
+
+#ifdef HAVE_CLOCK_GETTIME
+
+void time_accounts_set(TimeAccounts *accs, enum timeaccount new_acc)
+{
+ struct timespec tp;
+
+ if ( accs == NULL ) return;
+
+ clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
+
+ /* Record time used on the previous account */
+ if ( accs->cur_acc != TACC_NOTHING ) {
+ int i = find_account(accs, accs->cur_acc);
+ if ( i == MAX_ACCOUNTS ) {
+ printf("Too many time accounts!\n");
+ } else {
+
+ time_t sec = tp.tv_sec - accs->cur_sec;
+ long nsec = tp.tv_nsec - accs->cur_nsec;
+
+ if ( nsec < 0 ) {
+ sec -= 1;
+ nsec += 1000000000;
+ }
+ accs->sec[i] += sec;
+ accs->nsec[i] += nsec;
+
+ while ( accs->nsec[i] > 1000000000 ) {
+ accs->sec[i] += 1;
+ accs->nsec[i] -= 1000000000;
+ }
+
+ }
+ }
+
+ accs->cur_acc = new_acc;
+ accs->cur_sec = tp.tv_sec;
+ accs->cur_nsec = tp.tv_nsec;
+}
+
+#else
+
+void time_accounts_set(TimeAccounts *accs, enum timeaccount new_acc)
+{
+ if ( accs == NULL ) return;
+
+ /* Record time used on the previous account */
+ if ( accs->cur_acc != TACC_NOTHING ) {
+ int i = find_account(accs, accs->cur_acc);
+ if ( i == MAX_ACCOUNTS ) {
+ printf("Too many time accounts!\n");
+ } else {
+ /* Do nothing because we have no timer */
+ }
+ }
+
+ accs->cur_acc = new_acc;
+ accs->cur_sec = 0;
+ accs->cur_nsec = 0;
+}
+
+#endif
+
+static const char *taccname(enum timeaccount acc)
+{
+ switch ( acc ) {
+ case TACC_NOTHING : return "Nothing";
+ case TACC_SELECT : return "select()";
+ case TACC_STREAMREAD : return "Stream read";
+ case TACC_SIGNALS : return "Checking signals";
+ case TACC_QUEUETOPUP : return "Topping up queue";
+ case TACC_STATUS : return "Printing status";
+ case TACC_ENDCHECK : return "Checking end";
+ case TACC_WAKEUP : return "Waking up workers";
+ case TACC_WAITPID : return "Waiting on workers";
+ case TACC_WAITFILE : return "Waiting for image file";
+ case TACC_IMAGE_DATA : return "Reading image data";
+ case TACC_IMAGE_PARAMS : return "Reading image parameters";
+ case TACC_CREATE_DETGEOM : return "Creating detgeom";
+ case TACC_CREATE_BADMAP : return "Creating bad pixel map";
+ case TACC_CREATE_SATMAP : return "Creating saturation map";
+ case TACC_CACHE_HEADERS : return "Caching image headers";
+ case TACC_FILTER : return "Image filters";
+ case TACC_RESRANGE : return "Resolution range";
+ case TACC_PEAKSEARCH : return "Peak search";
+ case TACC_INDEXING : return "Indexing";
+ case TACC_PREDPARAMS : return "Prediction parameters";
+ case TACC_INTEGRATION : return "Integration";
+ case TACC_TOTALS : return "Crystal totals";
+ case TACC_WRITESTREAM : return "Writing stream";
+ case TACC_CLEANUP : return "Image cleanup";
+ case TACC_EVENTWAIT : return "Waiting for event";
+ case TACC_FINALCLEANUP : return "Final cleanup";
+ default : return "Unknown";
+ }
+}
+
+
+static const char *taccname_short(enum timeaccount acc)
+{
+ switch ( acc ) {
+ case TACC_NOTHING : return "?????";
+ case TACC_SELECT : return "selct";
+ case TACC_STREAMREAD : return "sread";
+ case TACC_SIGNALS : return "signs";
+ case TACC_QUEUETOPUP : return "qfill";
+ case TACC_STATUS : return "print";
+ case TACC_ENDCHECK : return "endch";
+ case TACC_WAKEUP : return "wakew";
+ case TACC_WAITPID : return "waitw";
+ case TACC_WAITFILE : return "wfile";
+ case TACC_IMAGE_DATA : return "idata";
+ case TACC_IMAGE_PARAMS : return "iprms";
+ case TACC_CREATE_DETGEOM : return "dgeom";
+ case TACC_CREATE_BADMAP : return "bdmap";
+ case TACC_CREATE_SATMAP : return "stmap";
+ case TACC_CACHE_HEADERS : return "headc";
+ case TACC_FILTER : return "filtr";
+ case TACC_RESRANGE : return "rrnge";
+ case TACC_PEAKSEARCH : return "peaks";
+ case TACC_INDEXING : return "index";
+ case TACC_PREDPARAMS : return "predp";
+ case TACC_INTEGRATION : return "integ";
+ case TACC_TOTALS : return "ctotl";
+ case TACC_WRITESTREAM : return "swrte";
+ case TACC_CLEANUP : return "clean";
+ case TACC_EVENTWAIT : return "wevnt";
+ case TACC_FINALCLEANUP : return "final";
+ default : return "unkwn";
+ }
+}
+
+
+void time_accounts_print_short(TimeAccounts *accs)
+{
+ int i;
+ for ( i=0; i<accs->n_accs; i++ ) {
+ printf("%s: %.3f ", taccname_short(accs->accs[i]),
+ (double)accs->sec[i] + accs->nsec[i]/1e9);
+ }
+ printf("\n");
+ fflush(stdout);
+}
+
+
+void time_accounts_print(TimeAccounts *accs)
+{
+ int i;
+ printf("Wall clock time budget:\n");
+ printf("-----------------------\n");
+ for ( i=0; i<accs->n_accs; i++ ) {
+ printf("%25s: %10lli sec %10li nsec\n", taccname(accs->accs[i]),
+ (long long)accs->sec[i], accs->nsec[i]);
+ }
+}
diff --git a/libcrystfel/src/time-accounts.h b/libcrystfel/src/time-accounts.h
new file mode 100644
index 00000000..56b44fa6
--- /dev/null
+++ b/libcrystfel/src/time-accounts.h
@@ -0,0 +1,75 @@
+/*
+ * time-accounts.h
+ *
+ * Simple profiling according to wall clock time
+ *
+ * Copyright © 2016-2021 Deutsches Elektronen-Synchrotron DESY,
+ * a research centre of the Helmholtz Association.
+ *
+ * Authors:
+ * 2016-2018 Thomas White <taw@physics.org>
+ *
+ * This file is part of CrystFEL.
+ *
+ * CrystFEL is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * CrystFEL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with CrystFEL. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TIME_ACCOUNTS_H
+#define TIME_ACCOUNTS_H
+
+enum timeaccount
+{
+ TACC_NOTHING,
+ TACC_STREAMREAD,
+ TACC_SELECT,
+ TACC_SIGNALS,
+ TACC_QUEUETOPUP,
+ TACC_STATUS,
+ TACC_ENDCHECK,
+ TACC_WAKEUP,
+ TACC_WAITPID,
+ TACC_WAITFILE,
+ TACC_IMAGE_DATA,
+ TACC_IMAGE_PARAMS,
+ TACC_CREATE_DETGEOM,
+ TACC_CREATE_BADMAP,
+ TACC_CREATE_SATMAP,
+ TACC_CACHE_HEADERS,
+ TACC_FILTER,
+ TACC_RESRANGE,
+ TACC_PEAKSEARCH,
+ TACC_INDEXING,
+ TACC_PREDPARAMS,
+ TACC_INTEGRATION,
+ TACC_TOTALS,
+ TACC_WRITESTREAM,
+ TACC_CLEANUP,
+ TACC_EVENTWAIT,
+ TACC_FINALCLEANUP,
+};
+
+typedef struct _timeaccounts TimeAccounts;
+
+extern TimeAccounts *time_accounts_init(void);
+extern void time_accounts_free(TimeAccounts *accs);
+
+extern void time_accounts_set(TimeAccounts *accs, enum timeaccount new_acc);
+
+extern void time_accounts_reset(TimeAccounts *accs);
+
+extern void time_accounts_print_short(TimeAccounts *accs);
+extern void time_accounts_print(TimeAccounts *accs);
+
+#endif /* TIME_ACCOUNTS_H */