core(persistence): fix reserveNodeSpace() implementation

- avoid data copying after buffer block shrink
- resize current block in case of single FileNode
pull/15591/head
Alexander Alekhin 5 years ago
parent 2fef9bc1d8
commit 6e246ee58c
  1. 26
      modules/core/src/persistence.cpp

@ -1307,6 +1307,9 @@ public:
// In the case (b) the existing tag and the name are copied automatically. // In the case (b) the existing tag and the name are copied automatically.
uchar* reserveNodeSpace(FileNode& node, size_t sz) uchar* reserveNodeSpace(FileNode& node, size_t sz)
{ {
bool shrinkBlock = false;
size_t shrinkBlockIdx = 0, shrinkSize = 0;
uchar *ptr = 0, *blockEnd = 0; uchar *ptr = 0, *blockEnd = 0;
if( !fs_data_ptrs.empty() ) if( !fs_data_ptrs.empty() )
@ -1315,19 +1318,32 @@ public:
size_t ofs = node.ofs; size_t ofs = node.ofs;
CV_Assert( blockIdx == fs_data_ptrs.size()-1 ); CV_Assert( blockIdx == fs_data_ptrs.size()-1 );
CV_Assert( ofs <= fs_data_blksz[blockIdx] ); CV_Assert( ofs <= fs_data_blksz[blockIdx] );
CV_Assert( freeSpaceOfs <= fs_data_blksz[blockIdx] );
//CV_Assert( freeSpaceOfs <= ofs + sz ); //CV_Assert( freeSpaceOfs <= ofs + sz );
ptr = fs_data_ptrs[blockIdx] + ofs; ptr = fs_data_ptrs[blockIdx] + ofs;
blockEnd = fs_data_ptrs[blockIdx] + fs_data_blksz[blockIdx]; blockEnd = fs_data_ptrs[blockIdx] + fs_data_blksz[blockIdx];
CV_Assert(ptr >= fs_data_ptrs[blockIdx] && ptr <= blockEnd);
if( ptr + sz <= blockEnd ) if( ptr + sz <= blockEnd )
{ {
freeSpaceOfs = ofs + sz; freeSpaceOfs = ofs + sz;
return ptr; return ptr;
} }
fs_data[blockIdx]->resize(ofs); if (ofs == 0) // FileNode is a first component of this block. Resize current block instead of allocation of new one.
fs_data_blksz[blockIdx] = ofs; {
fs_data[blockIdx]->resize(sz);
ptr = &fs_data[blockIdx]->at(0);
fs_data_ptrs[blockIdx] = ptr;
fs_data_blksz[blockIdx] = sz;
freeSpaceOfs = sz;
return ptr;
}
shrinkBlock = true;
shrinkBlockIdx = blockIdx;
shrinkSize = ofs;
} }
size_t blockSize = std::max((size_t)CV_FS_MAX_LEN*4 - 256, sz) + 256; size_t blockSize = std::max((size_t)CV_FS_MAX_LEN*4 - 256, sz) + 256;
@ -1352,6 +1368,12 @@ public:
} }
} }
if (shrinkBlock)
{
fs_data[shrinkBlockIdx]->resize(shrinkSize);
fs_data_blksz[shrinkBlockIdx] = shrinkSize;
}
return new_ptr; return new_ptr;
} }

Loading…
Cancel
Save