tdf#117066 Saving ODT document with ~1500 bookmarks is slow, part 1
Individually, these don't make much difference, but they add up
to a halving the time to save on my machine.
EmbeddedObjectContainer shows a lot of work in HasEmbeddedObject and
GetEmbeddedObjectName, so add a reverse map there.
Change-Id: Ib758668dbb045e6ceb2611bd86aa2af4fbfb9917
Reviewed-on: https://gerrit.libreoffice.org/70309
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/comphelper/source/container/embeddedobjectcontainer.cxx b/comphelper/source/container/embeddedobjectcontainer.cxx
index ffa2296..ff0ec3a 100644
--- a/comphelper/source/container/embeddedobjectcontainer.cxx
+++ b/comphelper/source/container/embeddedobjectcontainer.cxx
@@ -55,19 +55,22 @@
namespace comphelper {
typedef std::unordered_map<OUString, uno::Reference <embed::XEmbeddedObject>>
EmbeddedObjectContainerNameMap;
typedef std::unordered_map<OUString, uno::Reference<embed::XEmbeddedObject>> EmbeddedObjectContainerNameMap;
struct EmbedImpl
{
struct XEmbeddedObjectRefHash
{
size_t operator()(const uno::Reference<embed::XEmbeddedObject>& rObject) const
{ return reinterpret_cast<size_t>(rObject.get()); }
};
// TODO/LATER: remove objects from temp. Container storage when object is disposed
EmbeddedObjectContainerNameMap maObjectContainer;
EmbeddedObjectContainerNameMap maNameToObjectMap;
// to speed up lookup by Reference
std::unordered_map<uno::Reference<embed::XEmbeddedObject>, OUString, XEmbeddedObjectRefHash> maObjectToNameMap;
uno::Reference < embed::XStorage > mxStorage;
EmbeddedObjectContainer* mpTempObjectContainer;
uno::Reference < embed::XStorage > mxImageStorage;
uno::WeakReference < uno::XInterface > m_xModel;
//EmbeddedObjectContainerNameMap maTempObjectContainer;
//uno::Reference < embed::XStorage > mxTempStorage;
bool mbOwnsStorage : 1;
bool mbUserAllowsLinkUpdate : 1;
@@ -197,7 +200,7 @@
void EmbeddedObjectContainer::CloseEmbeddedObjects()
{
for( const auto& rObj : pImpl->maObjectContainer )
for( const auto& rObj : pImpl->maNameToObjectMap )
{
uno::Reference < util::XCloseable > xClose( rObj.second, uno::UNO_QUERY );
if( xClose.is() )
@@ -229,18 +232,18 @@
uno::Sequence < OUString > EmbeddedObjectContainer::GetObjectNames() const
{
return comphelper::mapKeysToSequence(pImpl->maObjectContainer);
return comphelper::mapKeysToSequence(pImpl->maNameToObjectMap);
}
bool EmbeddedObjectContainer::HasEmbeddedObjects() const
{
return !pImpl->maObjectContainer.empty();
return !pImpl->maNameToObjectMap.empty();
}
bool EmbeddedObjectContainer::HasEmbeddedObject( const OUString& rName )
{
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
if (aIt != pImpl->maObjectContainer.end())
auto aIt = pImpl->maNameToObjectMap.find( rName );
if (aIt != pImpl->maNameToObjectMap.end())
return true;
uno::Reference <container::XNameAccess> xAccess(pImpl->mxStorage, uno::UNO_QUERY);
if (!xAccess.is())
@@ -250,12 +253,7 @@
bool EmbeddedObjectContainer::HasEmbeddedObject( const uno::Reference < embed::XEmbeddedObject >& xObj ) const
{
for( const auto& rObj : pImpl->maObjectContainer )
{
if( rObj.second == xObj )
return true;
}
return false;
return pImpl->maObjectToNameMap.find(xObj) != pImpl->maObjectToNameMap.end();
}
bool EmbeddedObjectContainer::HasInstantiatedEmbeddedObject( const OUString& rName )
@@ -263,19 +261,19 @@
// allows to detect whether the object was already instantiated
// currently the filter instantiate it on loading, so this method allows
// to avoid objects pointing to the same persistence
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
return ( aIt != pImpl->maObjectContainer.end() );
auto aIt = pImpl->maNameToObjectMap.find( rName );
return ( aIt != pImpl->maNameToObjectMap.end() );
}
OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const css::uno::Reference < css::embed::XEmbeddedObject >& xObj ) const
{
for( const auto& rObj : pImpl->maObjectContainer )
auto it = pImpl->maObjectToNameMap.find(xObj);
if (it == pImpl->maObjectToNameMap.end())
{
if( rObj.second == xObj )
return rObj.first;
SAL_WARN( "comphelper.container", "Unknown object!" );
return OUString();
}
SAL_WARN( "comphelper.container", "Unknown object!" );
return OUString();
return it->second;
}
uno::Reference< embed::XEmbeddedObject>
@@ -285,7 +283,7 @@
SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Empty object name!");
uno::Reference < embed::XEmbeddedObject > xObj;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
auto aIt = pImpl->maNameToObjectMap.find( rName );
#if OSL_DEBUG_LEVEL > 1
uno::Reference < container::XNameAccess > xAccess( pImpl->mxStorage, uno::UNO_QUERY );
@@ -296,11 +294,11 @@
{
(void)*pIter;
}
OSL_ENSURE( aIt != pImpl->maObjectContainer.end() || xAccess->hasByName(rName), "Could not return object!" );
OSL_ENSURE( aIt != pImpl->maNameToObjectMap.end() || xAccess->hasByName(rName), "Could not return object!" );
#endif
// check if object was already created
if ( aIt != pImpl->maObjectContainer.end() )
if ( aIt != pImpl->maNameToObjectMap.end() )
xObj = (*aIt).second;
else
xObj = Get_Impl(rName, uno::Reference<embed::XEmbeddedObject>(), pBaseURL);
@@ -424,9 +422,10 @@
#endif
// remember object - it needs to be in storage already
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
OSL_ENSURE( aIt == pImpl->maObjectContainer.end(), "Element already inserted!" );
pImpl->maObjectContainer[ rName ] = xObj;
auto aIt = pImpl->maNameToObjectMap.find( rName );
OSL_ENSURE( aIt == pImpl->maNameToObjectMap.end(), "Element already inserted!" );
pImpl->maNameToObjectMap[ rName ] = xObj;
pImpl->maObjectToNameMap[ xObj ] = rName;
uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
if ( xChild.is() && xChild->getParent() != pImpl->m_xModel.get() )
xChild->setParent( pImpl->m_xModel.get() );
@@ -434,7 +433,7 @@
// look for object in temporary container
if ( pImpl->mpTempObjectContainer )
{
auto& rObjectContainer = pImpl->mpTempObjectContainer->pImpl->maObjectContainer;
auto& rObjectContainer = pImpl->mpTempObjectContainer->pImpl->maNameToObjectMap;
auto aIter = std::find_if(rObjectContainer.begin(), rObjectContainer.end(),
[&xObj](const EmbeddedObjectContainerNameMap::value_type& rEntry) { return rEntry.second == xObj; });
if (aIter != rObjectContainer.end())
@@ -464,7 +463,8 @@
}
// temp. container needs to forget the object
pImpl->mpTempObjectContainer->pImpl->maObjectContainer.erase( aIter );
pImpl->mpTempObjectContainer->pImpl->maObjectToNameMap.erase( aIter->second );
pImpl->mpTempObjectContainer->pImpl->maNameToObjectMap.erase( aIter );
}
}
}
@@ -841,15 +841,15 @@
bool EmbeddedObjectContainer::MoveEmbeddedObject( const OUString& rName, EmbeddedObjectContainer& rCnt )
{
// find object entry
EmbeddedObjectContainerNameMap::iterator aIt2 = rCnt.pImpl->maObjectContainer.find( rName );
OSL_ENSURE( aIt2 == rCnt.pImpl->maObjectContainer.end(), "Object does already exist in target container!" );
auto aIt2 = rCnt.pImpl->maNameToObjectMap.find( rName );
OSL_ENSURE( aIt2 == rCnt.pImpl->maNameToObjectMap.end(), "Object does already exist in target container!" );
if ( aIt2 != rCnt.pImpl->maObjectContainer.end() )
if ( aIt2 != rCnt.pImpl->maNameToObjectMap.end() )
return false;
uno::Reference < embed::XEmbeddedObject > xObj;
EmbeddedObjectContainerNameMap::iterator aIt = pImpl->maObjectContainer.find( rName );
if ( aIt != pImpl->maObjectContainer.end() )
auto aIt = pImpl->maNameToObjectMap.find( rName );
if ( aIt != pImpl->maNameToObjectMap.end() )
{
xObj = (*aIt).second;
try
@@ -859,7 +859,8 @@
// move object
OUString aName( rName );
rCnt.InsertEmbeddedObject( xObj, aName );
pImpl->maObjectContainer.erase( aIt );
pImpl->maObjectToNameMap.erase( aIt->second );
pImpl->maNameToObjectMap.erase( aIt );
uno::Reference < embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
if ( xPersist.is() )
pImpl->mxStorage->removeElement( rName );
@@ -956,11 +957,12 @@
return false;
}
auto aIter = std::find_if(pImpl->maObjectContainer.begin(), pImpl->maObjectContainer.end(),
auto aIter = std::find_if(pImpl->maNameToObjectMap.begin(), pImpl->maNameToObjectMap.end(),
[&xObj](const EmbeddedObjectContainerNameMap::value_type& rEntry) { return rEntry.second == xObj; });
if (aIter != pImpl->maObjectContainer.end())
if (aIter != pImpl->maNameToObjectMap.end())
{
pImpl->maObjectContainer.erase( aIter );
pImpl->maObjectToNameMap.erase( aIter->second );
pImpl->maNameToObjectMap.erase( aIter );
uno::Reference < container::XChild > xChild( xObj, uno::UNO_QUERY );
if ( xChild.is() )
xChild->setParent( uno::Reference < uno::XInterface >() );
@@ -997,11 +999,12 @@
{
// disconnect the object from the container and close it if possible
auto aIter = std::find_if(pImpl->maObjectContainer.begin(), pImpl->maObjectContainer.end(),
auto aIter = std::find_if(pImpl->maNameToObjectMap.begin(), pImpl->maNameToObjectMap.end(),
[&xObj](const EmbeddedObjectContainerNameMap::value_type& rEntry) { return rEntry.second == xObj; });
if (aIter != pImpl->maObjectContainer.end())
if (aIter != pImpl->maNameToObjectMap.end())
{
pImpl->maObjectContainer.erase( aIter );
pImpl->maObjectToNameMap.erase( aIter->second );
pImpl->maNameToObjectMap.erase( aIter );
uno::Reference < ::util::XCloseable > xClose( xObj, uno::UNO_QUERY );
try