summaryrefslogtreecommitdiff
path: root/tools/sfrtest.cc
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2015-01-19 14:57:24 -0500
committerPaul Davis <paul@linuxaudiosystems.com>2015-01-19 14:57:24 -0500
commitf1a59e5373c844d34acbc1c7eabbc75b23a77e54 (patch)
treed4449fa4186ad99e77a742f438ee19060a590c8a /tools/sfrtest.cc
parentae7b978b0ba26f911e50bc3cbd50cc9455c94fad (diff)
new read tester for investigating read bandwidth issues
Diffstat (limited to 'tools/sfrtest.cc')
-rw-r--r--tools/sfrtest.cc167
1 files changed, 167 insertions, 0 deletions
diff --git a/tools/sfrtest.cc b/tools/sfrtest.cc
new file mode 100644
index 0000000000..8a1d715007
--- /dev/null
+++ b/tools/sfrtest.cc
@@ -0,0 +1,167 @@
+/* g++ -o sfrtest sfrtest.cc `pkg-config --cflags --libs sndfile` `pkg-config --cflags --libs glibmm-2.4` */
+
+#include <vector>
+#include <iostream>
+#include <iomanip>
+#include <sstream>
+#include <cstdlib>
+#include <cerrno>
+
+#include <unistd.h>
+#include <sndfile.h>
+#include <stdint.h>
+#include <string.h>
+#include <getopt.h>
+#include <fcntl.h>
+
+#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
+
+using namespace std;
+
+SF_INFO format_info;
+float* data = 0;
+bool with_sync = false;
+
+int
+read_one (SNDFILE* sf, uint32_t nframes)
+{
+ if (sf_read_float (sf, (float*) data, nframes) != nframes) {
+ return -1;
+ }
+
+ if (with_sync) {
+ sf_write_sync (sf);
+ }
+
+ return 0;
+}
+
+void
+usage ()
+{
+ cout << "sfrtest [ -n NFILES ] [ -b BLOCKSIZE ] [ -s ] [ -D ] filename-template" << endl;
+}
+
+int
+main (int argc, char* argv[])
+{
+ vector<SNDFILE*> sndfiles;
+ uint32_t sample_size;
+ char optstring[] = "n:b:s";
+ uint32_t block_size = 64 * 1024;
+ uint32_t nfiles = 100;
+ bool direct = false;
+ const struct option longopts[] = {
+ { "nfiles", 1, 0, 'n' },
+ { "blocksize", 1, 0, 'b' },
+ { "sync", 0, 0, 's' },
+ { "direct", 0, 0, 'D' },
+ { 0, 0, 0, 0 }
+ };
+
+ int option_index = 0;
+ int c = 0;
+ char const * name_template = 0;
+ int samplerate;
+
+ while (1) {
+ if ((c = getopt_long (argc, argv, optstring, longopts, &option_index)) == -1) {
+ break;
+ }
+
+ switch (c) {
+ case 'n':
+ nfiles = atoi (optarg);
+ break;
+ case 'b':
+ block_size = atoi (optarg);
+ break;
+ case 's':
+ with_sync = true;
+ break;
+ case 'D':
+ direct = true;
+ break;
+ default:
+ usage ();
+ return 0;
+ }
+ }
+
+ if (optind < argc) {
+ name_template = argv[optind];
+ } else {
+ usage ();
+ return 1;
+ }
+
+ for (uint32_t n = 1; n <= nfiles; ++n) {
+ SNDFILE* sf;
+ char path[PATH_MAX+1];
+
+ snprintf (path, sizeof (path), name_template, n);
+
+ if (!Glib::file_test (path, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_REGULAR)) {
+ break;
+ }
+
+ int flags = O_RDONLY;
+ int fd = open (path, flags, 0644);
+
+ if (fd < 0) {
+ cerr << "Could not open file #" << n << " @ " << path << " (" << strerror (errno) << ")" << endl;
+ return 1;
+ }
+
+#ifdef __APPLE__
+ if (direct) {
+ /* Apple man pages say only that it returns "a value other than -1 on success",
+ which probably means zero, but you just can't be too careful with
+ those guys.
+ */
+ if (fcntl (fd, F_NOCACHE, 1) == -1) {
+ cerr << "Cannot set F_NOCACHE on file # " << n << endl;
+ }
+ }
+#endif
+
+ if ((sf = sf_open_fd (fd, SFM_READ, &format_info, true)) == 0) {
+ cerr << "Could not open SNDFILE #" << n << " @ " << path << " (" << sf_strerror (0) << ")" << endl;
+ return 1;
+ }
+
+ samplerate = format_info.samplerate;
+
+ sndfiles.push_back (sf);
+ }
+
+ cout << "Discovered " << nfiles+1 << " files using " << name_template << endl;
+
+ data = new float[block_size];
+ uint64_t read = 0;
+
+ while (true) {
+ gint64 before;
+ before = g_get_monotonic_time();
+ for (vector<SNDFILE*>::iterator s = sndfiles.begin(); s != sndfiles.end(); ++s) {
+ if (read_one (*s, block_size)) {
+ cerr << "Read failed for file #" << distance (sndfiles.begin(), s) << endl;
+ return 1;
+ }
+ }
+ read += block_size;
+ gint64 elapsed = g_get_monotonic_time() - before;
+ double bandwidth = (sndfiles.size() * block_size * sample_size) / (elapsed/1000000.0);
+ double data_minutes = read / (double) (60.0 * 48000.0);
+ const double data_rate = sndfiles.size() * sample_size * samplerate;
+ stringstream ds;
+ ds << setprecision (1) << data_minutes;
+
+ cout << "BW @ " << read << " frames (" << ds.str() << " minutes) = " << (bandwidth/1048576.0) << " MB/sec " << bandwidth / data_rate << " x faster than necessary " << endl;
+ }
+
+ return 0;
+}
+
+