23#include <wx/textctrl.h>
24#include <wx/checkbox.h>
26#include <wx/stattext.h>
27#include <wx/stopwatch.h>
29#include <wx/valtext.h>
49#define SampleType short
50#define SampleFormat int16Sample
62 void OnRun( wxCommandEvent &event );
63 void OnSave( wxCommandEvent &event );
64 void OnClear( wxCommandEvent &event );
65 void OnClose( wxCommandEvent &event );
109 dlog.CentreOnParent();
141 wxDefaultPosition, wxDefaultSize,
142 wxDEFAULT_DIALOG_STYLE |
149 mBlockSizeStr =
wxT(
"64");
150 mNumEditsStr =
wxT(
"100");
151 mDataSizeStr =
wxT(
"32");
152 mRandSeedStr =
wxT(
"234657");
154 mBlockDetail =
false;
159 MakeBenchmarkDialog();
176 S.StartVerticalLay(
true);
179 S.StartMultiColumn(4);
183 .Validator<wxTextValidator>(wxFILTER_NUMERIC, &
mBlockSizeStr)
184 .AddTextBox(
XXO(
"Disk Block Size (KB):"),
190 .Validator<wxTextValidator>(wxFILTER_NUMERIC, &
mNumEditsStr)
191 .AddTextBox(
XXO(
"Number of Edits:"),
197 .Validator<wxTextValidator>(wxFILTER_NUMERIC, &
mDataSizeStr)
198 .AddTextBox(
XXO(
"Test Data Size (MB):"),
204 .Validator<wxTextValidator>(wxFILTER_NUMERIC, &
mRandSeedStr)
207 .AddTextBox(
XXO(
"Random Seed:"),
216 .AddCheckBox(
XXO(
"Show detailed info about each block file"),
221 .AddCheckBox(
XXO(
"Show detailed info about each editing operation"),
228 .Style( wxTE_MULTILINE | wxTE_READONLY | wxTE_RICH )
229 .MinSize( { 500, 200 } )
230 .AddTextWindow(
wxT(
""));
234 S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND,
false);
236 S.StartHorizontalLay(wxALIGN_LEFT,
false);
238 S.Id(
RunID).AddButton(
XXO(
"Run"), wxALIGN_CENTRE,
true);
243 S.EndHorizontalLay();
245 S.StartHorizontalLay(wxALIGN_CENTER,
true);
249 S.EndHorizontalLay();
251 S.StartHorizontalLay(wxALIGN_NOT | wxALIGN_LEFT,
false);
254 S.Id(wxID_CANCEL).AddButton(
XXO(
"Close"));
256 S.EndHorizontalLay();
258 S.EndHorizontalLay();
263 SetSizeHints(GetSize());
270 auto fName =
XO(
"benchmark.txt").Translation();
272 fName =
SelectFile(FileNames::Operation::Export,
273 XO(
"Export Benchmark Data as:"),
278 wxFD_SAVE | wxRESIZE_BORDER,
284 mText->SaveFile(fName);
294 auto s =
str.Translation();
321 TransferDataFromWindow();
328 long blockSize, numEdits, dataSize, randSeed;
335 if (blockSize < 1 || blockSize > 1024) {
337 XO(
"Block size should be in the range 1 - 1024 KB.") );
341 if (numEdits < 1 || numEdits > 10000) {
343 XO(
"Number of edits should be in the range 1 - 10000.") );
347 if (dataSize < 1 || dataSize > 2000) {
349 XO(
"Test data size should be in the range 1 - 2000 MB.") );
360 const auto cleanup =
finally( [&] {
380 uint64_t nChunks, chunkSize;
382 chunkSize = 200ull + (rand() % 100ull);
383 nChunks = (dataSize * 1048576ull) / (chunkSize*
sizeof(
SampleType));
384 while (nChunks < 20 || chunkSize > (blockSize*1024)/4)
386 chunkSize = std::max( uint64_t(1), (chunkSize / 2) + (rand() % 100) );
387 nChunks = (dataSize * 1048576ull) / (chunkSize*
sizeof(
SampleType));
394 Printf(
XO(
"Using %lld chunks of %lld samples each, for a total of %.1f MB.\n")
395 .
Format( nChunks, chunkSize, nChunks*chunkSize*
sizeof(
SampleType)/1048576.0 ) );
397 int trials = numEdits;
400 Samples small1{nChunks};
401 Samples block{chunkSize};
415 for (uint64_t i = 0; i < nChunks; i++) {
418 for (uint64_t b = 0; b < chunkSize; b++)
430 if (t->GetClip(0)->GetVisibleSampleCount() != nChunks * chunkSize) {
431 Printf(
XO(
"Expected len %lld, track len %lld.\n")
434 t->GetClip(0)->GetVisibleSampleCount()
444 for (z = 0; z < trials; z++) {
447 const uint64_t x0 = rand() % nChunks;
451 const uint64_t xlen = 1 + (rand() % (nChunks - x0));
454 .
Format( x0 * chunkSize, (x0 + xlen) * chunkSize) );
459 t->Cut(
double (x0 * chunkSize),
double ((x0 + xlen) * chunkSize));
463 Printf(
XO(
"Cut (%lld, %lld) failed.\n")
464 .
Format( (x0 * chunkSize), (x0 + xlen) * chunkSize) );
465 Printf(
XO(
"Expected len %lld, track len %lld.\n")
468 t->GetClip(0)->GetVisibleSampleCount()
475 const uint64_t y0 = rand() % (nChunks - xlen + 1);
481 t->Paste((
double)(y0 * chunkSize), *tmp);
488 if (t->GetClip(0)->GetVisibleSampleCount() != nChunks * chunkSize) {
490 Printf(
XO(
"Expected len %lld, track len %lld.\n")
493 t->GetClip(0)->GetVisibleSampleCount()
499 auto first = &small1[0];
500 if (x0 + xlen < nChunks)
501 std::rotate( first + x0, first + x0 + xlen, first + nChunks );
502 std::rotate( first + y0, first + nChunks - xlen, first + nChunks );
505 elapsed = timer.Time();
509 auto seq = t->GetClip(0)->GetSequence(0);
510 seq->DebugPrintf(seq->GetBlockArray(), seq->GetNumSamples(), &tempStr);
513 Printf(
XO(
"Time to perform %d edits: %ld ms\n").
Format( trials, elapsed ) );
519 Printf(
XO(
"Checking file pointer leaks:\n") );
520 Printf(
XO(
"Track # blocks: %ld\n").
Format( t->GetBlockArray()->size() ) );
522 system(
"ls .audacity_temp/* | wc --lines");
525 Printf(
XO(
"Doing correctness check...\n") );
531 for (uint64_t i = 0; i < nChunks; i++) {
533 auto pBlock =
reinterpret_cast<samplePtr>(block.get());
534 constexpr auto backwards =
false;
535 t->DoGet(0, 1, &pBlock,
SampleFormat, i * chunkSize, chunkSize, backwards);
536 for (uint64_t b = 0; b < chunkSize; b++)
545 Printf(
XO(
"Passed correctness check!\n") );
547 Printf(
XO(
"Errors in %d/%lld chunks\n").
Format( bad, nChunks ) );
549 elapsed = timer.Time();
551 Printf(
XO(
"Time to check all data: %ld ms\n").
Format( elapsed ) );
552 Printf(
XO(
"Reading data again...\n") );
559 for (uint64_t i = 0; i < nChunks; i++) {
561 auto pBlock =
reinterpret_cast<samplePtr>(block.get());
562 constexpr auto backwards =
false;
563 t->DoGet(0, 1, &pBlock,
SampleFormat, i * chunkSize, chunkSize, backwards);
564 for (uint64_t b = 0; b < chunkSize; b++)
569 elapsed = timer.Time();
571 Printf(
XO(
"Time to check all data (2): %ld ms\n").
Format( elapsed ) );
573 Printf(
XO(
"At 44100 Hz, %d bytes per sample, the estimated number of\n simultaneous tracks that could be played at once: %.1f\n" )
583 Printf(
XO(
"Benchmark completed successfully.\n") );
int AudacityMessageBox(const TranslatableString &message, const TranslatableString &caption, long style, wxWindow *parent, int x, int y)
void RunBenchmark(wxWindow *parent, AudacityProject &project)
EVT_BUTTON(wxID_NO, DependencyDialog::OnNo) EVT_BUTTON(wxID_YES
XXO("&Cut/Copy/Paste Toolbar")
an object holding per-project preferred sample rate
FilePath SelectFile(FileNames::Operation op, const TranslatableString &message, const FilePath &default_path, const FilePath &default_filename, const FileExtension &default_extension, const FileTypes &fileTypes, int flags, wxWindow *parent)
void DoProjectTempoChange(ChannelGroup &group, double newTempo)
BoolSetting EditClipsCanMove
This simplifies arrays of arrays, each array separately allocated with NEW[] But it might be better t...
Base class for exceptions specially processed by the application.
The top-level handle to an Audacity project. It serves as a source of events that other objects can b...
BenchmarkDialog is used for measuring performance and accuracy of sample block storage.
void OnClose(wxCommandEvent &event)
void OnSave(wxCommandEvent &event)
void HoldPrint(bool hold)
BenchmarkDialog(wxWindow *parent, AudacityProject &project)
void OnClear(wxCommandEvent &event)
AudacityProject & mProject
void Printf(const TranslatableString &str)
void MakeBenchmarkDialog()
void OnRun(wxCommandEvent &event)
const ProjectRate & mRate
FILES_API const FileType TextFiles
Holds project sample rate.
static ProjectRate & Get(AudacityProject &project)
static ProjectTimeSignature & Get(AudacityProject &project)
static SampleBlockFactoryPtr New(AudacityProject &project)
static void SetMaxDiskBlockSize(size_t bytes)
static size_t GetMaxDiskBlockSize()
bool Write(const T &value)
Write value to config and return true if successful.
Makes temporary changes to preferences, then rolls them back at destruction.
Derived from ShuttleGuiBase, an Audacity specific class for shuttling data to and from GUI.
std::shared_ptr< Track > Holder
static TrackListHolder Temporary(AudacityProject *pProject, const Track::Holder &pTrack={})
Holds a msgid for the translation catalog; may also bind format arguments.
Used to create or clone a WaveTrack, with appropriate context from the project that will own the trac...
static CommandContext::TargetFactory::SubstituteInUnique< InteractiveOutputTargets > scope
void rotate(const float *oldPhase, const float *newPhase, std::complex< float > *dst, int32_t n)