[ANNOUNCE] VDR-1.5.12: some "micro" speed improvements

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

the attached patches speed up starting and stopping VDR on slow machines
with huge channels.conf files, by avoiding some n / 2 * (n + 1) loops.

Please test them and report bugs here.

Bye.
-- 
Dipl.-Inform. (FH) Reinhard Nissl
mailto:rnissl@xxxxxx
--- ../vdr-1.5.12-orig/channels.h	2007-09-02 12:23:11.000000000 +0200
+++ channels.h	2007-12-23 14:50:09.000000000 +0100
@@ -147,9 +147,12 @@ private:
   int modification;
   mutable const cSchedule *schedule;
   cLinkChannels *linkChannels;
-  cChannel *refChannel;
+  cLinkChannels *refChannels;
   cString ParametersToString(void) const;
   bool StringToParameters(const char *s);
+  void AddRefChannel(cChannel *RefChannel);
+  void DelRefChannel(cChannel *RefChannel);
+  void DelLinkChannel(cChannel *RefChannel);
 public:
   cChannel(void);
   cChannel(const cChannel &Channel);
@@ -198,7 +201,8 @@ public:
   int Guard(void) const { return guard; }
   int Hierarchy(void) const { return hierarchy; }
   const cLinkChannels* LinkChannels(void) const { return linkChannels; }
-  const cChannel *RefChannel(void) const { return refChannel; }
+  const cChannel *RefChannel(void) const { return refChannels ? refChannels->Last()->Channel() : 0; }
+  const cLinkChannels* RefChannels(void) const { return refChannels; }
   bool IsCable(void) const { return cSource::IsCable(source); }
   bool IsSat(void) const { return cSource::IsSat(source); }
   bool IsTerr(void) const { return cSource::IsTerr(source); }
@@ -216,7 +220,6 @@ public:
   void SetCaIds(const int *CaIds); // list must be zero-terminated
   void SetCaDescriptors(int Level);
   void SetLinkChannels(cLinkChannels *LinkChannels);
-  void SetRefChannel(cChannel *RefChannel);
   };
 
 class cChannels : public cRwLock, public cConfig<cChannel> {
--- ../vdr-1.5.12-orig/channels.c	2007-10-12 16:40:53.000000000 +0200
+++ channels.c	2007-12-23 14:50:09.000000000 +0100
@@ -178,7 +178,7 @@ cChannel::cChannel(void)
   modification = CHANNELMOD_NONE;
   schedule     = NULL;
   linkChannels = NULL;
-  refChannel   = NULL;
+  refChannels  = NULL;
 }
 
 cChannel::cChannel(const cChannel &Channel)
@@ -189,28 +189,26 @@ cChannel::cChannel(const cChannel &Chann
   portalName = NULL;
   schedule     = NULL;
   linkChannels = NULL;
-  refChannel   = NULL;
+  refChannels  = NULL;
   *this = Channel;
 }
 
 cChannel::~cChannel()
 {
-  delete linkChannels;
-  linkChannels = NULL; // more than one channel can link to this one, so we need the following loop
-  for (cChannel *Channel = Channels.First(); Channel; Channel = Channels.Next(Channel)) {
-      if (Channel->linkChannels) {
-         for (cLinkChannel *lc = Channel->linkChannels->First(); lc; lc = Channel->linkChannels->Next(lc)) {
-             if (lc->Channel() == this) {
-                Channel->linkChannels->Del(lc);
-                break;
-                }
-             }
-         if (Channel->linkChannels->Count() == 0) {
-            delete Channel->linkChannels;
-            Channel->linkChannels = NULL;
-            }
-         }
-      }
+  if (linkChannels) {
+     // in all channels which we link to remove the reference to us
+     for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc))
+         lc->Channel()->DelRefChannel(this);
+     delete linkChannels;
+     linkChannels = NULL;
+     }
+  if (refChannels) {
+     // in all channels which reference us remove their link to us
+     for (cLinkChannel *lc = refChannels->First(); lc; lc = refChannels->Next(lc))
+         lc->Channel()->DelLinkChannel(this);
+     delete refChannels;
+     refChannels = NULL;
+     }
   free(name);
   free(shortName);
   free(provider);
@@ -556,7 +554,7 @@ void cChannel::SetLinkChannels(cLinkChan
   q += sprintf(q, "linking channel %d from", Number());
   if (linkChannels) {
      for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
-         lc->Channel()->SetRefChannel(NULL);
+         lc->Channel()->DelRefChannel(this);
          q += sprintf(q, " %d", lc->Channel()->Number());
          }
      delete linkChannels;
@@ -567,7 +565,7 @@ void cChannel::SetLinkChannels(cLinkChan
   linkChannels = LinkChannels;
   if (linkChannels) {
      for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
-         lc->Channel()->SetRefChannel(this);
+         lc->Channel()->AddRefChannel(this);
          q += sprintf(q, " %d", lc->Channel()->Number());
          //dsyslog("link %4d -> %4d: %s", Number(), lc->Channel()->Number(), lc->Channel()->Name());
          }
@@ -577,9 +575,39 @@ void cChannel::SetLinkChannels(cLinkChan
   dsyslog(buffer);
 }
 
-void cChannel::SetRefChannel(cChannel *RefChannel)
+void cChannel::AddRefChannel(cChannel *RefChannel)
+{
+  if (!refChannels)
+     refChannels = new cLinkChannels;
+  refChannels->Add(new cLinkChannel(RefChannel));
+}
+
+void cChannel::DelRefChannel(cChannel *RefChannel)
 {
-  refChannel = RefChannel;
+  for (cLinkChannel *lc = refChannels->First(); lc; lc = refChannels->Next(lc)) {
+      if (lc->Channel() == RefChannel) {
+         refChannels->Del(lc);
+         if (refChannels->Count() <= 0) {
+            delete refChannels;
+            refChannels = NULL;
+            }
+         return;
+         }
+      }
+}
+
+void cChannel::DelLinkChannel(cChannel *LinkChannel)
+{
+  for (cLinkChannel *lc = linkChannels->First(); lc; lc = linkChannels->Next(lc)) {
+      if (lc->Channel() == LinkChannel) {
+         linkChannels->Del(lc);
+         if (linkChannels->Count() <= 0) {
+            delete linkChannels;
+            linkChannels = NULL;
+            }
+         return;
+         }
+      }
 }
 
 static int PrintParameter(char *p, char Name, int Value)
--- ../vdr-1.5.12-orig/epg.h	2006-10-07 15:47:19.000000000 +0200
+++ epg.h	2007-12-23 22:10:31.000000000 +0100
@@ -164,11 +164,15 @@ class cSchedules : public cList<cSchedul
   friend class cSchedulesLock;
 private:
   cRwLock rwlock;
+  cHash<cSchedule> schedulesHash;
   static cSchedules schedules;
   static const char *epgDataFileName;
   static time_t lastCleanup;
   static time_t lastDump;
   static time_t modified;
+  void HashSchedule(cSchedule *Schedule);
+  void UnhashSchedule(cSchedule *Schedule);
+  static unsigned int HashKey(tChannelID ChannelID);
 public:
   static void SetEpgDataFileName(const char *FileName);
   static const cSchedules *Schedules(cSchedulesLock &SchedulesLock);
--- ../vdr-1.5.12-orig/epg.c	2007-06-10 14:52:19.000000000 +0200
+++ epg.c	2007-12-23 22:10:31.000000000 +0100
@@ -1045,6 +1045,7 @@ cSchedule *cSchedules::AddSchedule(tChan
   if (!p) {
      p = new cSchedule(ChannelID);
      Add(p);
+     HashSchedule(p);
      cChannel *channel = Channels.GetByChannelID(ChannelID);
      if (channel)
         channel->schedule = p;
@@ -1055,10 +1056,14 @@ cSchedule *cSchedules::AddSchedule(tChan
 const cSchedule *cSchedules::GetSchedule(tChannelID ChannelID) const
 {
   ChannelID.ClrRid();
-  for (cSchedule *p = First(); p; p = Next(p)) {
-      if (p->ChannelID() == ChannelID)
-         return p;
-      }
+  cList<cHashObject> *list = schedulesHash.GetList(HashKey(ChannelID));
+  if (list) {
+     for (cHashObject *hobj = list->First(); hobj; hobj = list->Next(hobj)) {
+         cSchedule *p = (cSchedule *)hobj->Object();
+         if (p->ChannelID() == ChannelID)
+            return p;
+         }
+     }
   return NULL;
 }
 
@@ -1074,7 +1079,23 @@ const cSchedule *cSchedules::GetSchedule
   if (Channel->schedule == &DummySchedule && AddIfMissing) {
      cSchedule *Schedule = new cSchedule(Channel->GetChannelID());
      ((cSchedules *)this)->Add(Schedule);
+     ((cSchedules *)this)->HashSchedule(Schedule);
      Channel->schedule = Schedule;
      }
   return Channel->schedule != &DummySchedule? Channel->schedule : NULL;
 }
+
+void cSchedules::HashSchedule(cSchedule *Schedule)
+{
+  schedulesHash.Add(Schedule, HashKey(Schedule->ChannelID().ClrRid()));
+}
+
+void cSchedules::UnhashSchedule(cSchedule *Schedule)
+{
+  schedulesHash.Del(Schedule, HashKey(Schedule->ChannelID().ClrRid()));
+}
+
+unsigned int cSchedules::HashKey(tChannelID ChannelID)
+{
+  return (unsigned int)((ChannelID.Nid() << 16 | ChannelID.Source()) ^ (ChannelID.Tid() << 16 | ChannelID.Sid()) ^ ChannelID.Rid());
+}
_______________________________________________
vdr mailing list
vdr@xxxxxxxxxxx
http://www.linuxtv.org/cgi-bin/mailman/listinfo/vdr

[Index of Archives]     [Linux Media]     [Asterisk]     [DCCP]     [Netdev]     [Xorg]     [Util Linux NG]     [Xfree86]     [Big List of Linux Books]     [Fedora Users]     [Fedora Women]     [ALSA Devel]     [Linux USB]

  Powered by Linux