mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
RideCache load performance improvement
.. string manipulation using raw C since its simple character replacement, halved time over previous approach. .. lookup rideitem in ridecache via binary search (lower_bound) rather than serial. Minor speed up. .. Overall, loading should be noticeably quicker for most users.
This commit is contained in:
@@ -58,7 +58,6 @@
|
||||
|
||||
Athlete::Athlete(Context *context, const QDir &homeDir)
|
||||
{
|
||||
fprintf(stderr, "new athlete preamble...\n"); fflush(stderr);
|
||||
// athlete name / structured directory
|
||||
this->home = new AthleteDirectoryStructure(homeDir);
|
||||
this->context = context;
|
||||
|
||||
@@ -124,12 +124,12 @@ RideCache::RideCache(Context *context) : context(context)
|
||||
}
|
||||
}
|
||||
|
||||
// now sort it - we need to use find on it
|
||||
qSort(rides_.begin(), rides_.end(), rideCacheLessThan);
|
||||
|
||||
// load the store - will unstale once cache restored
|
||||
load();
|
||||
|
||||
// now sort it
|
||||
qSort(rides_.begin(), rides_.end(), rideCacheLessThan);
|
||||
|
||||
// set model once we have the basics
|
||||
model_ = new RideCacheModel(context, this);
|
||||
|
||||
@@ -152,6 +152,20 @@ RideCache::RideCache(Context *context) : context(context)
|
||||
connect(&watcher, SIGNAL(progressValueChanged(int)), this, SLOT(progressing(int)));
|
||||
}
|
||||
|
||||
struct comparerideitem { bool operator()(const RideItem *p1, const RideItem *p2) { return p1->dateTime < p2->dateTime; } };
|
||||
|
||||
int
|
||||
RideCache::find(RideItem *dt)
|
||||
{
|
||||
// use lower_bound to binary search
|
||||
QVector<RideItem*>::const_iterator i = std::lower_bound(rides_.begin(), rides_.end(), dt, comparerideitem());
|
||||
int index = i - rides_.begin();
|
||||
|
||||
// did it find the right value?
|
||||
if (index < 0 || index >= rides_.count() || rides_.at(index)->dateTime != dt->dateTime) return -1;
|
||||
return index;
|
||||
}
|
||||
|
||||
RideCache::~RideCache()
|
||||
{
|
||||
exiting = true;
|
||||
|
||||
@@ -102,6 +102,9 @@ class RideCache : public QObject
|
||||
void load();
|
||||
void save(bool opendata=false, QString filename="");
|
||||
|
||||
// find entry quickly
|
||||
int find(RideItem *);
|
||||
|
||||
// user updated options/preferences
|
||||
void configChanged(qint32);
|
||||
|
||||
|
||||
@@ -39,19 +39,44 @@
|
||||
// Un-Escape special characters (JSON compliance)
|
||||
static QString unprotect(char *string)
|
||||
{
|
||||
// sending UTF-8 to FLEX demands symetric conversion back to QString
|
||||
QString string2 = QString::fromUtf8(string);
|
||||
|
||||
// this is a lexer string so it will be enclosed
|
||||
// in quotes. Lets strip those first
|
||||
QStringRef r = string2.midRef(1,string2.length()-2);
|
||||
char *s = string;
|
||||
char *target = static_cast<char*>(malloc(strlen(string)+1));
|
||||
char *p = target;
|
||||
|
||||
// does it end with a space (to avoid token conflict) ?
|
||||
if (r.endsWith(" ")) r = r.mid(0, r.length()-1);
|
||||
// first "
|
||||
s++;
|
||||
|
||||
QString s = Utils::RidefileUnEscape(r);
|
||||
while (*s != '\0') {
|
||||
if (*s == '\\') {
|
||||
switch(*++s) {
|
||||
case '\\' : *p++ = '\\'; break;
|
||||
case 't' : *p++ = '\t'; break;
|
||||
case 'n' : *p++ = '\n'; break;
|
||||
case 'r' : *p++ = '\r'; break;
|
||||
case 'b' : *p++ = '\b'; break;
|
||||
case 'f' : *p++ = '\f'; break;
|
||||
case '/' : *p++ = '/'; break;
|
||||
case '"' : *p++ = '"'; break;
|
||||
default:
|
||||
*p++ = '\\'; *p++ = *s;
|
||||
}
|
||||
} else *p++ = *s;
|
||||
s++;
|
||||
}
|
||||
|
||||
return s;
|
||||
// trailing "
|
||||
p--;
|
||||
|
||||
// trailing SINGLE space used to protect tokens
|
||||
*p-- = '\0';
|
||||
if(p>=target && *p == ' ') *p = '\0';
|
||||
|
||||
// as a qstring
|
||||
QString r = QString::fromUtf8(target);
|
||||
free(target);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
// we reimplement these to remove compiler warnings
|
||||
|
||||
@@ -83,33 +83,21 @@ ride: '{' rideelement_list '}' {
|
||||
#endif
|
||||
} else {
|
||||
|
||||
// we're loading the cache
|
||||
bool found = false;
|
||||
foreach(RideItem *i, jc->cache->rides()) {
|
||||
if (i->fileName == jc->item.fileName) {
|
||||
double progress= double(jc->loading++) / double(jc->cache->rides().count()) * 100.0f;
|
||||
if (jc->context->mainWindow->progress) {
|
||||
|
||||
found = true;
|
||||
|
||||
// progress update
|
||||
double progress= double(jc->loading++) / double(jc->cache->rides().count()) * 100.0f;
|
||||
if (jc->context->mainWindow->progress) {
|
||||
|
||||
// percentage progress
|
||||
QString m = QString("%1%").arg(progress , 0, 'f', 0);
|
||||
jc->context->mainWindow->progress->setText(m);
|
||||
QApplication::processEvents();
|
||||
} else {
|
||||
jc->context->notifyLoadProgress(jc->folder,progress);
|
||||
}
|
||||
|
||||
// update from our loaded value
|
||||
i->setFrom(jc->item);
|
||||
break;
|
||||
}
|
||||
// percentage progress
|
||||
QString m = QString("%1%").arg(progress , 0, 'f', 0);
|
||||
jc->context->mainWindow->progress->setText(m);
|
||||
QApplication::processEvents();
|
||||
} else {
|
||||
jc->context->notifyLoadProgress(jc->folder,progress);
|
||||
}
|
||||
// not found !
|
||||
if (found == false)
|
||||
qDebug()<<"unable to load:"<<jc->item.fileName<<jc->item.dateTime<<jc->item.weight;
|
||||
|
||||
// find entry and update it
|
||||
int index=jc->cache->find(&jc->item);
|
||||
if (index==-1) qDebug()<<"unable to load:"<<jc->item.fileName<<jc->item.dateTime<<jc->item.weight;
|
||||
else jc->cache->rides().at(index)->setFrom(jc->item);
|
||||
}
|
||||
|
||||
// now set our ride item clean again, so we don't
|
||||
|
||||
@@ -95,6 +95,8 @@ class RideItem : public QObject
|
||||
|
||||
public:
|
||||
|
||||
bool operator==(RideItem &other) { return other.dateTime == dateTime; }
|
||||
|
||||
Context *context; // to notify widgets when date/time changes
|
||||
bool isdirty; // ride data has changed and needs saving
|
||||
bool isstale; // metric data is out of date and needs recomputing
|
||||
|
||||
@@ -84,6 +84,22 @@ AthleteCard::AthleteCard(ChartSpace *parent, QString path) : ChartSpaceItem(pare
|
||||
painter.drawEllipse(0, 0, img.width(), img.height());
|
||||
avatar = canvas.toImage();
|
||||
|
||||
#if 0
|
||||
// ridecache raw
|
||||
if (loadprogress == 0) {
|
||||
QTime timer;
|
||||
timer.start();
|
||||
QFile rideDB(gcroot + "/" + path + "/cache/rideDB.json");
|
||||
if (rideDB.exists() && rideDB.open(QFile::ReadOnly)) {
|
||||
|
||||
QByteArray contents = rideDB.readAll();
|
||||
rideDB.close();
|
||||
QJsonDocument json = QJsonDocument::fromJson(contents);
|
||||
}
|
||||
fprintf(stderr, "'%s' read rideDB took %d usecs\n", path.toStdString().c_str(), timer.elapsed()); fflush(stderr);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user