1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Kernel: Support lazy sweeping simple GC. v5.0.69

This commit is contained in:
winlin 2022-09-30 18:33:29 +08:00
parent 4b7d9587f4
commit 927dd473eb
6 changed files with 221 additions and 3 deletions

View file

@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 5.0 Changelog ## SRS 5.0 Changelog
* v5.0, 2022-09-30, Kernel: Support lazy sweeping simple GC. v5.0.69
* v5.0, 2022-09-30, HTTP: Support HTTP header in creating order. v5.0.68 * v5.0, 2022-09-30, HTTP: Support HTTP header in creating order. v5.0.68
* v5.0, 2022-09-27, For [#2899](https://github.com/ossrs/srs/issues/2899): API: Support exporter for Prometheus. v5.0.67 * v5.0, 2022-09-27, For [#2899](https://github.com/ossrs/srs/issues/2899): API: Support exporter for Prometheus. v5.0.67
* v5.0, 2022-09-27, For [#3167](https://github.com/ossrs/srs/issues/3167): WebRTC: Refine sequence jitter algorithm. v5.0.66 * v5.0, 2022-09-27, For [#3167](https://github.com/ossrs/srs/issues/3167): WebRTC: Refine sequence jitter algorithm. v5.0.66

View file

@ -406,6 +406,28 @@ void SrsResourceManager::dispose(ISrsResource* c)
} }
} }
SrsSweepGc::SrsSweepGc()
{
}
SrsSweepGc::~SrsSweepGc()
{
}
srs_error_t SrsSweepGc::start()
{
srs_error_t err = srs_success;
return err;
}
void SrsSweepGc::remove(ISrsLazyResource* c)
{
// TODO: FIXME: MUST lazy sweep.
srs_freep(c);
}
ISrsLazyGc* _srs_gc = NULL;
ISrsExpire::ISrsExpire() ISrsExpire::ISrsExpire()
{ {
} }

View file

@ -124,8 +124,93 @@ private:
void dispose(ISrsResource* c); void dispose(ISrsResource* c);
}; };
// If a connection is able to be expired, // A simple lazy-sweep GC, just wait for a long time to delete the disposable resources.
// user can use HTTP-API to kick-off it. class SrsSweepGc : public ISrsLazyGc
{
public:
SrsSweepGc();
virtual ~SrsSweepGc();
public:
virtual srs_error_t start();
virtual void remove(ISrsLazyResource* c);
};
extern ISrsLazyGc* _srs_gc;
// A wrapper template for lazy-sweep resource.
// See https://github.com/ossrs/srs/issues/3176#lazy-sweep
template<typename T>
class SrsLazyResourceWrapper : public ISrsResource
{
private:
T* resource_;
ISrsResource* wrapper_;
bool is_root_;
public:
SrsLazyResourceWrapper(T* resource = NULL, ISrsResource* wrapper = NULL) {
wrapper_ = wrapper ? wrapper : this;
resource_ = resource ? resource : new T();
resource_->gc_use(wrapper_);
is_root_ = !resource;
if (!resource) {
resource_->gc_set_creator_wrapper(wrapper_);
}
}
virtual ~SrsLazyResourceWrapper() {
resource_->gc_dispose(wrapper_);
if (is_root_) {
resource_->gc_set_creator_wrapper(NULL);
}
if (resource_->gc_ref() == 0) {
_srs_gc->remove(resource_);
}
}
public:
SrsLazyResourceWrapper<T>* copy() {
return new SrsLazyResourceWrapper<T>(resource_);
}
T* resource() {
return resource_;
}
// Interface ISrsResource
public:
virtual const SrsContextId& get_id() {
return resource_->get_id();
}
virtual std::string desc() {
return resource_->desc();
}
};
// Use macro to generate a wrapper class, because typedef will cause IDE incorrect tips.
// See https://github.com/ossrs/srs/issues/3176#lazy-sweep
#define SRS_LAZY_WRAPPER_GENERATOR(Resource, IWrapper, IResource) \
private: \
SrsLazyResourceWrapper<Resource> impl_; \
public: \
Resource##Wrapper(Resource* resource = NULL) : impl_(resource, this) { \
} \
virtual ~Resource##Wrapper() { \
} \
public: \
IWrapper* copy() { \
return new Resource##Wrapper(impl_.resource()); \
} \
IResource* resource() { \
return impl_.resource(); \
} \
public: \
virtual const SrsContextId& get_id() { \
return impl_.get_id(); \
} \
virtual std::string desc() { \
return impl_.desc(); \
} \
// If a connection is able be expired, user can use HTTP-API to kick-off it.
class ISrsExpire class ISrsExpire
{ {
public: public:

View file

@ -9,6 +9,6 @@
#define VERSION_MAJOR 5 #define VERSION_MAJOR 5
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 68 #define VERSION_REVISION 69
#endif #endif

View file

@ -6,6 +6,9 @@
#include <srs_protocol_conn.hpp> #include <srs_protocol_conn.hpp>
#include <algorithm>
using namespace std;
ISrsResource::ISrsResource() ISrsResource::ISrsResource()
{ {
} }
@ -35,3 +38,64 @@ ISrsConnection::~ISrsConnection()
{ {
} }
ISrsLazyResource::ISrsLazyResource()
{
gc_ref_ = 0;
gc_creator_wrapper_ = NULL;
}
ISrsLazyResource::~ISrsLazyResource()
{
}
ISrsLazyResource* ISrsLazyResource::gc_use(ISrsResource* wrapper)
{
srs_assert(wrapper);
if (std::find(gc_wrappers_.begin(), gc_wrappers_.end(), wrapper) == gc_wrappers_.end()) {
gc_wrappers_.push_back(wrapper);
}
gc_ref_++;
return this;
}
ISrsLazyResource* ISrsLazyResource::gc_dispose(ISrsResource* wrapper)
{
srs_assert(wrapper);
vector<ISrsResource*>::iterator it = std::find(gc_wrappers_.begin(), gc_wrappers_.end(), wrapper);
if (it != gc_wrappers_.end()) {
it = gc_wrappers_.erase(it);
}
gc_ref_--;
return this;
}
int32_t ISrsLazyResource::gc_ref()
{
return gc_ref_;
}
void ISrsLazyResource::gc_set_creator_wrapper(ISrsResource* wrapper)
{
gc_creator_wrapper_ = wrapper;
}
ISrsResource* ISrsLazyResource::gc_creator_wrapper()
{
return gc_creator_wrapper_;
}
ISrsResource* ISrsLazyResource::gc_available_wrapper()
{
return gc_wrappers_.empty() ? NULL : gc_wrappers_.front();
}
ISrsLazyGc::ISrsLazyGc()
{
}
ISrsLazyGc::~ISrsLazyGc()
{
}

View file

@ -10,6 +10,7 @@
#include <srs_core.hpp> #include <srs_core.hpp>
#include <string> #include <string>
#include <vector>
// The resource managed by ISrsResourceManager. // The resource managed by ISrsResourceManager.
class ISrsResource class ISrsResource
@ -20,6 +21,7 @@ public:
public: public:
// Get the context id of connection. // Get the context id of connection.
virtual const SrsContextId& get_id() = 0; virtual const SrsContextId& get_id() = 0;
public:
// The resource description, optional. // The resource description, optional.
virtual std::string desc(); virtual std::string desc();
}; };
@ -46,5 +48,49 @@ public:
virtual std::string remote_ip() = 0; virtual std::string remote_ip() = 0;
}; };
// Lazy-sweep resource, never sweep util all wrappers are freed.
// See https://github.com/ossrs/srs/issues/3176#lazy-sweep
class ISrsLazyResource : public ISrsResource
{
private:
// The reference count of resource, 0 is no wrapper and safe to sweep.
int32_t gc_ref_;
// The creator wrapper, which created this resource. Note that it might be disposed and the pointer is NULL, so be
// careful and make sure to check it before use it.
ISrsResource* gc_creator_wrapper_;
// All available wrappers.
std::vector<ISrsResource*> gc_wrappers_;
public:
ISrsLazyResource();
virtual ~ISrsLazyResource();
public:
// For wrapper to use this resource.
virtual ISrsLazyResource* gc_use(ISrsResource* wrapper);
// For wrapper to dispose this resource.
virtual ISrsLazyResource* gc_dispose(ISrsResource* wrapper);
// The current reference count of resource.
virtual int32_t gc_ref();
public:
// Set the creator wrapper, from which resource clone wrapper.
virtual void gc_set_creator_wrapper(ISrsResource* wrapper);
// Get the first available wrapper. NULL if the creator wrapper disposed.
virtual ISrsResource* gc_creator_wrapper();
// Get the first available wrapper. NULL if all wrappers disposed.
// It should be equal to the gc_creator_wrapper() if creator wrapper not disposed.
virtual ISrsResource* gc_available_wrapper();
};
// The lazy-sweep GC, wait for a long time to dispose resource even when resource is disposable.
// See https://github.com/ossrs/srs/issues/3176#lazy-sweep
class ISrsLazyGc
{
public:
ISrsLazyGc();
virtual ~ISrsLazyGc();
public:
// Remove then free the specified resource.
virtual void remove(ISrsLazyResource* c) = 0;
};
#endif #endif