Commit bb232092 authored by Albert Astals Cid's avatar Albert Astals Cid

limit the number of text pages we keep in memory so that searching does not...

limit the number of text pages we keep in memory so that searching does not bring your system to its knees

BUG: 161213

svn path=/trunk/KDE/kdegraphics/okular/; revision=803949
parent e13e74db
......@@ -743,6 +743,13 @@ void DocumentPrivate::refreshPixmaps( int pageNumber )
void DocumentPrivate::_o_configChanged()
{
// free text pages if needed
calculateMaxTextPages();
while (m_allocatedTextPagesFifo.count() > m_maxAllocatedTextPages)
{
int pageToKick = m_allocatedTextPagesFifo.takeFirst();
m_pagesVector.at(pageToKick)->setTextPage( 0 ); // deletes the textpage
}
}
void DocumentPrivate::doContinueNextMatchSearch(void *pagesToNotifySet, void * theMatch, int currentPage, int searchID, const QString & text, int theCaseSensitivity, bool moveViewport, const QColor & color, bool noDialogs, int donePages)
......@@ -2970,6 +2977,43 @@ void DocumentPrivate::requestDone( PixmapRequest * req )
sendGeneratorRequest();
}
void DocumentPrivate::calculateMaxTextPages()
{
int multipliers = qMax(1, qRound(getTotalMemory() / 536870912.0)); // 512 MB
switch (Settings::memoryLevel())
{
case Settings::EnumMemoryLevel::Low:
m_maxAllocatedTextPages = multipliers * 2;
break;
case Settings::EnumMemoryLevel::Normal:
m_maxAllocatedTextPages = multipliers * 50;
break;
case Settings::EnumMemoryLevel::Aggressive:
m_maxAllocatedTextPages = multipliers * 250;
break;
}
}
void DocumentPrivate::textGenerationDone( Page *page )
{
if ( !m_generator || m_closingLoop ) return;
// 1. If we reached the cache limit, delete the first text page from the fifo
if (m_allocatedTextPagesFifo.size() == m_maxAllocatedTextPages)
{
int pageToKick = m_allocatedTextPagesFifo.takeFirst();
if (pageToKick != page->number()) // this should never happen but better be safe than sorry
{
m_pagesVector.at(pageToKick)->setTextPage( 0 ); // deletes the textpage
}
}
// 2. Add the page to the fifo of generated text pages
m_allocatedTextPagesFifo.append( page->number() );
}
void Document::setRotation( int r )
{
d->setRotationInternal( r, true );
......@@ -3267,3 +3311,5 @@ VisiblePageRect::VisiblePageRect( int page, const NormalizedRect &rectangle )
}
#include "document.moc"
/* kate: replace-tabs on; indent-width 4; */
......@@ -82,12 +82,14 @@ class DocumentPrivate
m_scripter( 0 ),
m_fontsCached( false )
{
calculateMaxTextPages();
}
// private methods
QString pagesSizeString() const;
QString localizedSize(const QSizeF &size) const;
void cleanupPixmapMemory( qulonglong bytesOffset = 0 );
void calculateMaxTextPages();
qulonglong getTotalMemory();
qulonglong getFreeMemory();
void loadDocumentInfo();
......@@ -123,6 +125,7 @@ class DocumentPrivate
* the pixmap generation @p request.
*/
void requestDone( PixmapRequest * request );
void textGenerationDone( Page *page );
/**
* Request a particular metadata of the Document itself (ie, not something
* depending on the document type/backend).
......@@ -159,6 +162,8 @@ class DocumentPrivate
QMutex m_pixmapRequestsMutex;
QLinkedList< AllocatedPixmap * > m_allocatedPixmapsFifo;
qulonglong m_allocatedPixmapsTotalMemory;
QList< int > m_allocatedTextPagesFifo;
int m_maxAllocatedTextPages;
bool m_warnedOutOfMemory;
// the rotation applied to the document
......
......@@ -103,6 +103,7 @@ void GeneratorPrivate::pixmapGenerationFinished()
void GeneratorPrivate::textpageGenerationFinished()
{
Q_Q( Generator );
Page *page = mTextPageGenerationThread->page();
mTextPageGenerationThread->endGeneration();
......@@ -121,7 +122,11 @@ void GeneratorPrivate::textpageGenerationFinished()
}
if ( mTextPageGenerationThread->textPage() )
page->setTextPage( mTextPageGenerationThread->textPage() );
{
TextPage *tp = mTextPageGenerationThread->textPage();
page->setTextPage( tp );
q->signalTextGenerationDone( page, tp );
}
}
QMutex* GeneratorPrivate::threadsLock()
......@@ -234,8 +239,10 @@ bool Generator::canGenerateTextPage() const
void Generator::generateTextPage( Page *page )
{
Q_D( Generator );
page->setTextPage( textPage( page ) );
TextPage *tp = textPage( page );
page->setTextPage( tp );
d->mTextPageReady = true;
signalTextGenerationDone( page, tp );
}
QImage Generator::image( PixmapRequest * )
......@@ -329,6 +336,15 @@ void Generator::signalPixmapRequestDone( PixmapRequest * request )
}
}
void Generator::signalTextGenerationDone( Page *page, TextPage *textPage )
{
Q_D( Generator );
if ( d->m_document )
d->m_document->textGenerationDone( page );
else
delete textPage;
}
const Document * Generator::document() const
{
Q_D( const Generator );
......
......@@ -387,6 +387,11 @@ class OKULAR_EXPORT Generator : public QObject
*/
void signalPixmapRequestDone( PixmapRequest * request );
/**
* This method must be called when a text generation has been finished.
*/
void signalTextGenerationDone( Page *page, TextPage *textPage );
/**
* This method is called when the document is closed and not used
* any longer.
......
......@@ -756,8 +756,12 @@ void PDFGenerator::generatePixmap( Okular::PixmapRequest * request )
#else
QList<Poppler::TextBox*> textList = p->textList((Poppler::Page::Rotation)request->page()->orientation());
#endif
page->setTextPage( abstractTextPage(textList, page->height(), page->width(), request->page()->orientation()) );
Okular::TextPage *tp = abstractTextPage(textList, page->height(), page->width(), request->page()->orientation());
page->setTextPage( tp );
qDeleteAll(textList);
// notify the new generation
signalTextGenerationDone( page, tp );
}
delete p;
......@@ -1573,9 +1577,13 @@ void PDFGenerator::threadFinished()
delete outImage;
if ( !outText.isEmpty() )
{
request->page()->setTextPage( abstractTextPage( outText ,
request->page()->height(), request->page()->width(),request->page()->orientation()));
Okular::TextPage *tp = abstractTextPage( outText, request->page()->height(),
request->page()->width(),request->page()->orientation());
request->page()->setTextPage( tp );
qDeleteAll(outText);
// notify the new generation
signalTextGenerationDone( request->page(), tp );
}
bool genObjectRects = !rectsGenerated.at( request->page()->number() );
if (genObjectRects)
......@@ -1772,5 +1780,7 @@ void PDFPixmapGeneratorThread::run()
// by ending the thread notifies the GUI thread that data is pending and can be read
}
#include "generator_pdf.moc"
/* kate: replace-tabs on; indent-width 4; */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment