mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-28 00:29:21 +00:00
feat(address): add a sip addresses cache to increase performance (+50%)
This commit is contained in:
parent
e7aadda4fa
commit
b61cc2bdb9
5 changed files with 164 additions and 2 deletions
|
|
@ -91,6 +91,7 @@ set(LINPHONE_CXX_OBJECTS_PRIVATE_HEADER_FILES
|
|||
conference/session/call-session.h
|
||||
conference/session/media-session.h
|
||||
conference/session/port-config.h
|
||||
containers/lru-cache.h
|
||||
content/content-manager.h
|
||||
content/content-p.h
|
||||
content/content-type.h
|
||||
|
|
|
|||
|
|
@ -38,6 +38,8 @@ public:
|
|||
}
|
||||
void setInternalAddress (const SalAddress *value);
|
||||
|
||||
static void clearSipAddressesCache ();
|
||||
|
||||
private:
|
||||
struct AddressCache {
|
||||
std::string scheme;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "address/identity-address.h"
|
||||
#include "c-wrapper/c-wrapper.h"
|
||||
#include "c-wrapper/internal/c-sal.h"
|
||||
#include "containers/lru-cache.h"
|
||||
#include "logger/logger.h"
|
||||
|
||||
// =============================================================================
|
||||
|
|
@ -31,6 +32,49 @@ using namespace std;
|
|||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
namespace {
|
||||
class SalAddressWrap {
|
||||
public:
|
||||
explicit SalAddressWrap (SalAddress *salAddress = nullptr) : mSalAddress(salAddress) {}
|
||||
|
||||
SalAddressWrap (const SalAddressWrap &other) : mSalAddress(other.mSalAddress) {
|
||||
if (mSalAddress)
|
||||
sal_address_ref(mSalAddress);
|
||||
}
|
||||
|
||||
SalAddressWrap (SalAddressWrap &&other) : mSalAddress(other.mSalAddress) {
|
||||
other.mSalAddress = nullptr;
|
||||
}
|
||||
|
||||
~SalAddressWrap () {
|
||||
if (mSalAddress)
|
||||
sal_address_unref(mSalAddress);
|
||||
}
|
||||
|
||||
const SalAddress *get () {
|
||||
return mSalAddress;
|
||||
}
|
||||
|
||||
private:
|
||||
SalAddress *mSalAddress;
|
||||
};
|
||||
LruCache<string, SalAddressWrap> addressesCache;
|
||||
}
|
||||
|
||||
static SalAddress *getSalAddressFromCache (const string &uri) {
|
||||
SalAddressWrap *wrap = addressesCache[uri];
|
||||
if (wrap)
|
||||
return sal_address_clone(wrap->get());
|
||||
|
||||
SalAddress *address = sal_address_new(L_STRING_TO_C(uri));
|
||||
if (address) {
|
||||
addressesCache.insert(uri, SalAddressWrap(address));
|
||||
return sal_address_clone(address);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
void AddressPrivate::setInternalAddress (const SalAddress *addr) {
|
||||
|
|
@ -39,11 +83,16 @@ void AddressPrivate::setInternalAddress (const SalAddress *addr) {
|
|||
internalAddress = sal_address_clone(addr);
|
||||
}
|
||||
|
||||
void AddressPrivate::clearSipAddressesCache () {
|
||||
addressesCache.clear();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
Address::Address (const string &address) : ClonableObject(*new AddressPrivate) {
|
||||
L_D();
|
||||
if (!(d->internalAddress = sal_address_new(L_STRING_TO_C(address)))) {
|
||||
|
||||
if (!(d->internalAddress = getSalAddressFromCache(address))) {
|
||||
lWarning() << "Cannot create Address, bad uri [" << address << "]";
|
||||
}
|
||||
}
|
||||
|
|
@ -65,7 +114,7 @@ Address::Address (const IdentityAddress &identityAddress) : ClonableObject(*new
|
|||
if (identityAddress.hasGruu())
|
||||
uri += ";gr=" + identityAddress.getGruu();
|
||||
|
||||
d->internalAddress = sal_address_new(L_STRING_TO_C(uri));
|
||||
d->internalAddress = getSalAddressFromCache(uri);
|
||||
}
|
||||
|
||||
Address::Address (const Address &other) : ClonableObject(*new AddressPrivate) {
|
||||
|
|
|
|||
107
src/containers/lru-cache.h
Normal file
107
src/containers/lru-cache.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* lru-cache.h
|
||||
* Copyright (C) 2010-2018 Belledonne Communications SARL
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _L_LRU_CACHE_H_
|
||||
#define _L_LRU_CACHE_H_
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "linphone/utils/general.h"
|
||||
|
||||
// =============================================================================
|
||||
|
||||
LINPHONE_BEGIN_NAMESPACE
|
||||
|
||||
template<typename Key, typename Value>
|
||||
class LruCache {
|
||||
public:
|
||||
LruCache (int capacity = DefaultCapacity) : mCapacity(capacity) {
|
||||
if (capacity < MinCapacity)
|
||||
capacity = MinCapacity;
|
||||
}
|
||||
|
||||
int getCapacity () const {
|
||||
return mCapacity;
|
||||
}
|
||||
|
||||
int getSize () const {
|
||||
return int(mKeyToPair.size());
|
||||
}
|
||||
|
||||
Value *operator[] (const Key &key) {
|
||||
auto it = mKeyToPair.find(key);
|
||||
return it == mKeyToPair.end() ? nullptr : &it->second.second;
|
||||
}
|
||||
|
||||
const Value *operator[] (const Key &key) const {
|
||||
auto it = mKeyToPair.find(key);
|
||||
return it == mKeyToPair.cend() ? nullptr : &it->second.second;
|
||||
}
|
||||
|
||||
void insert (const Key &key, const Value &value) {
|
||||
auto it = mKeyToPair.find(key);
|
||||
if (it != mKeyToPair.end())
|
||||
mKeys.erase(it->second.first);
|
||||
else if (int(mKeyToPair.size()) == mCapacity) {
|
||||
Key lastKey = mKeys.back();
|
||||
mKeys.pop_back();
|
||||
mKeyToPair.erase(lastKey);
|
||||
}
|
||||
|
||||
mKeys.push_front(key);
|
||||
mKeyToPair.insert({ key, { mKeys.begin(), value } });
|
||||
}
|
||||
|
||||
void insert (const Key &key, Value &&value) {
|
||||
auto it = mKeyToPair.find(key);
|
||||
if (it != mKeyToPair.end())
|
||||
mKeys.erase(it->second.first);
|
||||
else if (int(mKeyToPair.size()) == mCapacity) {
|
||||
Key lastKey = mKeys.back();
|
||||
mKeys.pop_back();
|
||||
mKeyToPair.erase(lastKey);
|
||||
}
|
||||
|
||||
mKeys.push_front(key);
|
||||
mKeyToPair.insert({ key, std::make_pair(mKeys.begin(), std::move(value)) });
|
||||
}
|
||||
|
||||
void clear () {
|
||||
mKeyToPair.clear();
|
||||
mKeys.clear();
|
||||
}
|
||||
|
||||
static constexpr int MinCapacity = 10;
|
||||
static constexpr int DefaultCapacity = 1000;
|
||||
|
||||
private:
|
||||
using Pair = std::pair<typename std::list<Key>::iterator, Value>;
|
||||
|
||||
const int mCapacity;
|
||||
|
||||
// See: https://stackoverflow.com/questions/16781886/can-we-store-unordered-maptiterator
|
||||
// Do not store iterator key.
|
||||
std::list<Key> mKeys;
|
||||
std::unordered_map<Key, Pair> mKeyToPair;
|
||||
};
|
||||
|
||||
LINPHONE_END_NAMESPACE
|
||||
|
||||
#endif // ifndef _L_LRU_CACHE_H_
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include <mediastreamer2/mscommon.h>
|
||||
#include <xercesc/util/PlatformUtils.hpp>
|
||||
|
||||
#include "address/address-p.h"
|
||||
#include "call/call.h"
|
||||
#include "core/core-listener.h"
|
||||
#include "core/core-p.h"
|
||||
|
|
@ -75,6 +76,8 @@ void CorePrivate::uninit () {
|
|||
linphone_core_iterate(L_GET_C_BACK_PTR(q));
|
||||
ms_usleep(10000);
|
||||
}
|
||||
|
||||
AddressPrivate::clearSipAddressesCache();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue