Much better performance when using natbib (bug 2460):

* src/BufferView_pimpl.C
	(bool BufferView::Pimpl::dispatch): update bibfiles cache after adding or
	deleting a bib database
* src/buffer.C
	(bool Buffer::readDocument): update bibfiles cache after the document 
	was read
* src/buffer.[Ch]
	(void Buffer::updateBibfilesCache): new method to build or update a cached
	vector with all used bibtex databases. 
	(void Buffer::getBibfilesCache): new method that returns the actual cache.
	(Buffer * Buffer::getMasterBuffer): new (non-const) method to get the buffer 
	of the master document

* src/insets/insetbibtex.C
	(void InsetBibtex::doDispatch): update the bibfiles cache after the inset has
	been modified.
* src/insets/insetinclude.C.
	(void Insetinclude::doDispatch): update the bibfiles cache after the inset 
	has Been modified.
* src/insets/insetinclude.[Ch]:
	(void Insetinclude::updateBibfilesCache): new method to build or update 
	a cached vector with all used bibtex databases. 
	(void Insetinclude::getBibfilesCache): new method that returns the actual 
	cache.
* src/insets/insetcite.C
	(string const getNatbibLabel): store a map of timestamps for all used bibtex 
	files (buffer's bibfiles cache) and rebuild the list of keys only if the timestamps
	or the list of files have changed. This is the actual performance boost. 

git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@13681 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Jürgen Spitzmüller 2006-04-15 11:46:17 +00:00
parent 3072b1111e
commit 1bed69439f
7 changed files with 163 additions and 20 deletions

View File

@ -1334,8 +1334,10 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
bv_funcs::findInset(tmpcur, InsetBase::BIBTEX_CODE, false);
InsetBibtex * inset = getInsetByCode<InsetBibtex>(tmpcur,
InsetBase::BIBTEX_CODE);
if (inset)
inset->addDatabase(cmd.argument);
if (inset) {
if (inset->addDatabase(cmd.argument))
buffer_->updateBibfilesCache();
}
break;
}
@ -1344,8 +1346,10 @@ bool BufferView::Pimpl::dispatch(FuncRequest const & cmd)
bv_funcs::findInset(tmpcur, InsetBase::BIBTEX_CODE, false);
InsetBibtex * inset = getInsetByCode<InsetBibtex>(tmpcur,
InsetBase::BIBTEX_CODE);
if (inset)
inset->delDatabase(cmd.argument);
if (inset) {
if (inset->delDatabase(cmd.argument))
buffer_->updateBibfilesCache();
}
break;
}

View File

@ -486,6 +486,7 @@ bool Buffer::readDocument(LyXLex & lex)
for_each(text().paragraphs().begin(),
text().paragraphs().end(),
bind(&Paragraph::setInsetOwner, _1, &inset()));
updateBibfilesCache();
return res;
}
@ -1252,6 +1253,53 @@ void Buffer::fillWithBibKeys(vector<pair<string, string> > & keys)
}
void Buffer::updateBibfilesCache()
{
// if this is a child document and the parent is already loaded
// update the parent's cache instead
Buffer * tmp = getMasterBuffer();
BOOST_ASSERT(tmp);
if (tmp != this) {
tmp->updateBibfilesCache();
return;
}
bibfilesCache_.clear();
for (InsetIterator it = inset_iterator_begin(inset()); it; ++it) {
if (it->lyxCode() == InsetBase::BIBTEX_CODE) {
InsetBibtex const & inset =
dynamic_cast<InsetBibtex const &>(*it);
vector<string> const bibfiles = inset.getFiles(*this);
bibfilesCache_.insert(bibfilesCache_.end(),
bibfiles.begin(),
bibfiles.end());
} else if (it->lyxCode() == InsetBase::INCLUDE_CODE) {
InsetInclude & inset =
dynamic_cast<InsetInclude &>(*it);
inset.updateBibfilesCache(*this);
vector<string> const & bibfiles =
inset.getBibfilesCache(*this);
bibfilesCache_.insert(bibfilesCache_.end(),
bibfiles.begin(),
bibfiles.end());
}
}
}
vector<string> const & Buffer::getBibfilesCache() const
{
// if this is a child document and the parent is already loaded
// use the parent's cache instead
Buffer const * tmp = getMasterBuffer();
BOOST_ASSERT(tmp);
if (tmp != this)
return tmp->getBibfilesCache();
return bibfilesCache_;
}
bool Buffer::isDepClean(string const & name) const
{
DepClean::const_iterator const it = pimpl_->dep_clean.find(name);
@ -1495,6 +1543,19 @@ Buffer const * Buffer::getMasterBuffer() const
}
Buffer * Buffer::getMasterBuffer()
{
if (!params().parentname.empty()
&& bufferlist.exists(params().parentname)) {
Buffer * buf = bufferlist.getBuffer(params().parentname);
if (buf)
return buf->getMasterBuffer();
}
return this;
}
MacroData const & Buffer::getMacro(std::string const & name) const
{
return pimpl_->macros.get(name);

View File

@ -24,6 +24,7 @@
#include <boost/signal.hpp>
#include <iosfwd>
#include <string>
#include <map>
#include <utility>
#include <vector>
@ -217,6 +218,10 @@ public:
child document)
*/
Buffer const * getMasterBuffer() const;
/** Get the document's master (or \c this if this is not a
child document)
*/
Buffer * getMasterBuffer();
/// Is buffer read-only?
bool isReadonly() const;
@ -249,6 +254,12 @@ public:
/// return all bibkeys from buffer and its childs
void fillWithBibKeys(std::vector<std::pair<std::string, std::string> > & keys) const;
/// Update the cache with all bibfiles in use (including bibfiles
/// of child documents).
void updateBibfilesCache();
/// Return the cache with all bibfiles in use (including bibfiles
/// of child documents).
std::vector<std::string> const & getBibfilesCache() const;
///
void getLabelList(std::vector<std::string> &) const;
@ -354,6 +365,9 @@ private:
/// it's BufferView, this should be FIXED in future.
StableDocIterator cursor_;
StableDocIterator anchor_;
/// A cache for the bibfiles (including bibfiles of child documents),
/// needed for appropriate update of natbib labels.
std::vector<std::string> bibfilesCache_;
};
#endif

View File

@ -86,9 +86,10 @@ void InsetBibtex::doDispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandMailer::string2params("bibtex", cmd.argument, p);
if (!p.getCmdName().empty())
if (!p.getCmdName().empty()) {
setParams(p);
else
cur.buffer().updateBibfilesCache();
} else
cur.noUpdate();
break;
}

View File

@ -24,6 +24,8 @@
#include "support/lstrings.h"
#include <boost/filesystem/operations.hpp>
using lyx::support::ascii_lowercase;
using lyx::support::contains;
using lyx::support::getVectorFromString;
@ -37,6 +39,7 @@ using std::vector;
using std::map;
namespace biblio = lyx::biblio;
namespace fs = boost::filesystem;
namespace {
@ -50,26 +53,47 @@ string const getNatbibLabel(Buffer const & buffer,
if (!buffer.fully_loaded())
return string();
// Cache the labels
typedef std::map<Buffer const *, biblio::InfoMap> CachedMap;
static CachedMap cached_keys;
// build the keylist
typedef vector<std::pair<string, string> > InfoType;
InfoType bibkeys;
buffer.fillWithBibKeys(bibkeys);
InfoType::const_iterator bit = bibkeys.begin();
InfoType::const_iterator bend = bibkeys.end();
// and cache the timestamp of the bibliography files.
static std::map<string, time_t> bibfileStatus;
biblio::InfoMap infomap;
for (; bit != bend; ++bit) {
infomap[bit->first] = bit->second;
vector<string> const & bibfilesCache = buffer.getBibfilesCache();
// compare the cached timestamps with the actual ones.
bool changed = false;
for (vector<string>::const_iterator it = bibfilesCache.begin();
it != bibfilesCache.end(); ++ it) {
string const f = *it;
if (bibfileStatus[f] != fs::last_write_time(f)) {
changed = true;
bibfileStatus[f] = fs::last_write_time(f);
}
}
// build the keylist only if the bibfiles have been changed
if (cached_keys.empty() || bibfileStatus.empty() || changed) {
typedef vector<std::pair<string, string> > InfoType;
InfoType bibkeys;
buffer.fillWithBibKeys(bibkeys);
InfoType::const_iterator bit = bibkeys.begin();
InfoType::const_iterator bend = bibkeys.end();
for (; bit != bend; ++bit)
infomap[bit->first] = bit->second;
cached_keys[&buffer] = infomap;
} else
// use the cached keys
infomap = cached_keys[&buffer];
if (infomap.empty())
return string();
cached_keys[&buffer] = infomap;
// the natbib citation-styles
// CITET: author (year)
// CITEP: (author,year)

View File

@ -128,9 +128,10 @@ void InsetInclude::doDispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetIncludeMailer::string2params(cmd.argument, p);
if (!p.getCmdName().empty())
if (!p.getCmdName().empty()) {
set(p, cur.buffer());
else
cur.buffer().updateBibfilesCache();
} else
cur.noUpdate();
break;
}
@ -613,6 +614,34 @@ void InsetInclude::fillWithBibKeys(Buffer const & buffer,
}
void InsetInclude::updateBibfilesCache(Buffer const & buffer)
{
if (loadIfNeeded(buffer, params_)) {
string const included_file = includedFilename(buffer, params_);
Buffer * tmp = bufferlist.getBuffer(included_file);
tmp->setParentName("");
tmp->updateBibfilesCache();
tmp->setParentName(parentFilename(buffer));
}
}
std::vector<string> const &
InsetInclude::getBibfilesCache(Buffer const & buffer) const
{
if (loadIfNeeded(buffer, params_)) {
string const included_file = includedFilename(buffer, params_);
Buffer * tmp = bufferlist.getBuffer(included_file);
tmp->setParentName("");
std::vector<string> const & cache = tmp->getBibfilesCache();
tmp->setParentName(parentFilename(buffer));
return cache;
}
static std::vector<string> const empty;
return empty;
}
void InsetInclude::metrics(MetricsInfo & mi, Dimension & dim) const
{
BOOST_ASSERT(mi.base.bv && mi.base.bv->buffer());

View File

@ -52,9 +52,19 @@ public:
* \param buffer the Buffer containing this inset.
* \param keys the list of bibkeys in the child buffer.
*/
///
void fillWithBibKeys(Buffer const & buffer,
std::vector<std::pair<std::string,std::string> > & keys) const;
/** Update the cache with all bibfiles in use of the child buffer
* (including bibfiles of grandchild documents).
* \param buffer the Buffer containing this inset.
*/
void updateBibfilesCache(Buffer const & buffer);
/** Return the cache with all bibfiles in use of the child buffer
* (including bibfiles of grandchild documents).
* \param buffer the Buffer containing this inset.
*/
std::vector<std::string> const &
getBibfilesCache(Buffer const & buffer) const;
///
EDITABLE editable() const { return IS_EDITABLE; }
///