d437076142
The file opened and mapped to memory in
the `xdictionary` ctor was never unmapped
and closed again, resulting in a memory leak.
For Android Viewer, this resulted in the app
running out of memory after a while when
scrolling up and down in the Chinese sample
doc from tdf#148851.
On Android, closing the file is actually the relevant part,
because the content of files from `/assets` is automatically
loaded into memory when the files are opened (s. the call to
`openMemoryAsFile` in `openFilePath` in `sal/osl/unx/file.cxx`)
and that memory is only freed when the file is closed
again (s. `osl_closeFile`).
When using the sample doc, the file in question
was "file:///assets/share/dict_zh.data", which
has a size of 2.2 MB and is therefore actually
loaded into memory anew every time, since only
files below 50 KiB are handled by the file cache
introduced in
commit 26a46c1143
Date: Fri Dec 20 14:46:36 2019 +0000
android: file-cache to improve performance.
Fix the memory leak by unmapping and closing
the file again in the dtor.
Change-Id: I3388964877080d1f2b3cf2682a41549e0bfb850c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133581
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
94 lines
3.1 KiB
C++
94 lines
3.1 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#pragma once
|
|
|
|
#include <osl/file.h>
|
|
#include <sal/types.h>
|
|
|
|
#include <com/sun/star/i18n/Boundary.hpp>
|
|
|
|
namespace i18npool {
|
|
|
|
#define CACHE_MAX 32 // max cache structure number
|
|
#define DEFAULT_SIZE 256 // for boundary size, to avoid alloc and release memory
|
|
|
|
// cache structure.
|
|
struct WordBreakCache {
|
|
sal_Unicode *contents; // separated segment contents.
|
|
sal_Int32* wordboundary; // word boundaries in segments.
|
|
sal_Int32 length; // contents length saved here.
|
|
sal_Int32 size; // size of wordboundary
|
|
|
|
WordBreakCache();
|
|
bool equals(const sal_Unicode *str, css::i18n::Boundary const & boundary) const; // checking cached string
|
|
};
|
|
|
|
struct xdictionarydata
|
|
{
|
|
const sal_uInt8 * existMark;
|
|
const sal_Int16 * index1;
|
|
const sal_Int32 * index2;
|
|
const sal_Int32 * lenArray;
|
|
const sal_Unicode* dataArea;
|
|
xdictionarydata() :
|
|
existMark( nullptr ),
|
|
index1( nullptr ),
|
|
index2( nullptr ),
|
|
lenArray( nullptr ),
|
|
dataArea( nullptr )
|
|
{
|
|
}
|
|
};
|
|
|
|
class xdictionary
|
|
{
|
|
private:
|
|
xdictionarydata data;
|
|
void initDictionaryData(const char *lang);
|
|
|
|
css::i18n::Boundary boundary;
|
|
bool japaneseWordBreak;
|
|
#ifdef DICT_JA_ZH_IN_DATAFILE
|
|
oslFileHandle m_aFileHandle;
|
|
sal_uInt64 m_nFileSize;
|
|
char* m_pMapping;
|
|
#endif
|
|
|
|
public:
|
|
xdictionary(const char *lang);
|
|
~xdictionary();
|
|
css::i18n::Boundary nextWord( const OUString& rText, sal_Int32 nPos, sal_Int16 wordType);
|
|
css::i18n::Boundary previousWord( const OUString& rText, sal_Int32 nPos, sal_Int16 wordType);
|
|
css::i18n::Boundary const & getWordBoundary( const OUString& rText, sal_Int32 nPos, sal_Int16 wordType, bool bDirection );
|
|
void setJapaneseWordBreak();
|
|
|
|
private:
|
|
WordBreakCache cache[CACHE_MAX];
|
|
OUString segmentCachedString;
|
|
css::i18n::Boundary segmentCachedBoundary;
|
|
|
|
bool seekSegment(const OUString& rText, sal_Int32 pos, css::i18n::Boundary& boundary);
|
|
WordBreakCache& getCache(const sal_Unicode *text, css::i18n::Boundary const & boundary);
|
|
bool exists(const sal_uInt32 u) const;
|
|
sal_Int32 getLongestMatch(const sal_Unicode *text, sal_Int32 len) const;
|
|
};
|
|
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|