mirror of
https://github.com/Unidata/netcdf-c.git
synced 2024-12-15 08:30:11 +08:00
d2316f866c
Primary Fixes: * Add a whole variable optimization -- used in the rare case that nc_get/put_vara covers the whole of a variable and the variable has a single chunk. * Fix chunking error when stride causes whole chunks to be skipped. * Fix some memory leaks * Add test cases * Add one performance test to nczarr_test/. This uses the timer utils from unit_test: timer_utils.[ch]. * Move ncdumpchunks utility from ncdump to nczarr_test Misc. Other Changes: * Make check for aws libraries conditional on --enable-nczarr-s3 * Remove all but one bm tests from nczarr_test until they are working. * Remove another dependency on HDF5 from supposedly non-HDF5 specific code; specifically hdf5_log_hdf5. * Make the BAIL2 macro be hdf5 specific and replace elsewhere with an HDF5 independent equivalent. * Move hdf5cache.c to libsrc4/nc4cache.c because it is used by nczarr. * Modify unit_tests so that some of them are run even if using Windows. * Misc. small bug fixes and refactors and memory leaks. * Rename some conflicting tests for cmake. * Attempted to make nc_perf work with cmake and failed.
171 lines
4.1 KiB
C
171 lines
4.1 KiB
C
/*********************************************************************
|
|
* Copyright 2020, UCAR/Unidata
|
|
* See netcdf/COPYRIGHT file for copying and redistribution conditions.
|
|
*********************************************************************/
|
|
|
|
#include "config.h"
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#ifdef HAVE_TIME_H
|
|
#include <time.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_TIME_H
|
|
#include <sys/time.h>
|
|
#endif
|
|
#ifdef HAVE_SYS_RESOURCE_H
|
|
#include <sys/resource.h>
|
|
#endif
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
|
|
#include "timer_utils.h"
|
|
|
|
#undef DEBUG
|
|
|
|
static int NCT_initialized = 0;
|
|
|
|
#ifdef _WIN32
|
|
LARGE_INTEGER frequency;
|
|
LARGE_INTEGER starttime;
|
|
|
|
void
|
|
NCT_inittimer(void)
|
|
{
|
|
if(NCT_initialized) return;
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"timer mechanism: QueryPerformanceCounter\n");
|
|
#endif
|
|
LARGE_INTEGER li;
|
|
(void)QueryPerformanceFrequency(&frequency);
|
|
QueryPerformanceCounter(&starttime);
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"frequency=%lld starttime=%lld\n",frequency.QuadPart,starttime.QuadPart);
|
|
#endif
|
|
NCT_initialized = 1;
|
|
}
|
|
#else
|
|
void
|
|
NCT_inittimer(void)
|
|
{
|
|
if(NCT_initialized) return;
|
|
#ifdef DEBUG
|
|
#if defined HAVE_CLOCK_GETTIME
|
|
fprintf(stderr,"timer mechanism: clock_gettime\n");
|
|
#elif defined HAVE_GETTIMEOFDAY
|
|
fprintf(stderr,"timer mechanism: gettimeofday\n");
|
|
#elif defined HAVE_GETRUSAGE
|
|
fprintf(stderr,"timer mechanism: getrusage\n");
|
|
#else
|
|
fprintf(stderr,"timer mechanism: Unknown\n");
|
|
#endif
|
|
#endif /*DEBUG*/
|
|
NCT_initialized = 1;
|
|
}
|
|
#endif
|
|
|
|
void
|
|
NCT_marktime(Nanotime* nt)
|
|
{
|
|
#ifdef _WIN32
|
|
LARGE_INTEGER endtime;
|
|
QueryPerformanceCounter(&endtime);
|
|
nt->tv_sec = endtime.QuadPart / 1000000000;
|
|
nt->tv_nsec = endtime.QuadPart % 1000000000;
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"endtime=%lld\n",endtime.QuadPart);
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef _WIN32
|
|
/* Pick one */
|
|
#ifdef HAVE_CLOCK_GETTIME
|
|
clockid_t clk_id = CLOCK_MONOTONIC;
|
|
struct timespec t;
|
|
clock_gettime(clk_id,&t);
|
|
nt->tv_sec = (long long)t.tv_sec;
|
|
nt->tv_nsec = (long long)t.tv_nsec;
|
|
#elif defined HAVE_GETTIMEOFDAY
|
|
struct timeval tp;
|
|
gettimeofday(&tp, NULL);
|
|
nt->tv_sec = (long long)tp.tv_sec;
|
|
nt->tv_nsec = 1000*(long long)tp.tv_usec;
|
|
# elif defined HAVE_GETRUSAGE
|
|
struct rusage ru;
|
|
getrusage(RUSAGE_SELF, &ru);
|
|
nt->tv_sec = (long long)(ru.ru_utime.tv_sec + ru.ru_stime.tv_sec);
|
|
nt->tv_nsec = (long long)(1000*(ru.ru_utime.tv_usec + ru.ru_stime.tv_usec));
|
|
#endif
|
|
#endif
|
|
}
|
|
|
|
void
|
|
NCT_elapsedtime(Nanotime* nt0, Nanotime* nt1, Nanotime* delta)
|
|
{
|
|
long long nsec[2];
|
|
long long deltansec;
|
|
|
|
nsec[0] = nt0->tv_nsec+(1000000000 * nt0->tv_sec);
|
|
nsec[1] = nt1->tv_nsec+(1000000000 * nt1->tv_sec);
|
|
|
|
deltansec = nsec[1] - nsec[0];
|
|
delta->tv_nsec = deltansec % 1000000000;
|
|
delta->tv_sec = deltansec / 1000000000;
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"delta=(%lld,%lld)\n",delta->tv_sec,delta->tv_nsec);
|
|
#endif
|
|
}
|
|
|
|
int
|
|
NCT_reporttime(unsigned nelems, Nanotime* times, struct TimeRange range, const char* tag)
|
|
{
|
|
Nanotime delta;
|
|
long long nsec,avg;
|
|
double dnsec,dsec,davg;
|
|
|
|
NCT_elapsedtime(×[0],×[1],&delta);
|
|
nsec = NCT_nanoseconds(delta);
|
|
avg = nsec / nelems;
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"nsec=%lld avg=%lld\n",nsec,avg);
|
|
#endif
|
|
dnsec = (double)nsec;
|
|
dsec = dnsec / 1000000000.0;
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"dsec=%g dnsec=%g\n",dsec,dnsec);
|
|
#endif
|
|
davg = (dnsec/nelems);
|
|
fprintf(stderr,"\t%s:\t%8.6lf sec",tag,dsec);
|
|
fprintf(stderr," avg=%5.2lf nsec\n",davg);
|
|
#ifdef DEBUG
|
|
fprintf(stderr,"range: min=%lld max=%lld\n",range.min,range.max);
|
|
#endif
|
|
if(!NCT_rangetest(avg,range)) {
|
|
fprintf(stderr,"*** WARNING: unexpectedly large timing values%s\n",tag);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
long long
|
|
NCT_nanoseconds(Nanotime time)
|
|
{
|
|
return (time.tv_sec * 1000000000) + time.tv_nsec;
|
|
}
|
|
|
|
/* Provide a time range tester */
|
|
int
|
|
NCT_rangetest(long long nsec, struct TimeRange range)
|
|
{
|
|
if(nsec < range.min) {
|
|
fprintf(stderr,"range: time=%lld < min=%lld\n",nsec,range.min);
|
|
return 0;
|
|
}
|
|
if(nsec > range.max) {
|
|
fprintf(stderr,"range: time=%lld > max=%lld\n",nsec,range.max);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|