mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-23 02:14:50 +00:00
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:
parent
3072b1111e
commit
1bed69439f
@ -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;
|
||||
}
|
||||
|
||||
|
61
src/buffer.C
61
src/buffer.C
@ -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);
|
||||
|
14
src/buffer.h
14
src/buffer.h
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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());
|
||||
|
@ -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; }
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user