/** * Return the timestamp as string in ISO date/time * ("yyyy-mm-ddThh:mm:ssZ") format. If the timestamp is invalid, an * empty string will be returned. */ std::string to_iso() const { std::string s; if (m_timestamp != 0) { struct tm tm; time_t sse = seconds_since_epoch(); #ifndef NDEBUG auto result = #endif #ifndef _MSC_VER gmtime_r(&sse, &tm); assert(result != nullptr); #else gmtime_s(&tm, &sse); assert(result == 0); #endif s.resize(timestamp_length); /* This const_cast is ok, because we know we have enough space in the string for the format we are using (well at least until the year will have 5 digits). And by setting the size afterwards from the result of strftime we make sure thats set right, too. */ s.resize(strftime(const_cast<char*>(s.c_str()), timestamp_length, timestamp_format(), &tm)); } return s; }
int main(int argc, char* argv[]) { char* filename = argv[1]; off_t disk_size_in_bytes = disksize(filename); int i; double start_time, end_time; unsigned long sector_size = sectorsize(filename); long disk_size_in_sectors = disk_size_in_bytes / sector_size; int transfer_size_in_sectors = 1; // Probably doesn't make any sense to be anything other than 1. Except maybe 64 or 128. long transfer_size_in_bytes = transfer_size_in_sectors * sector_size; // TODO: initial random I/O test to determine number of repetitions based on random I/O rate. Or just stop after a certain elapsed time! int repetitions = 1000; struct timeval seed; // Scaling factor for the random numbers, to ensure that the sector chosen actually lies within the range of sectors on the disk. double block_scaling_factor = (double)MAX_RAND_INT / (double)disk_size_in_sectors; //fprintf(stderr, "block scaling factor = %f\n", block_scaling_factor); // Seed the RNG from the current time to avoid repetitive I/O patterns (and possible cache effects) across multiple runs: gettimeofday(&seed, NULL); srandom(seed.tv_usec); // char* buf = malloc(transfer_size_in_bytes); void* buf; int memalign_status = posix_memalign(&buf, 512, transfer_size_in_bytes); if (memalign_status != 0) { perror("Error allocating aligned buffer memory."); exit(EXIT_FAILURE); } int fd = diskbench_open(filename); off_t sector = 0; double elapsed_time_in_seconds = 0; fprintf(stderr, "\nAbout to perform random access test on %s\n\n", filename); fprintf(stderr, "Disk size: %lli GiB\n", disk_size_in_bytes / 1024 / 1024 / 1024); fprintf(stderr, " %lli MiB\n", disk_size_in_bytes / 1024 / 1024); fprintf(stderr, " %lli kiB\n", disk_size_in_bytes / 1024); fprintf(stderr, " %jd bytes\n", (intmax_t)disk_size_in_bytes); fprintf(stderr, " %li %lu-byte sectors\n\n", disk_size_in_sectors, sector_size); // Heading for output: fprintf(stderr, "sector\tbyte\tfraction\ttime(ms)\trate(MiB/s)\n"); for (i = 0; i < repetitions; i++) { sector = random() / block_scaling_factor; // Sector being sought: printf("%lli", sector); // Byte being sought: printf("\t%lli", sector * (long long int)sector_size); // Location as a fraction of the entire drive space: printf("\t%f", (double)sector / (double)disk_size_in_sectors); // Check the system time before doing the operation: start_time = seconds_since_epoch(); // Note: fseek() location is in bytes. lseek(fd, sector * (long)sector_size, SEEK_SET); // Does it make any difference if we only read one byte, rather than the whole block? read(fd, buf, transfer_size_in_bytes); // Record the time after finishing to determine elapsed time. end_time = seconds_since_epoch(); elapsed_time_in_seconds = end_time - start_time; // printf("; elapsed = %i s", time1.tv_sec - time0.tv_sec); printf("\t"); // Print elapsed time in milliseconds: printf("%f", elapsed_time_in_seconds * 1000.0); // printf("%f", 1000 * ((double)(time1.tv_sec - time0.tv_sec) + (double)(time1.tv_nsec - time0.tv_nsec) / 1000000000)); // Print throughput in MiB/s: printf("\t"); printf("%f", (double)transfer_size_in_bytes / elapsed_time_in_seconds / 1024.0 / 1024.0); printf("\n"); //printf("; time=%i, %i\n", (time1->tv_sec) - (time0->tv_sec), (time1->tv_nsec) - (time0->tv_nsec)); } free(buf); close(fd); return 0; }