Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
BC
public
liblinphone
Commits
b61cc2bd
Commit
b61cc2bd
authored
Feb 20, 2018
by
Ronan
Browse files
feat(address): add a sip addresses cache to increase performance (+50%)
parent
e7aadda4
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/CMakeLists.txt
View file @
b61cc2bd
...
...
@@ -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
...
...
src/address/address-p.h
View file @
b61cc2bd
...
...
@@ -38,6 +38,8 @@ public:
}
void
setInternalAddress
(
const
SalAddress
*
value
);
static
void
clearSipAddressesCache
();
private:
struct
AddressCache
{
std
::
string
scheme
;
...
...
src/address/address.cpp
View file @
b61cc2bd
...
...
@@ -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
)
{
...
...
src/containers/lru-cache.h
0 → 100644
View file @
b61cc2bd
/*
* 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_
src/core/core.cpp
View file @
b61cc2bd
...
...
@@ -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
();
}
// -----------------------------------------------------------------------------
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment