diff options
author | Wang Lei <leiw@apache.org> | 2012-09-14 07:03:51 +0000 |
---|---|---|
committer | Wang Lei <leiw@apache.org> | 2012-09-14 07:03:51 +0000 |
commit | b39f169896005a4ab3f2a0cfdb116de947dda207 (patch) | |
tree | a2521142e65f9dc0d18e07f0f06a8a0d3a178717 /svl | |
parent | 45fc638e2fcb644aa4df5b1a62c4ddccac111802 (diff) |
#i120575 optimize a comparing operation from 'memcmp' to 'hash compare' to improve xls loading performance
Patch by: li zhang (lizh.fee@gmail.com)
Review by: Wang Lei
Notes
reject: We have implemented different way to speed up styles import from xls
Diffstat (limited to 'svl')
-rw-r--r-- | svl/inc/svl/itemset.hxx | 26 | ||||
-rw-r--r-- | svl/source/items/itemset.cxx | 82 |
2 files changed, 102 insertions, 6 deletions
diff --git a/svl/inc/svl/itemset.hxx b/svl/inc/svl/itemset.hxx index c1611189a019..4da844eecaf9 100644 --- a/svl/inc/svl/itemset.hxx +++ b/svl/inc/svl/itemset.hxx @@ -78,6 +78,16 @@ class SVL_DLLPUBLIC SfxItemSet sal_uInt16* _pWhichRanges; // Array von Which-Bereichen sal_uInt16 _nCount; // Anzahl Items + //optimize a comparing operation from 'memcmp' to 'hash compare' to improve xls loading performance, i120575 + sal_Int32 _aHashKey; //hash result of array of points: _aItems. + + void UpdateHashKey(); + //Need invlidate the hashkey at every possible place where the array _aItems may be changed. + //thread safe : there is always solarmutex outter, so no need to add mutex here. + void InvalidateHashKey() { _aHashKey = 0;} //treat '0' as an invalidate key. + sal_Bool IsValidateHashKey() const { return (0!=_aHashKey);} + sal_Int32 GetHashKey() const { return _aHashKey; } + //end:i120575 //--------------------------------------------------------------------- #ifndef _SFXITEMS_HXX @@ -91,7 +101,14 @@ private: SVL_DLLPRIVATE void InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2); public: - SfxItemArray GetItems_Impl() const { return _aItems; } + //optimize a comparing operation from 'memcmp' to 'hash compare' to improve xls loading performance, i120575 + //Make this method public is dangerous, may disrupt the item array. so invalidate the hash key here. + //currently this method is never called, pls also do not do it in future. + SfxItemArray GetItems_Impl() const + { + const_cast<SfxItemSet &>(*this).InvalidateHashKey(); + return _aItems; + }//end:i120575 #endif //--------------------------------------------------------------------- @@ -169,6 +186,13 @@ public: virtual SvStream & Store( SvStream &, FASTBOOL bDirect = sal_False ) const; virtual int operator==(const SfxItemSet &) const; + + //optimize a comparing operation from 'memcmp' to 'hash compare' to improve xls loading performance, i120575 + //in some situation (e.g.. ScPatternAttr::operator== ), + //two sfxitemset can be compared 'quickly' by the Hashkey only. + //may also update the hashkey in this method. + sal_Bool QuickCompare( SfxItemSet & rCmp); + //end:i120575 }; // --------------- Inline Implementierungen ------------------------ diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index 0cbd01a0daa3..762464798da6 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -134,7 +134,8 @@ SfxItemSet::SfxItemSet : _pPool( &rPool ), _pParent( 0 ), - _nCount( 0 ) + _nCount( 0 ), + _aHashKey( 0 ) //i120575 { DBG_CTOR(SfxItemSet, DbgCheckItemSet); DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); @@ -163,7 +164,8 @@ SfxItemSet::SfxItemSet SfxItemSet::SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2 ): _pPool( &rPool ), _pParent( 0 ), - _nCount( 0 ) + _nCount( 0 ), + _aHashKey( 0 ) //i120575 { DBG_CTOR(SfxItemSet, DbgCheckItemSet); DBG_ASSERT( nWhich1 <= nWhich2, "Ungueltiger Bereich" ); @@ -205,7 +207,8 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, _pPool( &rPool ), _pParent( 0 ), _pWhichRanges( 0 ), - _nCount( 0 ) + _nCount( 0 ), + _aHashKey( 0 ) //i120575 { DBG_CTOR(SfxItemSet, DbgCheckItemSet); DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" ); @@ -256,7 +259,8 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ): _pPool( &rPool ), _pParent( 0 ), _pWhichRanges(0), - _nCount( 0 ) + _nCount( 0 ), + _aHashKey( 0 ) //i120575 { DBG_CTOR(SfxItemSet, 0); DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); @@ -272,7 +276,8 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ): SfxItemSet::SfxItemSet( const SfxItemSet& rASet ): _pPool( rASet._pPool ), _pParent( rASet._pParent ), - _nCount( rASet._nCount ) + _nCount( rASet._nCount ), + _aHashKey( 0 ) //i120575 { DBG_CTOR(SfxItemSet, DbgCheckItemSet); DBG_ASSERTWARNING( _pPool == _pPool->GetMasterPool(), "kein Master-Pool" ); @@ -455,6 +460,7 @@ sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich ) pPtr += 2; } } + InvalidateHashKey(); //i120575 return nDel; } @@ -484,6 +490,7 @@ void SfxItemSet::ClearInvalidItems( sal_Bool bHardDefault ) } pPtr += 2; } + InvalidateHashKey(); //i120575 } //------------------------------------------------------------------------ @@ -495,6 +502,7 @@ void SfxItemSet::InvalidateAllItems() DBG_ASSERT( !_nCount, "Es sind noch Items gesetzt" ); memset( (void*)_aItems, -1, ( _nCount = TotalCount() ) * sizeof( SfxPoolItem*) ); + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -582,6 +590,7 @@ const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) ) { *ppFnd = &_pPool->Put( rItem, nWhich ); + InvalidateHashKey(); //i120575 return *ppFnd; } @@ -589,6 +598,7 @@ const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich if( !rItem.Which() ) { *ppFnd = rItem.Clone(_pPool); + InvalidateHashKey(); //i120575 return 0; } else @@ -626,11 +636,14 @@ const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich SFX_ASSERT( !_pPool->IsItemFlag(nWhich, SFX_ITEM_POOLABLE) || rItem.ISA(SfxSetItem) || **ppFnd == rItem, nWhich, "putted Item unequal" ); + + InvalidateHashKey(); //i120575 return *ppFnd; } ppFnd += *(pPtr+1) - *pPtr + 1; pPtr += 2; } + InvalidateHashKey(); //i120575 return 0; } @@ -864,6 +877,7 @@ void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges ) _pWhichRanges = new sal_uInt16[ nCount ]; memcpy( _pWhichRanges, pNewRanges, sizeof( sal_uInt16 ) * nCount ); } + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -1137,6 +1151,7 @@ void SfxItemSet::Intersect( const SfxItemSet& rSet ) pItem = aIter.NextItem(); } } + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -1209,6 +1224,7 @@ void SfxItemSet::Differentiate( const SfxItemSet& rSet ) } } + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -1412,6 +1428,7 @@ void SfxItemSet::MergeValues( const SfxItemSet& rSet, sal_Bool bIgnoreDefaults ) MergeValue( *pItem, bIgnoreDefaults ); } } + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -1434,6 +1451,7 @@ void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, sal_Bool bIgnoreDefaults ppFnd += *(pPtr+1) - *pPtr + 1; pPtr += 2; } + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -1468,6 +1486,7 @@ void SfxItemSet::InvalidateItem( sal_uInt16 nWhich ) ppFnd += *(pPtr+1) - *pPtr + 1; pPtr += 2; } + InvalidateHashKey(); //i120575 } // ----------------------------------------------------------------------- @@ -1629,6 +1648,8 @@ SvStream &SfxItemSet::Load } } + + InvalidateHashKey(); //i120575 return rStream; } @@ -1768,6 +1789,7 @@ int SfxItemSet::PutDirect(const SfxPoolItem &rItem) rItem.AddRef(); } + InvalidateHashKey(); //i120575 return sal_True; } ppFnd += *(pPtr+1) - *pPtr + 1; @@ -2008,6 +2030,8 @@ const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhi if ( bIncrementCount ) ++_nCount; + InvalidateHashKey(); //i120575 + return &rNew; } @@ -2116,3 +2140,51 @@ SfxItemSet *SfxAllItemSet::Clone(sal_Bool bItems, SfxItemPool *pToPool ) const return bItems ? new SfxAllItemSet(*this) : new SfxAllItemSet(*_pPool); } +//for i120575 +//align with the rtl_hash, return signed int result and input len limited to 2G. +//can be replaced with other hash function in future for better performance, e.g. fnv hash. +inline sal_Int32 myhash(void * buf, sal_Int32 buf_len) +{ + return rtl_str_hashCode_WithLength( reinterpret_cast<const sal_Char *>(buf), buf_len); +} + +inline void SfxItemSet::UpdateHashKey() +{ + _aHashKey= myhash(_aItems,TotalCount()* sizeof(_aItems[0])); + + //always treat '0' as invalidate hash key, not using addtional bool data field for saving space. + if (!IsValidateHashKey() ) + { + _aHashKey = 1; + } +} + +sal_Bool SfxItemSet::QuickCompare( SfxItemSet & rCmp) +{ + if ( _pParent != rCmp._pParent || + _pPool != rCmp._pPool || + Count() != rCmp.Count() ) + return sal_False; + + if ((0==Count())&&(0==rCmp.Count())) + return sal_True; + + if (!IsValidateHashKey()) + { + UpdateHashKey(); + } + if (!rCmp.IsValidateHashKey()) + { + rCmp.UpdateHashKey(); + } + + //improved performance here, in most cases, the hashkey is not equal. + if (GetHashKey() != rCmp.GetHashKey()) + return sal_False; + + if ( 0 == memcmp( _aItems, rCmp._aItems, TotalCount() * sizeof(_aItems[0]) ) ) + return sal_True; + else + return sal_False; +} +//end: i120575 |