Ticket #3326: multi-sched-multimap-v4.patch

File multi-sched-multimap-v4.patch, 28.2 KB (added by danielk, 17 years ago)

Various scheduling optimizations, some good, some bad.

  • programs/mythbackend/scheduler.h

     
    22#define SCHEDULER_H_
    33
    44// C++ headers
     5#include <map>
    56#include <deque>
    67#include <vector>
    78using namespace std;
     
    3536typedef RecList::iterator RecIter;
    3637
    3738typedef vector<int> InputGroupList;
     39typedef QMap<int, RecList> CardListMap;
    3840
     41typedef multimap<uint64_t, ProgramInfo*> ConflictMap;
     42
    3943class Scheduler : public QObject
    4044{
    4145  public:
     
    99103    void PruneOverlaps(void);
    100104    void BuildListMaps(void);
    101105    void ClearListMaps(void);
     106
     107    bool IsConflicting(const ProgramInfo *p, const ProgramInfo *q,
     108                       bool openEnd) const;
     109
     110    bool IsSameProgram(const ProgramInfo *a, const ProgramInfo *b) const;
     111    bool IsSameTimeslot(const ProgramInfo *a, const ProgramInfo *b) const;
     112
    102113    bool FindNextConflict(const RecList &cardlist,
    103114                          const ProgramInfo *p, RecConstIter &iter,
    104115                          bool openEnd = false) const;
    105     const ProgramInfo *FindConflict(const QMap<int, RecList> &reclists,
    106                                     const ProgramInfo *p, bool openEnd = false) const;
     116
     117    ProgramInfo *FindAnyConflict(
     118        ConflictMap &map, const ProgramInfo *p, bool openend) const;
     119
     120    RecList FindAllConflict(
     121        ConflictMap &map, const ProgramInfo *p, bool openend) const;
     122
    107123    void MarkOtherShowings(ProgramInfo *p);
    108124    void MarkShowingsList(RecList &showinglist, ProgramInfo *p);
    109125    void BackupRecStatus(void);
     
    137153    RecList reclist;
    138154    RecList worklist;
    139155    RecList retrylist;
    140     QMap<int, RecList> cardlistmap;
     156    ConflictMap conflictmap;
     157    QMap<const ProgramInfo*, RecList*> splistmap;
    141158    QMap<int, RecList> recordidlistmap;
    142159    QMap<QString, RecList> titlelistmap;
    143160    QMap<int, InputGroupList> inputgroupmap;
     
    170187    QDateTime livetvTime;
    171188    int livetvpriority;
    172189    QMap<QString, bool> hasLaterList;
     190
     191    // cache IsSameProgram()
     192    typedef pair<const ProgramInfo*,const ProgramInfo*> IsSameKey;
     193    typedef QMap<IsSameKey,bool> IsSameCacheType;
     194    mutable IsSameCacheType cache_is_same_program;
     195    mutable IsSameCacheType cache_is_same_timeslot;
    173196};
    174197
    175198#endif
  • programs/mythbackend/scheduler.cpp

     
    302302
    303303    BuildInputGroupMap();
    304304
    305     VERBOSE(VB_SCHEDULE, "BuildWorkList...");
     305    VERBOSE(VB_IMPORTANT, "BuildWorkList...");
    306306    BuildWorkList();
    307     VERBOSE(VB_SCHEDULE, "AddNewRecords...");
     307    VERBOSE(VB_IMPORTANT, "AddNewRecords...");
    308308    AddNewRecords();
    309     VERBOSE(VB_SCHEDULE, "AddNotListed...");
     309    VERBOSE(VB_IMPORTANT, "AddNotListed...");
    310310    AddNotListed();
    311311
    312     VERBOSE(VB_SCHEDULE, "Sort by time...");
     312    VERBOSE(VB_IMPORTANT, "Sort by time...");
    313313    SORT_RECLIST(worklist, comp_overlap);
    314     VERBOSE(VB_SCHEDULE, "PruneOverlaps...");
     314    VERBOSE(VB_IMPORTANT, "PruneOverlaps...");
    315315    PruneOverlaps();
    316316
    317     VERBOSE(VB_SCHEDULE, "Sort by priority...");
     317    VERBOSE(VB_IMPORTANT, "Sort by priority...");
    318318    SORT_RECLIST(worklist, comp_priority);
    319     VERBOSE(VB_SCHEDULE, "BuildListMaps...");
     319    VERBOSE(VB_IMPORTANT, "BuildListMaps...");
    320320    BuildListMaps();
    321     VERBOSE(VB_SCHEDULE, "SchedNewRecords...");
     321    VERBOSE(VB_IMPORTANT, "SchedNewRecords...");
    322322    SchedNewRecords();
    323     VERBOSE(VB_SCHEDULE, "SchedPreserveLiveTV...");
     323    VERBOSE(VB_IMPORTANT, "SchedPreserveLiveTV...");
    324324    SchedPreserveLiveTV();
    325     VERBOSE(VB_SCHEDULE, "ClearListMaps...");
     325    VERBOSE(VB_IMPORTANT, "ClearListMaps...");
    326326    ClearListMaps();
    327327
    328     VERBOSE(VB_SCHEDULE, "Sort by time...");
     328    VERBOSE(VB_IMPORTANT, "Sort by time...");
    329329    SORT_RECLIST(worklist, comp_redundant);
    330     VERBOSE(VB_SCHEDULE, "PruneRedundants...");
     330    VERBOSE(VB_IMPORTANT, "PruneRedundants...");
    331331    PruneRedundants();
    332332
    333     VERBOSE(VB_SCHEDULE, "Sort by time...");
     333    VERBOSE(VB_IMPORTANT, "Sort by time...");
    334334    SORT_RECLIST(worklist, comp_recstart);
    335     VERBOSE(VB_SCHEDULE, "ClearWorkList...");
     335    VERBOSE(VB_IMPORTANT, "ClearWorkList...");
    336336    bool res = ClearWorkList();
    337337
    338338    return res;
     
    750750    erase_nulls(worklist);
    751751}
    752752
     753const static bool is_conflict_dbg = false;
     754static vector<uint> stats_i;
     755static vector<uint> stats_j;
     756static vector<uint> stats_k;
     757static vector<uint> stats_found;
     758static vector<uint> stats_all_i;
     759static vector<uint> stats_all_j;
     760static vector<uint> stats_all_k;
     761static vector<uint> stats_all_found;
     762
     763static uint insert(ConflictMap &cmap, const InputGroupList &input_groups, ProgramInfo *p)
     764{
     765    uint insert_cnt = 0;
     766    uint64_t btimeX = min(p->recstartts.toTime_t(),
     767                          p->startts.toTime_t());
     768    uint64_t etimeX = max(p->recendts.toTime_t(),
     769                          p->endts.toTime_t());
     770
     771    InputGroupList::const_iterator it = input_groups.begin();
     772    for (; it != input_groups.end(); ++it)
     773    {
     774        uint64_t btime = (((uint64_t)(*it)) << 32) + btimeX;
     775        uint64_t etime = (((uint64_t)(*it)) << 32) + etimeX;
     776        for (; btime < etime; btime += 2000)
     777        {
     778            cmap.insert(pair<uint64_t, ProgramInfo*>(btime, p));
     779            insert_cnt++;
     780        }
     781        cmap.insert(pair<uint64_t, ProgramInfo*>(etime, p));
     782        insert_cnt++;
     783    }
     784
     785    return insert_cnt;
     786}
     787
    753788void Scheduler::BuildListMaps(void)
    754789{
     790    uint tcnt = 0, ccnt = 0;
     791    VERBOSE(VB_IMPORTANT, "BuildListMaps -- begin");
     792
    755793    RecIter i = worklist.begin();
    756794    for ( ; i != worklist.end(); i++)
    757795    {
     
    760798            p->recstatus == rsWillRecord ||
    761799            p->recstatus == rsUnknown)
    762800        {
    763             cardlistmap[p->cardid].push_back(p);
     801            ++tcnt;
     802            ccnt += insert(conflictmap, inputgroupmap[p->inputid], p);
    764803            titlelistmap[p->title].push_back(p);
    765804            recordidlistmap[p->recordid].push_back(p);
    766805        }
    767806    }
     807
     808    VERBOSE(VB_IMPORTANT, "BuildListMaps title cnt: "
     809            <<tcnt<<" conflict cnt: "<<ccnt);
     810
     811    gContext->ClearSettingsCache();
     812    uint max_sz = gContext->GetNumSetting("BuildListMapsTemp", 100);
     813    uint64_t mht = 0, mhc = 0;
     814
     815    QMap<QString, RecList>::const_iterator it = titlelistmap.begin();
     816    for (; it != titlelistmap.end(); ++it)
     817    {
     818        uint sz = (*it).size();
     819
     820        if (sz < max_sz)
     821            continue;
     822
     823        VERBOSE(VB_IMPORTANT, QString("sz %1 title: '%2'")
     824                .arg(sz,4).arg(it.key()));
     825
     826        uint64_t startt, endt; rdtsc(startt);
     827        for (uint i = 0; i < sz; i++)
     828            splistmap[(*it)[i]] = NULL;
     829
     830        for (uint i = 0; i < sz; i++)
     831        {
     832            const ProgramInfo *p = (*it)[i];
     833            for (uint j = i+1; j < sz; j++)
     834            {
     835                const ProgramInfo *q = (*it)[j];
     836                if (!p->IsSameTimeslot(*q) || !IsSameProgram(p,q))
     837                    continue;
     838
     839                // place q in p's set
     840                if (!splistmap[p])
     841                {
     842                    splistmap[p] = new RecList;
     843                    splistmap[p]->push_back((*it)[i]);
     844                }
     845
     846                splistmap[q] = splistmap[p];
     847                splistmap[q]->push_back((*it)[j]);
     848
     849                break;
     850            }
     851        }
     852        rdtsc(endt); mht += (endt - startt); mhc++;
     853    }
     854    cout<<QString("Build splistmap:     %1 %2").arg(mhc,4).arg(mht,12)<<endl;
     855
     856    VERBOSE(VB_IMPORTANT, "BuildListMaps -- end");
     857
     858    stats_i.clear();
     859    stats_j.clear();
     860    stats_k.clear();
     861    stats_found.clear();
     862    stats_all_i.clear();
     863    stats_all_j.clear();
     864    stats_all_k.clear();
     865    stats_all_found.clear();
    768866}
    769867
    770868void Scheduler::ClearListMaps(void)
    771869{
    772     cardlistmap.clear();
     870    conflictmap.clear();
    773871    titlelistmap.clear();
    774872    recordidlistmap.clear();
     873    cache_is_same_program.clear();
     874    cache_is_same_timeslot.clear();
     875    // TODO clear out splistmap RecList's
     876    splistmap.clear();
    775877}
    776878
    777 bool Scheduler::FindNextConflict(
    778     const RecList     &cardlist,
    779     const ProgramInfo *p,
    780     RecConstIter      &j,
    781     bool               openEnd) const
     879bool Scheduler::IsConflicting(
     880    const ProgramInfo *p, const ProgramInfo *q, bool openEnd) const
    782881{
    783     bool is_conflict_dbg = false;
     882    //cerr<<":";
     883    if (!Recording(q))
     884        return false;
    784885
    785     for ( ; j != cardlist.end(); j++)
    786     {
    787         const ProgramInfo *q = *j;
     886    if (p == q)
     887        return false;
    788888
    789         if (p == q)
    790             continue;
     889    if (is_conflict_dbg)
     890        cout << QString("\n  comparing with '%1' ").arg(q->title);
    791891
    792         if (!Recording(q))
    793             continue;
    794 
     892    if (p->cardid != 0 && (p->cardid != q->cardid) &&
     893        !GetSharedInputGroup(p->inputid, q->inputid))
     894    {
    795895        if (is_conflict_dbg)
    796             cout << QString("\n  comparing with '%1' ").arg(q->title);
     896            cout << "  cardid== ";
     897        return false;
     898    }
    797899
    798         if (p->cardid != 0 && (p->cardid != q->cardid) &&
    799             !GetSharedInputGroup(p->inputid, q->inputid))
     900    if (openEnd && p->chanid != q->chanid)
     901    {
     902        if (p->recendts < q->recstartts || p->recstartts > q->recendts)
    800903        {
    801904            if (is_conflict_dbg)
    802                 cout << "  cardid== ";
    803             continue;
     905                cout << "  no-overlap ";
     906            return false;
    804907        }
    805 
    806         if (openEnd && p->chanid != q->chanid)
     908    }
     909    else
     910    {
     911        if (p->recendts <= q->recstartts || p->recstartts >= q->recendts)
    807912        {
    808             if (p->recendts < q->recstartts || p->recstartts > q->recendts)
    809             {
    810                 if (is_conflict_dbg)
    811                     cout << "  no-overlap ";
    812                 continue;
    813             }
     913            if (is_conflict_dbg)
     914                cout << "  no-overlap ";
     915            return false;
    814916        }
    815         else
    816         {
    817             if (p->recendts <= q->recstartts || p->recstartts >= q->recendts)
    818             {
    819                 if (is_conflict_dbg)
    820                     cout << "  no-overlap ";
    821                 continue;
    822             }
    823         }
     917    }
    824918
    825         if (is_conflict_dbg)
    826             cout << "\n" <<
    827                 QString("  cardid's: %1, %2 ").arg(p->cardid).arg(q->cardid) +
    828                 QString("Shared input group: %1 ")
    829                 .arg(GetSharedInputGroup(p->inputid, q->inputid)) +
    830                 QString("mplexid's: %1, %2")
    831                 .arg(p->GetMplexID()).arg(q->GetMplexID());
     919    if (is_conflict_dbg)
     920    {
     921        cout << "\n" <<
     922            QString("  cardid's: %1, %2 ").arg(p->cardid).arg(q->cardid) +
     923            QString("Shared input group: %1 ")
     924            .arg(GetSharedInputGroup(p->inputid, q->inputid)) +
     925            QString("mplexid's: %1, %2")
     926            .arg(p->GetMplexID()).arg(q->GetMplexID());
     927    }
    832928
    833         // if two inputs are in the same input group we have a conflict
    834         // unless the programs are on the same multiplex.
    835         if (p->cardid && (p->cardid != q->cardid) &&
    836             GetSharedInputGroup(p->inputid, q->inputid) &&
    837             p->GetMplexID() && (p->GetMplexID() == q->GetMplexID()))
    838         {
    839             continue;
    840         }
     929    // if two inputs are in the same input group we have a conflict
     930    // unless the programs are on the same multiplex.
     931    if (p->cardid && (p->cardid != q->cardid) &&
     932        GetSharedInputGroup(p->inputid, q->inputid) &&
     933        p->GetMplexID() && (p->GetMplexID() == q->GetMplexID()))
     934    {
     935        return false;
     936    }
    841937
    842         if (is_conflict_dbg)
    843             cout << "\n  Found conflict" << endl;
     938    if (is_conflict_dbg)
     939        cout << "\n  Found conflict" << endl;
    844940
    845         return true;
     941    return true;
     942}
     943
     944bool Scheduler::IsSameProgram(
     945    const ProgramInfo *a, const ProgramInfo *b) const
     946{
     947    IsSameKey X(a,b);
     948    IsSameCacheType::const_iterator it = cache_is_same_program.find(X);
     949    if (it != cache_is_same_program.end())
     950        return *it;
     951
     952    IsSameKey Y(b,a);
     953    bool val = a->IsSameProgram(*b);
     954    cache_is_same_program[X] = val;
     955    cache_is_same_program[Y] = val;
     956    return val;
     957}
     958
     959bool Scheduler::IsSameTimeslot(
     960    const ProgramInfo *a, const ProgramInfo *b) const
     961{
     962    IsSameKey X(a,b);
     963    IsSameCacheType::const_iterator it = cache_is_same_timeslot.find(X);
     964    if (it != cache_is_same_timeslot.end())
     965        return *it;
     966
     967    IsSameKey Y(b,a);
     968    bool val = a->IsSameTimeslot(*b);
     969    cache_is_same_timeslot[X] = val;
     970    cache_is_same_timeslot[Y] = val;
     971    return val;
     972}
     973
     974bool Scheduler::FindNextConflict(
     975    const RecList     &cardlist,
     976    const ProgramInfo *p,
     977    RecConstIter      &j,
     978    bool               openEnd) const
     979{
     980    cerr<<"FindNextConflict(RecList...)"<<endl;
     981    for ( ; j != cardlist.end(); j++)
     982    {
     983        if (IsConflicting(p, *j, openEnd))
     984            return true;
    846985    }
    847986
    848987    if (is_conflict_dbg)
     
    851990    return false;
    852991}
    853992
    854 const ProgramInfo *Scheduler::FindConflict(
    855     const QMap<int, RecList> &reclists,
    856     const ProgramInfo        *p,
    857     bool openend) const
     993ProgramInfo *Scheduler::FindAnyConflict(
     994    ConflictMap &cmap, const ProgramInfo *p, bool openend) const
    858995{
    859     bool is_conflict_dbg = false;
     996    QMap<ProgramInfo*,ProgramInfo*> dups;
     997    uint i = 0, j = 0, k = 0;
     998    uint64_t btimeX = p->recstartts.toTime_t() - 2000;
     999    uint64_t etimeX = p->recendts.toTime_t() + 1;
    8601000
    861     QMap<int, RecList>::const_iterator it = reclists.begin();
    862     for (; it != reclists.end(); ++it)
     1001    const InputGroupList &ingrp = inputgroupmap[p->inputid];
     1002    InputGroupList::const_iterator grpit = ingrp.begin();
     1003    const ProgramInfo *last = NULL;
     1004    for (; grpit != ingrp.end(); ++grpit)
    8631005    {
    864         if (is_conflict_dbg)
     1006        uint64_t btime = btimeX | (((uint64_t)*grpit) << 32);
     1007        ConflictMap::iterator beg = cmap.lower_bound(btime);
     1008        uint64_t etime = etimeX | (((uint64_t)*grpit) << 32);
     1009        ConflictMap::iterator end = cmap.upper_bound(etime);
     1010
     1011        ConflictMap::iterator it = beg;
     1012        for (; it != end; ++it)
    8651013        {
    866             cout << QString("Checking '%1' for conflicts on cardid %2")
    867                 .arg(p->title).arg(it.key());
     1014            if ((it->second == last) || dups[it->second])
     1015            {
     1016                i++;
     1017                continue;
     1018            }
     1019            last = dups[it->second] = it->second;
     1020            j++;
     1021            if (IsConflicting(p, it->second, openend))
     1022            {
     1023                stats_i.push_back(i);
     1024                stats_j.push_back(j);
     1025                stats_k.push_back(k);
     1026                stats_found.push_back(1);
     1027                return it->second;
     1028            }
    8681029        }
     1030    }
    8691031
    870         const RecList &cardlist = *it;
    871         RecConstIter k = cardlist.begin();
    872         if (FindNextConflict(cardlist, p, k, openend))
     1032    stats_i.push_back(i);
     1033    stats_j.push_back(j);
     1034    stats_k.push_back(k);
     1035    stats_found.push_back(0);
     1036
     1037    return NULL;
     1038}
     1039
     1040RecList Scheduler::FindAllConflict(
     1041    ConflictMap &cmap, const ProgramInfo *p, bool openend) const
     1042{
     1043    RecList list;
     1044
     1045    QMap<ProgramInfo*,ProgramInfo*> dups;
     1046    uint i = 0, j = 0, k = 0;
     1047    uint64_t btimeX = p->recstartts.toTime_t() - 2000;
     1048    uint64_t etimeX = p->recendts.toTime_t() + 1;
     1049
     1050    const InputGroupList &ingrp = inputgroupmap[p->inputid];
     1051    InputGroupList::const_iterator grpit = ingrp.begin();
     1052    const ProgramInfo *last = NULL;
     1053    for (; grpit != ingrp.end(); ++grpit)
     1054    {
     1055        uint64_t btime = btimeX | (((uint64_t)*grpit) << 32);
     1056        ConflictMap::iterator beg = cmap.lower_bound(btime);
     1057        uint64_t etime = etimeX | (((uint64_t)*grpit) << 32);
     1058        ConflictMap::iterator end = cmap.upper_bound(etime);
     1059
     1060        ConflictMap::iterator it = beg;
     1061        for (; it != end; ++it)
    8731062        {
    874             return *k;
     1063            if ((it->second == last) || dups[it->second])
     1064            {
     1065                i++;
     1066                continue;
     1067            }
     1068            last = dups[it->second] = it->second;
     1069
     1070            const ProgramInfo *q = last;
     1071            if (openend && p->chanid != q->chanid)
     1072            {
     1073                if (p->recendts < q->recstartts || p->recstartts > q->recendts)
     1074                {
     1075                    k++;
     1076                    continue;
     1077                }
     1078            }
     1079            else
     1080            {
     1081                if (p->recendts <= q->recstartts || p->recstartts >= q->recendts)
     1082                {
     1083                    k++;
     1084                    continue;
     1085                }
     1086            }
     1087
     1088            j++;
     1089            if (IsConflicting(p, it->second, openend))
     1090                list.push_back(it->second);
    8751091        }
    8761092    }
    8771093
    878     return NULL;
     1094    stats_all_i.push_back(i);
     1095    stats_all_j.push_back(j);
     1096    stats_all_k.push_back(k);
     1097    stats_all_found.push_back(list.size());
     1098
     1099    return list;
    8791100}
    8801101
    8811102void Scheduler::MarkOtherShowings(ProgramInfo *p)
    8821103{
    883     RecList *showinglist = &titlelistmap[p->title];
     1104    QMap<const ProgramInfo*, RecList*>::iterator sit = splistmap.find(p);
     1105    RecList *showinglist = NULL;
     1106    if (sit != splistmap.end())
     1107        showinglist = *sit;
     1108    else
     1109        showinglist = &titlelistmap[p->title];
    8841110
    885     MarkShowingsList(*showinglist, p);
     1111    if (showinglist)
     1112        MarkShowingsList(*showinglist, p);
    8861113
    8871114    if (p->rectype == kFindOneRecord ||
    8881115        p->rectype == kFindDailyRecord ||
     
    9011128
    9021129void Scheduler::MarkShowingsList(RecList &showinglist, ProgramInfo *p)
    9031130{
     1131    uint me = 0;
     1132    uint ign = 0;
     1133    uint sametime = 0;
     1134    uint later = 0;
     1135    uint earlier = 0;
     1136    uint other = 0;
     1137
    9041138    RecIter i = showinglist.begin();
    9051139    for ( ; i != showinglist.end(); i++)
    9061140    {
    9071141        ProgramInfo *q = *i;
    9081142        if (q == p)
     1143        {
     1144            me++;
    9091145            continue;
     1146        }
    9101147        if (q->recstatus != rsUnknown &&
    9111148            q->recstatus != rsWillRecord &&
    9121149            q->recstatus != rsEarlierShowing &&
    9131150            q->recstatus != rsLaterShowing)
     1151        {
     1152            ign++;
    9141153            continue;
     1154        }
     1155
    9151156        if (q->IsSameTimeslot(*p))
     1157        {
    9161158            q->recstatus = rsLaterShowing;
     1159            sametime++;
     1160        }
    9171161        else if (q->rectype != kSingleRecord &&
    9181162                 q->rectype != kOverrideRecord &&
    919                  q->IsSameProgram(*p))
     1163                 IsSameProgram(q,p))
    9201164        {
    9211165            if (q->recstartts < p->recstartts)
     1166            {
     1167                later++;
    9221168                q->recstatus = rsLaterShowing;
     1169            }
    9231170            else
     1171            {
     1172                earlier++;
    9241173                q->recstatus = rsEarlierShowing;
     1174            }
    9251175        }
     1176        else
     1177        {
     1178            other++;
     1179        }
    9261180    }
     1181
     1182    uint max_sz = gContext->GetNumSetting("BuildListMapsTemp", 100);
     1183    if (showinglist.size() >= max_sz)
     1184    {
     1185        cout<<QString("title: %1").arg(p->title,20)
     1186            <<"m:"<<me<<" ign: "<<ign<<" st: "<<sametime<<" sml: "<<later
     1187            <<" sme: "<<earlier<<" other: "<<other<<endl;
     1188    }
    9271189}
    9281190
    9291191void Scheduler::BackupRecStatus(void)
     
    9531215    if (p->recstatus == rsRecording)
    9541216        return false;
    9551217
    956     RecList *showinglist = &titlelistmap[p->title];
     1218    QMap<const ProgramInfo*, RecList*>::iterator sit = splistmap.find(p);
     1219    RecList *showinglist = NULL;
     1220    if (sit != splistmap.end())
     1221        showinglist = *sit;
     1222    else
     1223        showinglist = &titlelistmap[p->title];
    9571224
     1225    if (!showinglist)
     1226        return false;
     1227
    9581228    if (p->rectype == kFindOneRecord ||
    9591229        p->rectype == kFindDailyRecord ||
    9601230        p->rectype == kFindWeeklyRecord)
     
    9801250            continue;
    9811251        if (!p->IsSameTimeslot(*q))
    9821252        {
    983             if (!p->IsSameProgram(*q))
     1253            if (!IsSameProgram(p,q))
    9841254                continue;
    9851255            if ((p->rectype == kSingleRecord ||
    9861256                 p->rectype == kOverrideRecord))
     
    10321302            }
    10331303        }
    10341304
    1035         const ProgramInfo *conflict = FindConflict(cardlistmap, q);
     1305        ProgramInfo *conflict = FindAnyConflict(conflictmap, q, false);
    10361306        if (conflict)
    10371307        {
    10381308            PrintRec(conflict, "        !");
     
    10671337    return false;
    10681338}
    10691339
     1340static QMap<QString,uint> othershow;
     1341
    10701342void Scheduler::SchedNewRecords(void)
    10711343{
    10721344    VERBOSE(VB_SCHEDULE, "Scheduling:");
     1345    uint64_t mot = 0, moc = 0;
     1346    uint64_t fat = 0, fac = 0;
     1347    uint64_t mot2 = 0, moc2 = 0;
     1348    uint64_t mot3 = 0, moc3 = 0;
     1349    uint64_t mht = 0, mhc = 0;
    10731350
    10741351    bool openEnd = (bool)gContext->GetNumSetting("SchedOpenEnd", 0);
    10751352
     1353    uint max_sz = gContext->GetNumSetting("BuildListMapsTemp", 100);
     1354    othershow.clear();
     1355
    10761356    RecIter i = worklist.begin();
    10771357    while (i != worklist.end())
    10781358    {
    10791359        ProgramInfo *p = *i;
    10801360        if (p->recstatus == rsRecording)
     1361        {
     1362            uint64_t startt, endt; rdtsc(startt);
    10811363            MarkOtherShowings(p);
     1364            rdtsc(endt); mot += (endt - startt); moc++;
     1365        }
    10821366        else if (p->recstatus == rsUnknown)
    10831367        {
    1084             const ProgramInfo *conflict = FindConflict(cardlistmap, p, openEnd);
     1368            uint64_t startt, endt; rdtsc(startt);
     1369            ProgramInfo *conflict = FindAnyConflict(conflictmap, p, openEnd);
     1370            rdtsc(endt); fat += (endt - startt); fac++;
     1371
    10851372            if (!conflict)
    10861373            {
    10871374                p->recstatus = rsWillRecord;
     
    11011388                    VERBOSE(VB_GENERAL, msg);
    11021389                }
    11031390 
    1104                 MarkOtherShowings(p);
     1391                RecList *showinglist = &titlelistmap[p->title];
     1392                if (showinglist->size() >= max_sz)
     1393                {
     1394                    othershow[p->title] = showinglist->size();
     1395                    uint64_t startt, endt; rdtsc(startt);
     1396                    MarkOtherShowings(p);
     1397                    rdtsc(endt);
     1398                    mot2 += (endt - startt); moc2++;
     1399                }
     1400                else
     1401                {
     1402                    uint64_t startt, endt; rdtsc(startt);
     1403                    MarkOtherShowings(p);
     1404                    rdtsc(endt);
     1405                    mot3 += (endt - startt); moc3++;
     1406                }
     1407
    11051408                PrintRec(p, "  +");
    11061409            }
    11071410            else
     
    11161419        i++;
    11171420        if (i == worklist.end() || lastpri != (*i)->recpriority)
    11181421        {
     1422            uint64_t startt, endt; rdtsc(startt);
    11191423            MoveHigherRecords();
     1424            rdtsc(endt); mht += (endt - startt); mhc++;
    11201425            retrylist.clear();
    11211426        }
    11221427    }
     1428
     1429    cout<<endl;
     1430    VERBOSE(VB_IMPORTANT, "\nSchedulingNewRecords time report");
     1431    cout<<QString("MarkOtherShowings #1:%1 %2").arg(moc,4).arg(mot,12)<<endl;
     1432    //cout<<QString("MarkOther... #2>=%0:%1 %2").arg(max_sz).arg(moc2,4).arg(mot2,12)<<endl;
     1433    cout<<QString("MarkOtherShowings #2:%1 %2")
     1434        .arg(moc2+moc3,4).arg(mot2+mot3,12)<<endl;
     1435    cout<<QString("FindAnyConflict:     %1 %2").arg(fac,4).arg(fat,12)<<endl;
     1436    cout<<QString("MoveHigherRecords:   %1 %2").arg(mhc,4).arg(mht,12)<<endl;
     1437    cout<<endl;
     1438    cout<<QString("OtherShowings >= %1").arg(max_sz)<<endl;
     1439    QMap<QString,uint>::iterator it = othershow.begin();
     1440    for (; it != othershow.end(); ++it)
     1441        cout<<QString("%1: %2").arg(it.key(),20).arg(*it, 5)<<endl;
     1442    cout<<endl;
    11231443}
    11241444
    11251445void Scheduler::MoveHigherRecords(bool move_this)
    11261446{
     1447    VERBOSE(VB_IMPORTANT, "MoveHigherRecords("<<move_this<<
     1448            ") retrylist.size(): "<<retrylist.size());
     1449    uint64_t mht = 0, mhc = 0;
     1450    uint64_t mht2 = 0, mhc2 = 0;
     1451    uint64_t mht3 = 0, mhc3 = 0;
     1452    uint64_t bst = 0, bsc = 0;
     1453    uint64_t mot = 0, moc = 0;
     1454    uint64_t rst = 0, rsc = 0;
     1455
     1456
     1457    uint64_t startt, endt; rdtsc(startt);
     1458
    11271459    RecIter i = retrylist.begin();
    11281460    for ( ; i != retrylist.end(); i++)
    11291461    {
     
    11311463        if (p->recstatus != rsUnknown)
    11321464            continue;
    11331465
     1466        print_verbose_messages |= VB_SCHEDULE;
    11341467        PrintRec(p, "  ?");
     1468        print_verbose_messages &= ~VB_SCHEDULE;
    11351469
     1470        uint64_t startt, endt; rdtsc(startt);
     1471        bool cont = false;
    11361472        if (move_this && TryAnotherShowing(p))
     1473            cont = true;;
     1474        rdtsc(endt); mht += (endt - startt); mhc++;
     1475        if (cont)
    11371476            continue;
    11381477
    1139         BackupRecStatus();
     1478        {
     1479            uint64_t startt, endt; rdtsc(startt);
     1480            BackupRecStatus();
     1481            rdtsc(endt); bst += (endt - startt); bsc++;
     1482        }
     1483
    11401484        p->recstatus = rsWillRecord;
    11411485        if (move_this)
     1486        {
     1487            uint64_t startt, endt; rdtsc(startt);
    11421488            MarkOtherShowings(p);
     1489            rdtsc(endt); mot += (endt - startt); moc++;
     1490        }
    11431491
    1144         RecList cardlist;
    1145         QMap<int, RecList>::const_iterator it = cardlistmap.begin();
    1146         for (; it != cardlistmap.end(); ++it)
     1492
     1493        RecList conflicts = FindAllConflict(conflictmap, p, false);
     1494        RecList::iterator k = conflicts.begin();
     1495        for (; k != conflicts.end(); ++k)
    11471496        {
    1148             RecConstIter it2 = (*it).begin();
    1149             for (; it2 != (*it).end(); ++it2)
    1150                 cardlist.push_back(*it2);
    1151         }
    1152        
    1153         RecConstIter k = cardlist.begin();
    1154         for ( ; FindNextConflict(cardlist, p, k); k++)
    1155         {
     1497            uint64_t startt, endt; rdtsc(startt);
    11561498            if ((p->recpriority < (*k)->recpriority && !schedMoveHigher &&
    1157                 move_this) || !TryAnotherShowing(*k, !move_this))
     1499                 move_this) || !TryAnotherShowing(*k, !move_this))
    11581500            {
     1501                uint64_t startt, endt; rdtsc(startt);
    11591502                RestoreRecStatus();
     1503                rdtsc(endt); rst += (endt - startt); rsc++;
    11601504                break;
    11611505            }
     1506            rdtsc(endt); mht2 += (endt - startt); mhc2++;
    11621507        }
    11631508
    11641509        if (move_this && p->recstatus == rsWillRecord)
    11651510            PrintRec(p, "  +");
    11661511    }
     1512    rdtsc(endt); mht3 += (endt - startt); mhc3++;
     1513
     1514    cout<<QString("MHR1: %1 %2").arg(mhc,4).arg(mht,12)<<endl;
     1515    cout<<QString("MHR2: %1 %2").arg(mhc2,4).arg(mht2,12)<<endl;
     1516    cout<<QString("BRS:  %1 %2").arg(bsc,4).arg(bst,12)<<endl;
     1517    cout<<QString("RRS:  %1 %2").arg(rsc,4).arg(rst,12)<<endl;
     1518    cout<<QString("MOS:  %1 %2").arg(moc,4).arg(mot,12)<<endl;
     1519    cout<<QString("MHRT: %1 %2").arg(mhc3,4).arg(mht3,12)<<endl;
    11671520}
    11681521
    11691522void Scheduler::PruneRedundants(void)
     
    15221875            VERBOSE(VB_GENERAL, msg);
    15231876            gContext->LogEntry("scheduler", LP_INFO, "Scheduled items", msg);
    15241877
     1878            unsigned long long itotal[4] = {0,0,0,0};
     1879            unsigned long long jtotal[4] = {0,0,0,0};
     1880            unsigned long long ktotal[4] = {0,0,0,0};
     1881            unsigned long long cnt[4] = {0,0,0,0};
     1882            uint imax[4] = {0,0,0,0}, jmax[4] = {0,0,0,0}, kmax[4] = {0,0,0,0};
     1883            for (uint i = 0; i < stats_i.size(); i++)
     1884            {
     1885                uint j = (stats_found[i]) ? 1 : 0;
     1886                cnt[j]++;
     1887                itotal[j] += stats_i[i];
     1888                imax[j] = max(imax[j], stats_i[i]);
     1889                jtotal[j] += stats_j[i];
     1890                jmax[j] = max(jmax[j], stats_j[i]);
     1891                ktotal[j] += stats_k[i];
     1892                kmax[j] = max(kmax[j], stats_k[i]);
     1893            }
     1894
     1895            for (uint i = 0; i < stats_all_i.size(); i++)
     1896            {
     1897                uint j = 2 + (stats_all_found[i]) ? 1 : 0;
     1898                cnt[j] += stats_all_found[i];
     1899                itotal[j] += stats_all_i[i];
     1900                imax[j] = max(imax[j], stats_all_i[i]);
     1901                jtotal[j] += stats_all_j[i];
     1902                jmax[j] = max(jmax[j], stats_all_j[i]);
     1903                ktotal[j] += stats_all_k[i];
     1904                kmax[j] = max(kmax[j], stats_all_k[i]);
     1905            }
     1906
     1907            for (uint i = 0; i < 4; i++)
     1908            {
     1909                VERBOSE(VB_IMPORTANT,
     1910                        QString("avg i: %1 j: %2, k: %3 max i: %4 j: %5 k: %6")
     1911                        .arg((double)itotal[i] / (double)cnt[i])
     1912                        .arg((double)jtotal[i] / (double)cnt[i])
     1913                        .arg((double)ktotal[i] / (double)cnt[i])
     1914                        .arg(imax[i]).arg(jmax[i]).arg(kmax[i]));
     1915            }
     1916
    15251917            fsInfoCacheFillTime = QDateTime::currentDateTime().addSecs(-1000);
    15261918
    15271919            lastupdate = curtime;