diff options
Diffstat (limited to 'libcrystfel')
-rw-r--r-- | libcrystfel/CMakeLists.txt | 3 | ||||
-rw-r--r-- | libcrystfel/meson.build | 5 | ||||
-rw-r--r-- | libcrystfel/src/image-hdf5.c | 11 | ||||
-rw-r--r-- | libcrystfel/src/image.c | 79 | ||||
-rw-r--r-- | libcrystfel/src/image.h | 10 | ||||
-rw-r--r-- | libcrystfel/src/index.c | 39 | ||||
-rw-r--r-- | libcrystfel/src/profile.c | 241 | ||||
-rw-r--r-- | libcrystfel/src/profile.h | 42 | ||||
-rw-r--r-- | libcrystfel/src/time-accounts.c | 265 | ||||
-rw-r--r-- | libcrystfel/src/time-accounts.h | 75 |
10 files changed, 376 insertions, 394 deletions
diff --git a/libcrystfel/CMakeLists.txt b/libcrystfel/CMakeLists.txt index 9aca17d8..3ca50b1f 100644 --- a/libcrystfel/CMakeLists.txt +++ b/libcrystfel/CMakeLists.txt @@ -62,7 +62,7 @@ set(LIBCRYSTFEL_SOURCES src/image-hdf5.c src/fom.c src/image-msgpack.c - src/time-accounts.c + src/profile.c ${BISON_symopp_OUTPUTS} ${FLEX_symopl_OUTPUTS} src/indexers/dirax.c @@ -100,6 +100,7 @@ set(LIBCRYSTFEL_HEADERS src/colscale.h src/detgeom.h src/fom.h + src/profile.h ) add_library(${PROJECT_NAME} SHARED diff --git a/libcrystfel/meson.build b/libcrystfel/meson.build index 780bdb77..b5005aa5 100644 --- a/libcrystfel/meson.build +++ b/libcrystfel/meson.build @@ -121,7 +121,7 @@ libcrystfel_sources = ['src/image.c', 'src/colscale.c', 'src/detgeom.c', 'src/fom.c', - 'src/time-accounts.c', + 'src/profile.c', 'src/image-cbf.c', 'src/image-hdf5.c', 'src/image-msgpack.c', @@ -180,8 +180,7 @@ install_headers(['src/reflist.h', 'src/datatemplate.h', 'src/colscale.h', 'src/detgeom.h', - 'src/fom.h', - 'src/time-accounts.h'], + 'src/fom.h'], subdir: 'crystfel') # API documentation (Doxygen) diff --git a/libcrystfel/src/image-hdf5.c b/libcrystfel/src/image-hdf5.c index fd16ac08..529420fb 100644 --- a/libcrystfel/src/image-hdf5.c +++ b/libcrystfel/src/image-hdf5.c @@ -42,6 +42,7 @@ #include "image.h" #include "utils.h" #include "detgeom.h" +#include "profile.h" #include "datatemplate.h" #include "datatemplate_priv.h" @@ -395,13 +396,16 @@ static int load_hdf5_hyperslab(struct panel_template *p, return 1; } + profile_start("H5Dopen2"); dh = H5Dopen2(fh, panel_full_path, H5P_DEFAULT); if ( dh < 0 ) { ERROR("Cannot open data for panel %s (%s)\n", p->name, panel_full_path); + profile_end("H5Dopen2"); free(panel_full_path); return 1; } + profile_end("H5Dopen2"); free(panel_full_path); @@ -509,7 +513,9 @@ static int load_hdf5_hyperslab(struct panel_template *p, return 1; } + profile_start("H5Dread"); r = H5Dread(dh, el_type, memspace, dataspace, H5P_DEFAULT, data); + profile_end("H5Dread"); if ( r < 0 ) { ERROR("Couldn't read data for panel %s\n", p->name); @@ -592,13 +598,16 @@ int image_hdf5_read(struct image *image, /* Set all pointers to NULL for easier clean-up */ for ( i=0; i<dtempl->n_panels; i++ ) image->dp[i] = NULL; + profile_start("open-hdf5"); fh = open_hdf5(image); + profile_end("open-hdf5"); if ( fh < 0 ) { ERROR("Failed to open file\n"); return 1; } for ( i=0; i<dtempl->n_panels; i++ ) { + profile_start("load-hdf5-hyperslab"); if ( load_hdf5_hyperslab(&dtempl->panels[i], fh, image->ev, (void *)&image->dp[i], H5T_NATIVE_FLOAT, @@ -606,9 +615,11 @@ int image_hdf5_read(struct image *image, dtempl->panels[i].data) ) { ERROR("Failed to load panel data\n"); + profile_end("load-hdf5-hyperslab"); close_hdf5(fh); return 1; } + profile_end("load-hdf5-hyperslab"); } close_hdf5(fh); diff --git a/libcrystfel/src/image.c b/libcrystfel/src/image.c index 7b86588d..2209ffee 100644 --- a/libcrystfel/src/image.c +++ b/libcrystfel/src/image.c @@ -42,7 +42,7 @@ #include "image-hdf5.h" #include "image-cbf.h" #include "image-msgpack.h" -#include "time-accounts.h" +#include "profile.h" #include "datatemplate.h" #include "datatemplate_priv.h" @@ -1287,49 +1287,67 @@ struct image *image_create_for_simulation(const DataTemplate *dtempl) static int do_image_read(struct image *image, const DataTemplate *dtempl, - int no_image_data, int no_mask_data, - TimeAccounts *taccs) + int no_image_data, int no_mask_data) { int i; + int r; /* Load the image data */ - time_accounts_set(taccs, TACC_IMAGE_DATA); if ( !no_image_data ) { - if ( image_read_image_data(image, dtempl) ) return 1; + int r; + profile_start("load-image-data"); + r = image_read_image_data(image, dtempl); + profile_end("load-image-data"); + if ( r ) return r; } else { - if ( image_set_zero_data(image, dtempl) ) return 1; + int r; + profile_start("set-zero-image-data"); + r = image_set_zero_data(image, dtempl); + profile_end("set-zero-image-data"); + if ( r ) return 1; } - time_accounts_set(taccs, TACC_IMAGE_PARAMS); - if ( set_image_parameters(image, dtempl) ) { + profile_start("set-image-parameters"); + r = set_image_parameters(image, dtempl); + profile_end("set-image-parameters"); + if ( r ) { ERROR("Failed to read image parameters\n"); return 1; } - time_accounts_set(taccs, TACC_CREATE_DETGEOM); - if ( create_detgeom(image, dtempl) ) { + + profile_start("create-detgeom"); + r = create_detgeom(image, dtempl); + profile_end("create-detgeom"); + if ( r ) { ERROR("Failed to read geometry information\n"); return 1; } - time_accounts_set(taccs, TACC_CREATE_BADMAP); - if ( create_badmap(image, dtempl, no_mask_data) ) return 1; - time_accounts_set(taccs, TACC_CREATE_SATMAP); - if ( create_satmap(image, dtempl) ) return 1; - time_accounts_set(taccs, TACC_CACHE_HEADERS); + profile_start("create-badmap"); + r = create_badmap(image, dtempl, no_mask_data); + profile_end("create-badmap"); + if ( r ) return 1; + + profile_start("create-satmap"); + r = create_satmap(image, dtempl); + profile_end("create-satmap"); + if ( r ) return 1; + + profile_start("read-headers-to-cache"); for ( i=0; i<dtempl->n_headers_to_copy; i++ ) { read_header_to_cache(image, dtempl->headers_to_copy[i]); } + profile_end("read-headers-to-cache"); return 0; } -struct image *image_read_with_time_accounting(const DataTemplate *dtempl, - const char *filename, - const char *event, - int no_image_data, - int no_mask_data, - TimeAccounts *taccs) +struct image *image_read(const DataTemplate *dtempl, + const char *filename, + const char *event, + int no_image_data, + int no_mask_data) { struct image *image; @@ -1355,7 +1373,7 @@ struct image *image_read_with_time_accounting(const DataTemplate *dtempl, image->data_source_type = file_type(image->filename); - if ( do_image_read(image, dtempl, no_image_data, no_mask_data, taccs) ) { + if ( do_image_read(image, dtempl, no_image_data, no_mask_data) ) { image_free(image); return NULL; } @@ -1364,26 +1382,13 @@ struct image *image_read_with_time_accounting(const DataTemplate *dtempl, } -struct image *image_read(const DataTemplate *dtempl, - const char *filename, - const char *event, - int no_image_data, - int no_mask_data) -{ - return image_read_with_time_accounting(dtempl, filename, event, - no_image_data, no_mask_data, - NULL); -} - - struct image *image_read_data_block(const DataTemplate *dtempl, void *data_block, size_t data_block_size, DataSourceType type, int serial, int no_image_data, - int no_mask_data, - TimeAccounts *taccs) + int no_mask_data) { struct image *image; char tmp[64]; @@ -1407,7 +1412,7 @@ struct image *image_read_data_block(const DataTemplate *dtempl, image->data_source_type = type; - if ( do_image_read(image, dtempl, no_image_data, no_mask_data, taccs) ) { + if ( do_image_read(image, dtempl, no_image_data, no_mask_data) ) { image_free(image); ERROR("Failed to load image\n"); return NULL; diff --git a/libcrystfel/src/image.h b/libcrystfel/src/image.h index 78fd01cd..3746e115 100644 --- a/libcrystfel/src/image.h +++ b/libcrystfel/src/image.h @@ -45,7 +45,6 @@ struct image; #include "index.h" #include "spectrum.h" #include "datatemplate.h" -#include "time-accounts.h" /** * \file image.h @@ -221,12 +220,6 @@ extern struct image *image_read(const DataTemplate *dtempl, const char *event, int no_image_data, int no_mask_data); -extern struct image *image_read_with_time_accounting(const DataTemplate *dtempl, - const char *filename, - const char *event, - int no_image_data, - int no_mask_data, - TimeAccounts *taccs); extern struct image *image_create_for_simulation(const DataTemplate *dtempl); extern struct image *image_read_data_block(const DataTemplate *dtempl, @@ -235,8 +228,7 @@ extern struct image *image_read_data_block(const DataTemplate *dtempl, DataSourceType type, int serial, int no_image_data, - int no_mask_data, - TimeAccounts *taccs); + int no_mask_data); extern void image_free(struct image *image); extern int image_read_header_float(struct image *image, const char *from, diff --git a/libcrystfel/src/index.c b/libcrystfel/src/index.c index e7b8b8cf..da560dab 100644 --- a/libcrystfel/src/index.c +++ b/libcrystfel/src/index.c @@ -49,6 +49,7 @@ #include "geometry.h" #include "cell-utils.h" #include "predict-refine.h" +#include "profile.h" #include "indexers/dirax.h" #include "indexers/asdf.h" #include "indexers/mosflm.h" @@ -604,47 +605,65 @@ static int try_indexer(struct image *image, IndexingMethod indm, case INDEXING_DIRAX : set_last_task(last_task, "indexing:dirax"); + profile_start("dirax"); r = run_dirax(image, mpriv); + profile_end("dirax"); break; case INDEXING_ASDF : set_last_task(last_task, "indexing:asdf"); + profile_start("asdf"); r = run_asdf(image, mpriv); + profile_end("asdf"); break; case INDEXING_MOSFLM : set_last_task(last_task, "indexing:mosflm"); + profile_start("mosflm"); r = run_mosflm(image, mpriv); + profile_end("mosflm"); break; case INDEXING_XDS : set_last_task(last_task, "indexing:xds"); + profile_start("xds"); r = run_xds(image, mpriv); + profile_end("xds"); break; case INDEXING_FILE : set_last_task(last_task, "indexing:file"); + profile_start("fromfile"); r = fromfile_index(image, mpriv); + profile_end("fromfile"); break; case INDEXING_FELIX : set_last_task(last_task, "indexing:felix"); + profile_start("felix"); r = felix_index(image, mpriv); + profile_end("felix"); break; case INDEXING_TAKETWO : set_last_task(last_task, "indexing:taketwo"); + profile_start("taketwo"); r = taketwo_index(image, mpriv); + profile_end("taketwo"); break; case INDEXING_PINKINDEXER : set_last_task(last_task, "indexing:pinkindexer"); + profile_start("pinkindexer"); r = run_pinkIndexer(image, mpriv, ipriv->n_threads); + profile_end("pinkindexer"); break; case INDEXING_XGANDALF : set_last_task(last_task, "indexing:xgandalf"); + profile_start("xgandalf"); r = run_xgandalf(image, mpriv); + profile_end("xgandalf"); break; default : @@ -670,6 +689,7 @@ static int try_indexer(struct image *image, IndexingMethod indm, for ( i=0; i<r; i++ ) { int j; + int r; int this_crystal = image->n_crystals - i - 1; /* ... starting at the end of the (complete) list ... */ @@ -680,9 +700,11 @@ static int try_indexer(struct image *image, IndexingMethod indm, crystal_set_mosaicity(cr, 0.0); /* Pre-refinement unit cell check if requested */ - if ( check_cell(ipriv->flags, cr, ipriv->target_cell, - ipriv->tolerance) ) - { + profile_start("prerefine-cell-check"); + r = check_cell(ipriv->flags, cr, ipriv->target_cell, + ipriv->tolerance); + profile_end("prerefine-cell-check"); + if ( r ) { crystal_set_user_flag(cr, 1); continue; } @@ -690,20 +712,27 @@ static int try_indexer(struct image *image, IndexingMethod indm, /* Prediction refinement if requested */ if ( ipriv->flags & INDEXING_REFINE ) { - if ( refine_prediction(image, cr) ) { + int r; + profile_start("refine"); + r = refine_prediction(image, cr); + profile_end("refine"); + if ( r ) { crystal_set_user_flag(cr, 1); continue; } } /* After refinement unit cell check if requested */ + profile_start("postrefine-cell-check"); if ( (ipriv->flags & INDEXING_CHECK_CELL) && !compare_cell_parameters(crystal_get_cell(cr), ipriv->target_cell, ipriv->tolerance) ) { + profile_end("postrefine-cell-check"); crystal_set_user_flag(cr, 1); continue; } + profile_end("postrefine-cell-check"); /* Peak alignment check if requested */ if ( ipriv->flags & INDEXING_CHECK_PEAKS ) @@ -719,6 +748,7 @@ static int try_indexer(struct image *image, IndexingMethod indm, if ( crystal_get_user_flag(cr) ) continue; /* Check if cell is too similar to existing ones */ + profile_start("cell-compare-to-others"); for ( j=0; j<this_crystal; j++ ) { Crystal *that_cr = image->crystals[j]; @@ -738,6 +768,7 @@ static int try_indexer(struct image *image, IndexingMethod indm, crystal_set_user_flag(cr, 1); } } + profile_end("cell-compare-to-others"); } diff --git a/libcrystfel/src/profile.c b/libcrystfel/src/profile.c new file mode 100644 index 00000000..f20e4b7e --- /dev/null +++ b/libcrystfel/src/profile.c @@ -0,0 +1,241 @@ +/* + * profile.c + * + * Simple profiling according to wall clock time + * + * Copyright © 2016-2022 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2016-2022 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 <unistd.h> + +#include "profile.h" + +#ifndef CLOCK_MONOTONIC_RAW +#define CLOCK_MONOTONIC_RAW (CLOCK_MONOTONIC) +#endif + +#define MAX_PROFILE_CHILDREN 32 + +struct _profile_block +{ + char *name; + + time_t start_sec; + long start_nsec; + double total_time; + + struct _profile_block *parent; + struct _profile_block *children[MAX_PROFILE_CHILDREN]; + int n_children; +}; + + +struct _profiledata +{ + struct _profile_block *root; + struct _profile_block *current; +}; + + +struct _profiledata *pd = NULL; + + +static struct _profile_block *start_profile_block(const char *name) +{ + struct _profile_block *b; + + b = malloc(sizeof(struct _profile_block)); + if ( b == NULL ) return NULL; + + b->name = strdup(name); + if ( b->name == NULL ) { + free(b); + return NULL; + } + b->n_children = 0; + +#ifdef HAVE_CLOCK_GETTIME + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp); + b->start_sec = tp.tv_sec; + b->start_nsec = tp.tv_nsec; +#endif + + return b; +} + + +static void stop_profile_block(struct _profile_block *b) +{ +#ifdef HAVE_CLOCK_GETTIME + struct timespec tp; + clock_gettime(CLOCK_MONOTONIC_RAW, &tp); + time_t sec = tp.tv_sec - b->start_sec; + long nsec = tp.tv_nsec - b->start_nsec; + b->total_time = sec + nsec*1e-9; +#else + b->total_time = 0.0; +#endif +} + + +void profile_init() +{ + if ( pd != NULL ) { + fprintf(stderr, "Attempted to initialise profiling twice!\n"); + fflush(stderr); + abort(); + } + + if ( pd == NULL ) { + pd = malloc(sizeof(struct _profiledata)); + if ( pd == NULL ) return; + } + + pd->root = start_profile_block("root"); + pd->current = pd->root; + pd->root->parent = NULL; + +#ifndef HAVE_CLOCK_GETTIME + printf("Profiling disabled because clock_gettime is not available\n"); +#endif +} + + +static char *format_profile_block(struct _profile_block *b) +{ + int i; + size_t total_len = 0; + char *subbufs[MAX_PROFILE_CHILDREN]; + char *full_buf; + + total_len = 32 + strlen(b->name); + for ( i=0; i<b->n_children; i++ ) { + subbufs[i] = format_profile_block(b->children[i]); + total_len += 1 + strlen(subbufs[i]); + } + + full_buf = malloc(total_len); + snprintf(full_buf, 32, "(%s %.3f", b->name, b->total_time); + for ( i=0; i<b->n_children; i++ ) { + strcat(full_buf, " "); + strcat(full_buf, subbufs[i]); + free(subbufs[i]); + } + strcat(full_buf, ")"); + + return full_buf; +} + + +static void free_profile_block(struct _profile_block *b) +{ + int i; + for ( i=0; i<b->n_children; i++ ) { + free_profile_block(b->children[i]); + } + free(b->name); + free(b); +} + + +void profile_print_and_reset() +{ + char *buf; + char *buf2; + + if ( pd == NULL ) { + fprintf(stderr, "Profiling not initialised yet!\n"); + fflush(stderr); + abort(); + } + + if ( pd->current != pd->root ) { + fprintf(stderr, "Attempted to finalise profiling while not " + "on root block (%s)\n", pd->current->name); + fflush(stderr); + abort(); + } + + stop_profile_block(pd->root); + + buf = format_profile_block(pd->root); + buf2 = malloc(2+strlen(buf)); + strcpy(buf2, buf); + strcat(buf2, "\n"); + write(STDOUT_FILENO, buf2, strlen(buf2)); + + free_profile_block(pd->root); + pd->root = start_profile_block("root"); + pd->current = pd->root; + pd->root->parent = NULL; +} + + +void profile_start(const char *name) +{ + struct _profile_block *b; + + if ( pd == NULL ) return; + + if ( pd->current->n_children >= MAX_PROFILE_CHILDREN ) { + fprintf(stderr, "Too many profile children.\n"); + fflush(stderr); + abort(); + } + + b = start_profile_block(name); + b->parent = pd->current; + pd->current->children[pd->current->n_children++] = b; + pd->current = b; +} + + +void profile_end(const char *name) +{ + if ( pd == NULL ) return; + + if ( pd->current == NULL ) { + fprintf(stderr, "No current profile block!\n"); + fflush(stderr); + abort(); + } + + if ( strcmp(name, pd->current->name) != 0 ) { + fprintf(stderr, "Attempt to close wrong profile block (%s) " + "current block is %s\n", name, pd->current->name); + fflush(stderr); + abort(); + } + + stop_profile_block(pd->current); + + pd->current = pd->current->parent; +} diff --git a/libcrystfel/src/profile.h b/libcrystfel/src/profile.h new file mode 100644 index 00000000..183528ce --- /dev/null +++ b/libcrystfel/src/profile.h @@ -0,0 +1,42 @@ +/* + * profile.h + * + * Simple profiling according to wall clock time + * + * Copyright © 2016-2022 Deutsches Elektronen-Synchrotron DESY, + * a research centre of the Helmholtz Association. + * + * Authors: + * 2016-2022 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 PROFILE_H +#define PROFILE_H + +/** + * \file profile.h + * Simple wall-clock profiling + */ + +extern void profile_init(); +extern void profile_print_and_reset(); +extern void profile_start(const char *name); +extern void profile_end(const char *name); + +#endif /* PROFILE_H */ diff --git a/libcrystfel/src/time-accounts.c b/libcrystfel/src/time-accounts.c deleted file mode 100644 index df2ccbb2..00000000 --- a/libcrystfel/src/time-accounts.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * 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; - -#ifndef HAVE_CLOCK_GETTIME - printf("Profiling disabled because clock_gettime is not available\n"); -#endif - - 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; - time_accounts_set(accs, accs->cur_acc); - 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 deleted file mode 100644 index 56b44fa6..00000000 --- a/libcrystfel/src/time-accounts.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 */ |