Slowdown with large # of dependencies #1237

Stat results are cached for the duration of a dependency scan.
This commit is contained in:
Chris Palmer 2017-01-31 18:07:35 +00:00
parent 315ebe1c9a
commit d201970b13
6 changed files with 109 additions and 4 deletions

View file

@ -255,6 +255,7 @@ HEADERS += src/version_check.h \
src/FontListTableView.h \
src/GroupModule.h \
src/FileModule.h \
src/StatCache.h \
src/builtin.h \
src/calc.h \
src/context.h \
@ -436,6 +437,7 @@ SOURCES += \
src/hash.cc \
src/GroupModule.cc \
src/FileModule.cc \
src/StatCache.cc \
src/builtin.cc \
src/calc.cc \
src/export.cc \

View file

@ -31,6 +31,7 @@
#include "exceptions.h"
#include "modcontext.h"
#include "parsersettings.h"
#include "StatCache.h"
#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
@ -85,9 +86,9 @@ bool FileModule::include_modified(const IncludeFile &inc) const
struct stat st;
memset(&st, 0, sizeof(struct stat));
fs::path fullpath = find_valid_path(this->path, inc.filename);
bool valid = !fullpath.empty() ? (stat(fullpath.generic_string().c_str(), &st) == 0) : false;
//fs::path fullpath = find_valid_path(this->path, inc.filename);
//bool valid = !fullpath.empty() ? (StatCache::stat(fullpath.generic_string().c_str(), &st) == 0) : false;
bool valid = (StatCache::stat(inc.filename.c_str(), &st) == 0);
if (valid && !inc.valid) return true; // Detect appearance of file but not removal
if (valid && st.st_mtime > inc.mtime) return true;

View file

@ -1,4 +1,5 @@
#include "ModuleCache.h"
#include "StatCache.h"
#include "FileModule.h"
#include "printutils.h"
#include "openscad.h"
@ -46,7 +47,7 @@ bool ModuleCache::evaluate(const std::string &filename, FileModule *&module)
// Create cache ID
struct stat st;
memset(&st, 0, sizeof(struct stat));
bool valid = (stat(filename.c_str(), &st) == 0);
bool valid = (StatCache::stat(filename.c_str(), &st) == 0);
// If file isn't there, just return and let the cache retain the old module
if (!valid) return false;

65
src/StatCache.cc Normal file
View file

@ -0,0 +1,65 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "StatCache.h"
#include "printutils.h"
#include <sys/stat.h>
#include <string>
#include <unordered_map>
typedef std::unordered_map<std::string, struct stat> StatMap;
static StatMap statMap;
static int hits, misses;
static bool printed = false;
void StatCache::clear(void) {
if(misses && !printed) {
PRINTB("StatCache: %d hits, %d misses", hits % misses);
printed = true;
}
statMap.clear();
hits = misses = 0;
}
int StatCache::stat(const char *path, struct stat *st) {
StatMap::iterator iter = statMap.find(path);
if(iter != statMap.end()) {
*st = iter->second;
++hits;
return 0;
}
struct stat buff;
if(int rv = ::stat(path, &buff))
return rv;
statMap.insert(std::make_pair(std::string(path), buff));
*st = buff;
++misses;
return 0;
}

33
src/StatCache.h Normal file
View file

@ -0,0 +1,33 @@
/*
* OpenSCAD (www.openscad.org)
* Copyright (C) 2009-2011 Clifford Wolf <clifford@clifford.at> and
* Marius Kintel <marius@kintel.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* As a special exception, you have permission to link this program
* with the CGAL library and distribute executables, as long as you
* follow the requirements of the GNU GPL in regard to all of the
* software in the executable aside from CGAL.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#pragma once
class StatCache {
public:
static void clear(void);
static int stat(const char *, struct stat *);
};

View file

@ -28,6 +28,7 @@
#include "openscad.h"
#include "GeometryCache.h"
#include "ModuleCache.h"
#include "StatCache.h"
#include "MainWindow.h"
#include "OpenSCADApp.h"
#include "parsersettings.h"
@ -948,6 +949,7 @@ void MainWindow::compile(bool reload, bool forcedone)
compileWarnings = 0;
this->renderingTime.start();
StatCache::clear();
// Reload checks the timestamp of the toplevel file and refreshes if necessary,
if (reload) {
@ -1012,6 +1014,7 @@ void MainWindow::compile(bool reload, bool forcedone)
void MainWindow::waitAfterReload()
{
StatCache::clear();
if (this->root_module->handleDependencies()) {
this->waitAfterReloadTimer->start();
return;