From dea2eb23262c32395c30363d615fda3b80499b84 Mon Sep 17 00:00:00 2001 From: nick_m Date: Fri, 13 Feb 2015 02:36:51 +1100 Subject: [PATCH] Cache the calculated peaks. Interestingly, keeping the last peakfile read around (staging) seems to "wind up" the vm cache on linux nicely. Don't use 8 times the amount of needed memory (!). Restore the waveview cache to previous size for comparison to master. Works very well for scrolling regions whose source length is less than the screen width at current zoom. Tested on a large session with 72% cpu load (while playing. --- libs/ardour/ardour/audiosource.h | 2 + libs/ardour/audiosource.cc | 77 ++++++++++++++++++-------------- libs/canvas/wave_view.cc | 2 +- 3 files changed, 47 insertions(+), 34 deletions(-) diff --git a/libs/ardour/ardour/audiosource.h b/libs/ardour/ardour/audiosource.h index 511500da28..07cb8ba3ec 100644 --- a/libs/ardour/ardour/audiosource.h +++ b/libs/ardour/ardour/audiosource.h @@ -169,7 +169,9 @@ class LIBARDOUR_API AudioSource : virtual public Source, mutable uint32_t _last_map_off; mutable size_t _last_raw_map_length; mutable bool _first_run; + mutable double _last_scale; mutable boost::scoped_array staging; + mutable boost::scoped_array peak_cache; }; } diff --git a/libs/ardour/audiosource.cc b/libs/ardour/audiosource.cc index a4a74c86b1..52dbec7dd6 100644 --- a/libs/ardour/audiosource.cc +++ b/libs/ardour/audiosource.cc @@ -80,6 +80,7 @@ AudioSource::AudioSource (Session& s, string name) , peak_leftover_size (0) , peak_leftovers (0) , _first_run (true) + , _last_scale (0.0) { } @@ -93,6 +94,7 @@ AudioSource::AudioSource (Session& s, const XMLNode& node) , peak_leftover_size (0) , peak_leftovers (0) , _first_run (true) + , _last_scale (0.0) { if (set_state (node, Stateful::loading_state_version)) { throw failed_constructor(); @@ -397,9 +399,9 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t size_t raw_map_length = bytes_to_read; size_t map_length = bytes_to_read + map_delta; - if (_first_run || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) { - - staging.reset (new PeakData[raw_map_length]); + if (_first_run || (_last_map_off != map_off) || (_last_scale != samples_per_visual_peak) || (_last_raw_map_length < raw_map_length)) { + peak_cache.reset (new PeakData[npeaks]); + staging.reset (new PeakData[npeaks]); //posix_fadvise (sfd, read_map_off, map_length, POSIX_FADV_WILLNEED); @@ -409,19 +411,21 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t return -1; } - memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length * sizeof(PeakData)); + memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length); munmap (addr, map_length); + memcpy ((void*)peak_cache.get(), (void*)staging.get(), bytes_to_read); + _last_map_off = map_off; _last_raw_map_length = raw_map_length; _first_run = false; + + if (zero_fill) { + memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill); + } + } - - memcpy ((void*)peaks, (void*)staging.get(), bytes_to_read); - - if (zero_fill) { - memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill); - } - + _last_scale = samples_per_visual_peak; + memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData)); return 0; } @@ -461,49 +465,56 @@ AudioSource::read_peaks_with_fpp (PeakData *peaks, framecnt_t npeaks, framepos_t size_t raw_map_length = chunksize * sizeof(PeakData); size_t map_length = (chunksize * sizeof(PeakData)) + map_delta; - if (_first_run || (_last_map_off != map_off) || (_last_raw_map_length < raw_map_length)) { - + if (_first_run || (_last_map_off != map_off) || (_last_scale != samples_per_visual_peak) || (_last_raw_map_length < raw_map_length)) { + peak_cache.reset (new PeakData[npeaks]); staging.reset (new PeakData[chunksize]); //posix_fadvise (sfd, read_map_off, map_length, POSIX_FADV_WILLNEED); - char* addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off); + char* addr; + addr = (char*) mmap (0, map_length, PROT_READ, MAP_PRIVATE, sfd, read_map_off); if (addr == MAP_FAILED) { cerr << "mmap error - could not map peak file to mem." << endl; return -1; } - memcpy ((void*)staging.get(), (void*)(addr + map_delta), chunksize * sizeof(PeakData)); + memcpy ((void*)staging.get(), (void*)(addr + map_delta), raw_map_length); munmap (addr, map_length); + _last_map_off = map_off; _last_raw_map_length = raw_map_length; _first_run = false; - } - while (nvisual_peaks < npeaks) { + _last_scale = samples_per_visual_peak; + + while (nvisual_peaks < npeaks) { - xmax = -1.0; - xmin = 1.0; + xmax = -1.0; + xmin = 1.0; - while (current_stored_peak <= stored_peak_before_next_visual_peak) { + while (current_stored_peak <= stored_peak_before_next_visual_peak) { - xmax = max (xmax, staging[i].max); - xmin = min (xmin, staging[i].min); - ++i; - ++current_stored_peak; + xmax = max (xmax, staging[i].max); + xmin = min (xmin, staging[i].min); + ++i; + ++current_stored_peak; + } + + peak_cache[nvisual_peaks].max = xmax; + peak_cache[nvisual_peaks].min = xmin; + ++nvisual_peaks; + next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak)); + stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak; } - peaks[nvisual_peaks].max = xmax; - peaks[nvisual_peaks].min = xmin; - ++nvisual_peaks; - next_visual_peak_frame = min ((double) start + cnt, (next_visual_peak_frame + samples_per_visual_peak)); - stored_peak_before_next_visual_peak = (uint32_t) next_visual_peak_frame / samples_per_file_peak; - } + if (zero_fill) { + cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl; + memset (&peak_cache[npeaks], 0, sizeof (PeakData) * zero_fill); + } - if (zero_fill) { - cerr << "Zero fill end of peaks (@ " << npeaks << " with " << zero_fill << endl; - memset (&peaks[npeaks], 0, sizeof (PeakData) * zero_fill); } + memcpy ((void*)peaks, (void*)peak_cache.get(), npeaks * sizeof(PeakData)); + return 0; } else { DEBUG_TRACE (DEBUG::Peaks, "UPSAMPLE\n"); diff --git a/libs/canvas/wave_view.cc b/libs/canvas/wave_view.cc index 8a5e6f32c9..9c4ae778fe 100644 --- a/libs/canvas/wave_view.cc +++ b/libs/canvas/wave_view.cc @@ -42,7 +42,7 @@ using namespace std; using namespace ARDOUR; using namespace ArdourCanvas; -#define CACHE_HIGH_WATER (3) +#define CACHE_HIGH_WATER (2) std::map , std::vector > WaveView::_image_cache; double WaveView::_global_gradient_depth = 0.6;