mirror of
https://github.com/cookiengineer/audacity
synced 2026-02-06 03:32:09 +01:00
Locate and position the current Audacity source code, and clear a variety of old junk out of the way into junk-branches
This commit is contained in:
552
src/Benchmark.cpp
Normal file
552
src/Benchmark.cpp
Normal file
@@ -0,0 +1,552 @@
|
||||
/**********************************************************************
|
||||
|
||||
Audacity: A Digital Audio Editor
|
||||
|
||||
Benchmark.cpp
|
||||
|
||||
Dominic Mazzoni
|
||||
|
||||
*******************************************************************//**
|
||||
|
||||
\class BenchmarkDialog
|
||||
\brief BenchmarkDialog is used for measuring performance and accuracy
|
||||
of the BlockFile system.
|
||||
|
||||
*//*******************************************************************/
|
||||
|
||||
|
||||
#include "Audacity.h"
|
||||
|
||||
#include <wx/log.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/filedlg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/timer.h>
|
||||
#include <wx/utils.h>
|
||||
#include <wx/valgen.h>
|
||||
#include <wx/valtext.h>
|
||||
#include <wx/intl.h>
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "Project.h"
|
||||
#include "WaveTrack.h"
|
||||
#include "Sequence.h"
|
||||
#include "Prefs.h"
|
||||
|
||||
#include "FileDialog.h"
|
||||
|
||||
class BenchmarkDialog: public wxDialog
|
||||
{
|
||||
public:
|
||||
// constructors and destructors
|
||||
BenchmarkDialog( wxWindow *parent );
|
||||
|
||||
void MakeBenchmarkDialog();
|
||||
|
||||
private:
|
||||
// WDR: handler declarations
|
||||
void OnRun( wxCommandEvent &event );
|
||||
void OnSave( wxCommandEvent &event );
|
||||
void OnClear( wxCommandEvent &event );
|
||||
void OnClose( wxCommandEvent &event );
|
||||
|
||||
void Printf(const wxChar *format, ...);
|
||||
void HoldPrint(bool hold);
|
||||
void FlushPrint();
|
||||
|
||||
bool mHoldPrint;
|
||||
wxString mToPrint;
|
||||
|
||||
wxString mBlockSizeStr;
|
||||
wxString mDataSizeStr;
|
||||
wxString mNumEditsStr;
|
||||
wxString mRandSeedStr;
|
||||
|
||||
bool mBlockDetail;
|
||||
bool mEditDetail;
|
||||
|
||||
wxTextCtrl *mText;
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
void RunBenchmark(wxWindow *parent)
|
||||
{
|
||||
/*
|
||||
int action = wxMessageBox(wxT("This will close all project windows "
|
||||
"(without saving)\n"
|
||||
"and open the Audacity Benchmark dialog.\n\n"
|
||||
"Are you sure you want to do this?"),
|
||||
wxT("Benchmark"),
|
||||
wxYES_NO | wxICON_EXCLAMATION,
|
||||
NULL);
|
||||
|
||||
if (action != wxYES)
|
||||
return;
|
||||
|
||||
CloseAllProjects();
|
||||
*/
|
||||
|
||||
BenchmarkDialog dlog(parent);
|
||||
|
||||
dlog.CentreOnParent();
|
||||
|
||||
dlog.ShowModal();
|
||||
}
|
||||
|
||||
//
|
||||
// BenchmarkDialog
|
||||
//
|
||||
|
||||
enum {
|
||||
RunID = 1000,
|
||||
BSaveID,
|
||||
ClearID,
|
||||
StaticTextID,
|
||||
BlockSizeID,
|
||||
DataSizeID,
|
||||
NumEditsID,
|
||||
RandSeedID
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(BenchmarkDialog,wxDialog)
|
||||
EVT_BUTTON( RunID, BenchmarkDialog::OnRun )
|
||||
EVT_BUTTON( BSaveID, BenchmarkDialog::OnSave )
|
||||
EVT_BUTTON( ClearID, BenchmarkDialog::OnClear )
|
||||
EVT_BUTTON( wxID_CANCEL, BenchmarkDialog::OnClose )
|
||||
END_EVENT_TABLE()
|
||||
|
||||
BenchmarkDialog::BenchmarkDialog(wxWindow *parent):
|
||||
wxDialog( parent, 0, wxT("Benchmark"),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxDEFAULT_DIALOG_STYLE |
|
||||
wxRESIZE_BORDER)
|
||||
{
|
||||
mBlockSizeStr = wxT("64");
|
||||
mNumEditsStr = wxT("100");
|
||||
mDataSizeStr = wxT("32");
|
||||
mRandSeedStr = wxT("234657");
|
||||
|
||||
mBlockDetail = false;
|
||||
mEditDetail = false;
|
||||
|
||||
HoldPrint(false);
|
||||
|
||||
MakeBenchmarkDialog();
|
||||
}
|
||||
|
||||
// WDR: handler implementations for BenchmarkDialog
|
||||
|
||||
void BenchmarkDialog::OnClose(wxCommandEvent &event)
|
||||
{
|
||||
EndModal(0);
|
||||
}
|
||||
|
||||
void BenchmarkDialog::MakeBenchmarkDialog()
|
||||
{
|
||||
ShuttleGui S(this, eIsCreating);
|
||||
wxControl *item;
|
||||
|
||||
// Strings don't need to be translated because this class doesn't
|
||||
// ever get used in a stable release.
|
||||
|
||||
S.StartVerticalLay(true);
|
||||
{
|
||||
S.SetBorder(8);
|
||||
S.StartMultiColumn(4);
|
||||
{
|
||||
//
|
||||
item = S.Id(BlockSizeID).AddTextBox(wxT("Disk Block Size (KB):"),
|
||||
wxT(""),
|
||||
12);
|
||||
item->SetValidator(wxTextValidator(wxFILTER_NUMERIC,
|
||||
&mBlockSizeStr));
|
||||
|
||||
//
|
||||
item = S.Id(NumEditsID).AddTextBox(wxT("Number of Edits:"),
|
||||
wxT(""),
|
||||
12);
|
||||
item->SetValidator(wxTextValidator(wxFILTER_NUMERIC,
|
||||
&mNumEditsStr));
|
||||
|
||||
//
|
||||
item = S.Id(DataSizeID).AddTextBox(wxT("Test Data Size (MB):"),
|
||||
wxT(""),
|
||||
12);
|
||||
item->SetValidator(wxTextValidator(wxFILTER_NUMERIC,
|
||||
&mDataSizeStr));
|
||||
|
||||
///
|
||||
item = S.Id(RandSeedID).AddTextBox(wxT("Random Seed:"),
|
||||
wxT(""),
|
||||
12);
|
||||
item->SetValidator(wxTextValidator(wxFILTER_NUMERIC,
|
||||
&mRandSeedStr));
|
||||
|
||||
}
|
||||
S.EndMultiColumn();
|
||||
|
||||
//
|
||||
item = S.AddCheckBox(wxT("Show detailed info about each block file"),
|
||||
wxT("false"));
|
||||
item->SetValidator(wxGenericValidator(&mBlockDetail));
|
||||
|
||||
//
|
||||
item = S.AddCheckBox(wxT("Show detailed info about each editing operation"),
|
||||
wxT("false"));
|
||||
item->SetValidator(wxGenericValidator(&mEditDetail));
|
||||
|
||||
//
|
||||
mText = S.Id(StaticTextID).AddTextWindow(wxT(""));
|
||||
mText->SetName(wxT("Output"));
|
||||
mText->SetSizeHints(wxSize(500,200));
|
||||
|
||||
//
|
||||
S.SetBorder(10);
|
||||
S.StartHorizontalLay(wxALIGN_LEFT | wxEXPAND, false);
|
||||
{
|
||||
S.StartHorizontalLay(wxALIGN_LEFT, false);
|
||||
{
|
||||
S.Id(RunID).AddButton(wxT("Run"))->SetDefault();
|
||||
S.Id(BSaveID).AddButton(wxT("Save"));
|
||||
S.Id(ClearID).AddButton(wxT("Clear"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxALIGN_CENTER, true);
|
||||
{
|
||||
// Spacer
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
|
||||
S.StartHorizontalLay(wxALIGN_RIGHT, false);
|
||||
{
|
||||
S.Id(wxID_CANCEL).AddButton(wxT("Close"));
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndHorizontalLay();
|
||||
}
|
||||
S.EndVerticalLay();
|
||||
|
||||
Fit();
|
||||
SetSizeHints(GetSize());
|
||||
}
|
||||
|
||||
void BenchmarkDialog::OnSave( wxCommandEvent &event )
|
||||
{
|
||||
wxString fName = wxT("benchmark.txt");
|
||||
|
||||
fName = FileSelector(wxT("Export Benchmark Data As:"),
|
||||
NULL, fName, wxT("txt"), wxT("*.txt"), wxFD_SAVE | wxRESIZE_BORDER, this);
|
||||
|
||||
if (fName == wxT(""))
|
||||
return;
|
||||
|
||||
mText->SaveFile(fName);
|
||||
}
|
||||
|
||||
void BenchmarkDialog::OnClear(wxCommandEvent &event)
|
||||
{
|
||||
mText->Clear();
|
||||
}
|
||||
|
||||
void BenchmarkDialog::Printf(const wxChar *format, ...)
|
||||
{
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
|
||||
wxString s = wxString::FormatV(format, argptr);
|
||||
mToPrint += s;
|
||||
if (!mHoldPrint)
|
||||
FlushPrint();
|
||||
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
void BenchmarkDialog::HoldPrint(bool hold)
|
||||
{
|
||||
mHoldPrint = hold;
|
||||
|
||||
if (!mHoldPrint)
|
||||
FlushPrint();
|
||||
}
|
||||
|
||||
void BenchmarkDialog::FlushPrint()
|
||||
{
|
||||
while(mToPrint.Length() > 100) {
|
||||
mText->AppendText(mToPrint.Left(100));
|
||||
mToPrint = mToPrint.Right(mToPrint.Length() - 100);
|
||||
}
|
||||
if (mToPrint.Length() > 0)
|
||||
mText->AppendText(mToPrint);
|
||||
mToPrint = wxT("");
|
||||
}
|
||||
|
||||
void BenchmarkDialog::OnRun( wxCommandEvent &event )
|
||||
{
|
||||
TransferDataFromWindow();
|
||||
|
||||
if (!Validate())
|
||||
return;
|
||||
|
||||
// This code will become part of libaudacity,
|
||||
// and this class will be phased out.
|
||||
long blockSize, numEdits, dataSize, randSeed;
|
||||
|
||||
mBlockSizeStr.ToLong(&blockSize);
|
||||
mNumEditsStr.ToLong(&numEdits);
|
||||
mDataSizeStr.ToLong(&dataSize);
|
||||
mRandSeedStr.ToLong(&randSeed);
|
||||
|
||||
if (blockSize < 1 || blockSize > 1024) {
|
||||
wxMessageBox(wxT("Block size should be in the range 1 - 1024 KB."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (numEdits < 1 || numEdits > 10000) {
|
||||
wxMessageBox(wxT("Number of edits should be in the range 1 - 10000."));
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataSize < 1 || dataSize > 2000) {
|
||||
wxMessageBox(wxT("Test data size should be in the range 1 - 2000 MB."));
|
||||
return;
|
||||
}
|
||||
|
||||
bool editClipCanMove = true;
|
||||
gPrefs->Read(wxT("/GUI/EditClipCanMove"), &editClipCanMove);
|
||||
gPrefs->Write(wxT("/GUI/EditClipCanMove"), false);
|
||||
|
||||
// Rememebr the old blocksize, so that we can restore it later.
|
||||
int oldBlockSize = Sequence::GetMaxDiskBlockSize();
|
||||
Sequence::SetMaxDiskBlockSize(blockSize * 1024);
|
||||
|
||||
wxBusyCursor busy;
|
||||
|
||||
HoldPrint(true);
|
||||
|
||||
DirManager *d = new DirManager();
|
||||
TrackFactory *fact = new TrackFactory(d);
|
||||
WaveTrack *t = fact->NewWaveTrack(int16Sample);
|
||||
Track *tmp = NULL;
|
||||
|
||||
t->SetRate(1);
|
||||
|
||||
srand(randSeed);
|
||||
|
||||
int nChunks, chunkSize;
|
||||
//chunkSize = 7500 + (rand() % 1000);
|
||||
chunkSize = 200 + (rand() % 100);
|
||||
nChunks = (dataSize * 1048576) / (chunkSize*sizeof(short));
|
||||
while(nChunks < 20 || chunkSize > (blockSize*1024)/4) {
|
||||
chunkSize = (chunkSize / 2) + (rand() % 100);
|
||||
nChunks = (dataSize * 1048576) / (chunkSize*sizeof(short));
|
||||
}
|
||||
|
||||
// The chunks are the pieces we move around in the test.
|
||||
// They are (and are supposed to be) a different size to
|
||||
// the blocks that make the blockfiles. That way we get to
|
||||
// do some testing of when edit chunks cross blockfile boundaries.
|
||||
Printf(wxT("Using %d chunks of %d samples each, for a total of ")
|
||||
wxT("%.1f MB.\n"),
|
||||
nChunks, chunkSize, nChunks*chunkSize*sizeof(short)/1048576.0);
|
||||
|
||||
int trials = numEdits;
|
||||
|
||||
short *small1 = new short[nChunks];
|
||||
short *small2 = new short[nChunks];
|
||||
short *block = new short[chunkSize];
|
||||
|
||||
Printf(wxT("Preparing...\n"));
|
||||
|
||||
wxYield();
|
||||
FlushPrint();
|
||||
|
||||
int i, b, v;
|
||||
int bad;
|
||||
int z;
|
||||
long elapsed;
|
||||
wxString tempStr;
|
||||
wxStopWatch timer;
|
||||
|
||||
for (i = 0; i < nChunks; i++) {
|
||||
v = short(rand());
|
||||
small1[i] = v;
|
||||
for (b = 0; b < chunkSize; b++)
|
||||
block[b] = v;
|
||||
|
||||
t->Append((samplePtr)block, int16Sample, chunkSize);
|
||||
}
|
||||
t->Flush();
|
||||
|
||||
// This forces the WaveTrack to flush all of the appends (which is
|
||||
// only necessary if you want to access the Sequence class directly,
|
||||
// as we're about to do).
|
||||
t->GetEndTime();
|
||||
|
||||
if (t->GetClipByIndex(0)->GetSequence()->GetNumSamples() != (sampleCount)nChunks * chunkSize) {
|
||||
Printf(wxT("Expected len %d, track len %d.\n"), nChunks * chunkSize,
|
||||
t->GetClipByIndex(0)->GetSequence()->GetNumSamples());
|
||||
goto fail;
|
||||
}
|
||||
//t->Debug();
|
||||
|
||||
Printf(wxT("Performing %d edits...\n"), trials);
|
||||
wxYield();
|
||||
FlushPrint();
|
||||
|
||||
timer.Start();
|
||||
for (z = 0; z < trials; z++) {
|
||||
int x0 = rand() % nChunks;
|
||||
int xlen = 1 + (rand() % (nChunks - x0));
|
||||
if (mEditDetail)
|
||||
Printf(wxT("Cut: %d - %d \n"), x0 * chunkSize, (x0 + xlen) * chunkSize);
|
||||
|
||||
t->Cut(double (x0 * chunkSize), double ((x0 + xlen) * chunkSize), &tmp);
|
||||
if (!tmp) {
|
||||
Printf(wxT("Trial %d\n"), z);
|
||||
Printf(wxT("Cut (%d, %d) failed.\n"), (x0 * chunkSize),
|
||||
(x0 + xlen) * chunkSize);
|
||||
Printf(wxT("Expected len %d, track len %d.\n"), nChunks * chunkSize,
|
||||
t->GetClipByIndex(0)->GetSequence()->GetNumSamples());
|
||||
goto fail;
|
||||
}
|
||||
|
||||
int y0 = rand() % (nChunks - xlen);
|
||||
if (mEditDetail)
|
||||
Printf(wxT("Paste: %d\n"), y0 * chunkSize);
|
||||
|
||||
t->Paste(double (y0 * chunkSize), tmp);
|
||||
|
||||
if (t->GetClipByIndex(0)->GetSequence()->GetNumSamples() != (sampleCount) nChunks * chunkSize) {
|
||||
Printf(wxT("Trial %d\n"), z);
|
||||
Printf(wxT("Expected len %d, track len %d.\n"), nChunks * chunkSize,
|
||||
t->GetClipByIndex(0)->GetSequence()->GetNumSamples());
|
||||
goto fail;
|
||||
}
|
||||
// Copy
|
||||
for (i = 0; i < xlen; i++)
|
||||
small2[i] = small1[x0 + i];
|
||||
// Delete
|
||||
for (i = 0; i < (nChunks - x0 - xlen); i++)
|
||||
small1[x0 + i] = small1[x0 + xlen + i];
|
||||
// Insert
|
||||
for (i = 0; i < (nChunks - xlen - y0); i++)
|
||||
small1[nChunks - i - 1] = small1[nChunks - i - 1 - xlen];
|
||||
// Paste
|
||||
for (i = 0; i < xlen; i++)
|
||||
small1[y0 + i] = small2[i];
|
||||
}
|
||||
|
||||
elapsed = timer.Time();
|
||||
|
||||
if (mBlockDetail) {
|
||||
t->GetClipByIndex(0)->GetSequence()->DebugPrintf(&tempStr);
|
||||
mToPrint += tempStr;
|
||||
}
|
||||
Printf(wxT("Time to perform %d edits: %ld ms\n"), trials, elapsed);
|
||||
FlushPrint();
|
||||
wxYield();
|
||||
|
||||
|
||||
#if 0
|
||||
Printf(wxT("Checking file pointer leaks:\n"));
|
||||
Printf(wxT("Track # blocks: %d\n"), t->GetBlockArray()->Count());
|
||||
Printf(wxT("Disk # blocks: \n"));
|
||||
system("ls .audacity_temp/* | wc --lines");
|
||||
#endif
|
||||
|
||||
Printf(wxT("Doing correctness check...\n"));
|
||||
FlushPrint();
|
||||
wxYield();
|
||||
|
||||
bad = 0;
|
||||
timer.Start();
|
||||
for (i = 0; i < nChunks; i++) {
|
||||
v = small1[i];
|
||||
t->Get((samplePtr)block, int16Sample, i * chunkSize, chunkSize);
|
||||
for (b = 0; b < chunkSize; b++)
|
||||
if (block[b] != v) {
|
||||
bad++;
|
||||
if (bad < 10)
|
||||
Printf(wxT("Bad: chunk %d sample %d\n"), i, b);
|
||||
b = chunkSize;
|
||||
}
|
||||
}
|
||||
if (bad == 0)
|
||||
Printf(wxT("Passed correctness check!\n"));
|
||||
else
|
||||
Printf(wxT("Errors in %d/%d chunks\n"), bad, nChunks);
|
||||
|
||||
elapsed = timer.Time();
|
||||
|
||||
Printf(wxT("Time to check all data: %ld ms\n"), elapsed);
|
||||
Printf(wxT("Reading data again...\n"));
|
||||
|
||||
wxYield();
|
||||
FlushPrint();
|
||||
|
||||
timer.Start();
|
||||
|
||||
for (i = 0; i < nChunks; i++) {
|
||||
v = small1[i];
|
||||
t->Get((samplePtr)block, int16Sample, i * chunkSize, chunkSize);
|
||||
for (b = 0; b < chunkSize; b++)
|
||||
if (block[b] != v)
|
||||
bad++;
|
||||
}
|
||||
|
||||
elapsed = timer.Time();
|
||||
|
||||
Printf(wxT("Time to check all data (2): %ld ms\n"), elapsed);
|
||||
|
||||
Printf(wxT("At 44100 Hz, 16-bits per sample, the estimated number of\n")
|
||||
wxT("simultaneous tracks that could be played at once: %.1f\n"),
|
||||
(nChunks*chunkSize/44100.0)/(elapsed/1000.0));
|
||||
|
||||
goto success;
|
||||
|
||||
fail:
|
||||
Printf(wxT("TEST FAILED!!!\n"));
|
||||
|
||||
success:
|
||||
if (tmp)
|
||||
delete tmp;
|
||||
|
||||
delete t;
|
||||
|
||||
delete[]small1;
|
||||
delete[]small2;
|
||||
delete[]block;
|
||||
|
||||
delete fact;
|
||||
d->Deref();
|
||||
|
||||
Sequence::SetMaxDiskBlockSize(oldBlockSize);
|
||||
HoldPrint(false);
|
||||
|
||||
gPrefs->Write(wxT("/GUI/EditClipCanMove"), editClipCanMove);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Indentation settings for Vim and Emacs and unique identifier for Arch, a
|
||||
// version control system. Please do not modify past this point.
|
||||
//
|
||||
// Local Variables:
|
||||
// c-basic-offset: 3
|
||||
// indent-tabs-mode: nil
|
||||
// End:
|
||||
//
|
||||
// vim: et sts=3 sw=3
|
||||
// arch-tag: 79fba2fd-f170-46cb-a781-8dca643f7cf4
|
||||
|
||||
Reference in New Issue
Block a user