Commit b61cc2bd authored by Ronan's avatar Ronan

feat(address): add a sip addresses cache to increase performance (+50%)

parent e7aadda4
......@@ -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) {
......
/*
* 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();
}
// -----------------------------------------------------------------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment