From patchwork Fri Dec 28 23:56:38 2007 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Reinhard Nissl X-Patchwork-Id: 12561 Received: from mail.gmx.net ([213.165.64.20]) by www.linuxtv.org with smtp (Exim 4.63) (envelope-from ) id 1J8P4h-0006hD-6S for vdr@linuxtv.org; Sat, 29 Dec 2007 00:57:11 +0100 Received: (qmail invoked by alias); 28 Dec 2007 23:56:39 -0000 Received: from p54933202.dip0.t-ipconnect.de (EHLO [192.168.101.15]) [84.147.50.2] by mail.gmx.net (mp006) with SMTP; 29 Dec 2007 00:56:39 +0100 X-Authenticated: #527675 X-Provags-ID: V01U2FsdGVkX1+wUONZwmOw9J0jyKqBRQp64TkDMyVIntiXBX/B/V KifdsYdEGZhwSr Message-ID: <47758D36.2090004@gmx.de> Date: Sat, 29 Dec 2007 00:56:38 +0100 From: Reinhard Nissl User-Agent: Mozilla/5.0 (X11; U; Linux i686; de; rv:1.8.1.9) Gecko/20070801 SUSE/2.0.0.9-0.1 Thunderbird/2.0.0.9 Mnenhy/0.7.5.666 MIME-Version: 1.0 To: VDR Mailing List References: <476ED734.4010802@gmx.de> <4772E6E6.7040909@gmx.de> <477417C7.2080707@gmx.de> <47757833.6020701@gmx.de> In-Reply-To: <47757833.6020701@gmx.de> X-Y-GMX-Trusted: 0 Subject: Re: [vdr] [ANNOUNCE] VDR-1.5.12: some "micro" speed improvements X-BeenThere: vdr@linuxtv.org X-Mailman-Version: 2.1.9 Precedence: list Reply-To: VDR Mailing List List-Id: VDR Mailing List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 Dec 2007 23:57:11 -0000 Status: O X-Status: X-Keywords: X-UID: 14914 Hi, Reinhard Nissl schrieb: > the first patch optimizes cNitFilter::Process() by looping only over the > relevant channels. It introduces a further hash in cChannels and > implements an iterator for hiding this implementation detail. Sorry, but a line from the DVB-S2 patch slipped through. Please find attached an updated version. Bye. --- ../vdr-1.5.12-orig/channels.h 2007-09-02 12:23:11.000000000 +0200 +++ channels.h 2007-12-28 22:56:02.000000000 +0100 @@ -219,13 +219,49 @@ public: void SetRefChannel(cChannel *RefChannel); }; +class cIteratorImpl { +private: + int refCount; + cIteratorImpl(const cIteratorImpl &); + const cIteratorImpl &operator =(const cIteratorImpl &); +public: + cIteratorImpl(void) { refCount = 0; } + virtual ~cIteratorImpl() {} + virtual int AddRef(void) { return ++refCount; } + virtual int DelRef(void) { int RefCount = --refCount; if (RefCount <= 0) delete this; return RefCount; } + virtual void *First(void) = 0; + virtual void *Last(void) = 0; + virtual void *Prev(void) = 0; + virtual void *Next(void) = 0; + virtual void *Current(void) const = 0; + }; + +template class cIterator +{ +private: + cIteratorImpl *impl; +public: + cIterator(cIteratorImpl *Impl) { impl = Impl; impl->AddRef(); } + cIterator(const cIterator &rhs) { impl = rhs.impl; impl->AddRef(); } + ~cIterator() { impl->DelRef(); } + const cIterator &operator =(const cIterator &rhs) { rhs.impl->AddRef(); impl->DelRef(); impl = rhs.impl; return *this; } + T *First(void) const { return (T *)impl->First(); } + T *Last(void) const { return (T *)impl->Last(); } + T *Prev(void) const { return (T *)impl->Prev(); } + T *Next(void) const { return (T *)impl->Next(); } + T *Current(void) const { return (T *)impl->Current(); } + }; + class cChannels : public cRwLock, public cConfig { private: int maxNumber; int modified; int beingEdited; cHash channelsHashSid; + cHash channelsHashNidTid; void DeleteDuplicateChannels(void); + void ClearChannelHashes(void); + static unsigned int HashKeyNidTid(unsigned short Nid, unsigned short Tid); public: cChannels(void); bool Load(const char *FileName, bool AllowComments = false, bool MustExist = false); @@ -240,6 +276,7 @@ public: cChannel *GetByServiceID(int Source, int Transponder, unsigned short ServiceID); cChannel *GetByChannelID(tChannelID ChannelID, bool TryWithoutRid = false, bool TryWithoutPolarization = false); cChannel *GetByTransponderID(tChannelID ChannelID); + cIterator GetChannelsBySourceNidTid(int Source, unsigned short Nid, unsigned short Tid); int BeingEdited(void) { return beingEdited; } void IncBeingEdited(void) { beingEdited++; } void DecBeingEdited(void) { beingEdited--; } --- ../vdr-1.5.12-orig/channels.c 2007-10-12 16:40:53.000000000 +0200 +++ channels.c 2007-12-28 22:56:02.000000000 +0100 @@ -905,14 +905,72 @@ bool cChannels::Load(const char *FileNam return false; } +void cChannels::ClearChannelHashes(void) +{ + channelsHashSid.Clear(); + channelsHashNidTid.Clear(); +} + void cChannels::HashChannel(cChannel *Channel) { channelsHashSid.Add(Channel, Channel->Sid()); + channelsHashNidTid.Add(Channel, HashKeyNidTid(Channel->Nid(), Channel->Tid())); } void cChannels::UnhashChannel(cChannel *Channel) { channelsHashSid.Del(Channel, Channel->Sid()); + channelsHashNidTid.Del(Channel, HashKeyNidTid(Channel->Nid(), Channel->Tid())); +} + +unsigned int cChannels::HashKeyNidTid(unsigned short Nid, unsigned short Tid) +{ + return Nid << 16 | Tid; +} + +cIterator cChannels::GetChannelsBySourceNidTid(int Source, unsigned short Nid, unsigned short Tid) +{ + class cIteratorImplSourceNidTid : public cIteratorImpl { + private: + cList *hashList; + cHashObject *current; + int source; + unsigned short nid; + unsigned short tid; + cChannel *FindMatchingChannel(bool reverse, bool reset = false) { + if (!hashList || (!current && !reset)) + return NULL; + while (true) { + if (reset) { + reset = false; + current = reverse ? hashList->Last() : hashList->First(); + } + else + current = reverse ? hashList->Prev(current) : hashList->Next(current); + if (!current) + break; + cChannel *Channel = (cChannel *)current->Object(); + if (Channel->Source() == source && Channel->Nid() == nid && Channel->Tid() == tid) + return Channel; + } + return NULL; + } + public: + cIteratorImplSourceNidTid(cList *HashList, int Source, unsigned short Nid, unsigned short Tid) { + hashList = HashList; + source = Source; + nid = Nid; + tid = Tid; + current = NULL; + } + virtual void *First(void) { return FindMatchingChannel(false, true); } + virtual void *Last(void) { return FindMatchingChannel(true, true); } + virtual void *Prev(void) { return FindMatchingChannel(false); } + virtual void *Next(void) { return FindMatchingChannel(true); } + virtual void *Current(void) const { return current ? (cChannel *)current->Object() : NULL; } + }; + + return cIterator(new cIteratorImplSourceNidTid(channelsHashNidTid.GetList(HashKeyNidTid(Nid, Tid)), Source, Nid, Tid)); } int cChannels::GetNextGroup(int Idx) @@ -949,7 +1007,7 @@ int cChannels::GetPrevNormal(int Idx) void cChannels::ReNumber( void ) { - channelsHashSid.Clear(); + ClearChannelHashes(); int Number = 1; for (cChannel *channel = First(); channel; channel = Next(channel)) { if (channel->GroupSep()) { --- ../vdr-1.5.12-orig/nit.c 2007-08-17 16:02:45.000000000 +0200 +++ nit.c 2007-12-29 00:49:01.000000000 +0100 @@ -142,20 +142,19 @@ void cNitFilter::Process(u_short Pid, u_ } if (Setup.UpdateChannels >= 5) { bool found = false; - for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) { - if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) { - int transponder = Channel->Transponder(); - if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), transponder)) { - for (int n = 0; n < NumFrequencies; n++) { - if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), transponder)) { - Frequency = Frequencies[n]; - break; - } + cIterator ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId()); + for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) { + int transponder = Channel->Transponder(); + if (!ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), transponder)) { + for (int n = 0; n < NumFrequencies; n++) { + if (ISTRANSPONDER(cChannel::Transponder(Frequencies[n], Polarization), transponder)) { + Frequency = Frequencies[n]; + break; } - } - if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder - Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate); + } } + if (ISTRANSPONDER(cChannel::Transponder(Frequency, Polarization), Transponder())) // only modify channels if we're actually receiving this transponder + Channel->SetSatTransponderData(Source, Frequency, Polarization, SymbolRate, CodeRate); found = true; } if (!found) { @@ -193,20 +192,19 @@ void cNitFilter::Process(u_short Pid, u_ } if (Setup.UpdateChannels >= 5) { bool found = false; - for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) { - if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) { - int transponder = Channel->Transponder(); - if (!ISTRANSPONDER(Frequency / 1000, transponder)) { - for (int n = 0; n < NumFrequencies; n++) { - if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) { - Frequency = Frequencies[n]; - break; - } + cIterator ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId()); + for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) { + int transponder = Channel->Transponder(); + if (!ISTRANSPONDER(Frequency / 1000, transponder)) { + for (int n = 0; n < NumFrequencies; n++) { + if (ISTRANSPONDER(Frequencies[n] / 1000, transponder)) { + Frequency = Frequencies[n]; + break; } - } - if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder - Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate); + } } + if (ISTRANSPONDER(Frequency / 1000, Transponder())) // only modify channels if we're actually receiving this transponder + Channel->SetCableTransponderData(Source, Frequency, Modulation, SymbolRate, CodeRate); found = true; } if (!found) { @@ -251,20 +249,19 @@ void cNitFilter::Process(u_short Pid, u_ } if (Setup.UpdateChannels >= 5) { bool found = false; - for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) { - if (!Channel->GroupSep() && Channel->Source() == Source && Channel->Nid() == ts.getOriginalNetworkId() && Channel->Tid() == ts.getTransportStreamId()) { - int transponder = Channel->Transponder(); - if (!ISTRANSPONDER(Frequency / 1000000, transponder)) { - for (int n = 0; n < NumFrequencies; n++) { - if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) { - Frequency = Frequencies[n]; - break; - } + cIterator ChannelIterator = Channels.GetChannelsBySourceNidTid(Source, ts.getOriginalNetworkId(), ts.getTransportStreamId()); + for (cChannel *Channel = ChannelIterator.First(); Channel; Channel = ChannelIterator.Next()) { + int transponder = Channel->Transponder(); + if (!ISTRANSPONDER(Frequency / 1000000, transponder)) { + for (int n = 0; n < NumFrequencies; n++) { + if (ISTRANSPONDER(Frequencies[n] / 1000000, transponder)) { + Frequency = Frequencies[n]; + break; } - } - if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder - Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode); + } } + if (ISTRANSPONDER(Frequency / 1000000, Transponder())) // only modify channels if we're actually receiving this transponder + Channel->SetTerrTransponderData(Source, Frequency, Bandwidth, Constellation, Hierarchy, CodeRateHP, CodeRateLP, GuardInterval, TransmissionMode); found = true; } if (!found) { @@ -276,7 +273,7 @@ void cNitFilter::Process(u_short Pid, u_ else delete Channel; } - } + } } } break;