Ticket #1660: speedup.patch

File speedup.patch, 21.2 KB (added by ajlill@…, 20 years ago)
  • libs/libmythtv/ThreadedFileWriter.cpp

     
    88#include <sys/stat.h>
    99#include <unistd.h>
    1010#include <fcntl.h>
     11#include <sys/time.h>
     12#include <sys/resource.h>
     13#include <sys/mman.h>
    1114
    1215// MythTV headers
    1316#include "ThreadedFileWriter.h"
     
    2023#define LOC QString("TFW: ")
    2124#define LOC_ERR QString("TFW, Error: ")
    2225
    23 const uint ThreadedFileWriter::TFW_DEF_BUF_SIZE   = 2*1024*1024;
     26const uint ThreadedFileWriter::TFW_DEF_BUF_SIZE   = 8*1024*1024;
    2427const uint ThreadedFileWriter::TFW_MAX_WRITE_SIZE = TFW_DEF_BUF_SIZE / 4;
    2528const uint ThreadedFileWriter::TFW_MIN_WRITE_SIZE = TFW_DEF_BUF_SIZE / 8;
    2629
     
    9093void *ThreadedFileWriter::boot_writer(void *wotsit)
    9194{
    9295    ThreadedFileWriter *fw = (ThreadedFileWriter *)wotsit;
     96    if (gContext->GetNumSetting("WriterRealtimePriority", 0))
     97      {
     98        struct sched_param sp = {1};
     99        int status = pthread_setschedparam(
     100                pthread_self(), SCHED_FIFO, &sp);
     101        if (status)
     102          {
     103            // perror("pthread_setschedparam");
     104            VERBOSE(VB_GENERAL, QString("Setting realtime priority for file writer failed: %1.").arg(strerror(errno)));
     105          }
     106        else
     107          VERBOSE(VB_GENERAL, "Using realtime priority for file writer.");
     108      } else {
     109      // Raise scheduling priority, to avoid problems with recordings.
     110      setpriority(PRIO_PROCESS, 0, -3);
     111    }
    93112    fw->DiskLoop();
    94113    return NULL;
    95114}
     
    140159    else
    141160    {
    142161        buf = new char[TFW_DEF_BUF_SIZE + 1024];
     162        //      mlock(buf,TFW_DEF_BUF_SIZE + 1024);
    143163        bzero(buf, TFW_DEF_BUF_SIZE + 64);
    144164
    145165        tfw_buf_size = TFW_DEF_BUF_SIZE;
     
    173193
    174194    if (buf)
    175195    {
     196      //        munlock(buf,tfw_buf_size + 1024);
    176197        delete [] buf;
    177198        buf = NULL;
    178199    }
     
    300321    Flush();
    301322
    302323    buflock.lock();
     324    //    munlock(buf,tfw_buf_size+1024);
    303325    delete [] buf;
    304326    rpos = wpos = 0;
    305327    buf = new char[newSize + 1024];
     328    //    mlock(buf,newSize+1024);
    306329    bzero(buf, newSize + 64);
    307330    tfw_buf_size = newSize;
    308331    buflock.unlock();
  • libs/libmythtv/programinfo.h

     
    217217    // Keyframe positions Map
    218218    void GetPositionMap(frm_pos_map_t &, int type) const;
    219219    void ClearPositionMap(int type) const;
     220    void ClearPositionMap(int type, bool sync) const;
    220221    void SetPositionMap(frm_pos_map_t &, int type,
    221222                        long long min_frm = -1, long long max_frm = -1) const;
    222     void SetPositionMapDelta(frm_pos_map_t &, int type) const;
     223    void SetPositionMapDelta(frm_pos_map_t &, int type);
    223224
    224 
    225225    // GUI stuff
    226226    void showDetails(void) const;
    227227    void EditRecording(void);
     
    318318  private:
    319319    bool ignoreBookmark;
    320320    mutable class ScheduledRecording* record;
     321   
     322    QString inUseForWhat;
    321323
    322     QString inUseForWhat;
    323324};
    324325
    325326/** \class ProgramList
  • libs/libmythtv/tv_rec.cpp

     
    55#include <unistd.h>
    66#include <pthread.h>
    77#include <sched.h> // for sched_yield
     8#include <sys/time.h>
     9#include <sys/resource.h>
    810
    911// C++ headers
    1012#include <iostream>
     
    11251127void *TVRec::RecorderThread(void *param)
    11261128{
    11271129    RecorderBase *recorder = (RecorderBase *)param;
     1130    if (gContext->GetNumSetting("ReaderRealtimePriority", 0))
     1131      {
     1132        struct sched_param sp = {1};
     1133        int status = pthread_setschedparam(
     1134              pthread_self(), SCHED_FIFO, &sp);
     1135        if (status)
     1136          {
     1137            // perror("pthread_setschedparam");
     1138            VERBOSE(VB_GENERAL, QString("Setting realtime priority for encode failed: %1.").arg(strerror(errno)));
     1139          }
     1140        else
     1141          VERBOSE(VB_GENERAL, "Using realtime priority for encoder.");
     1142      } else {
     1143      // Raise scheduling priority, to avoid problems with recordings.
     1144      setpriority(PRIO_PROCESS, 0, -3);
     1145    }
     1146
    11281147    recorder->StartRecording();
    11291148    return NULL;
    11301149}
  • libs/libmythtv/programinfo.cpp

     
    1919#include "remoteutil.h"
    2020#include "jobqueue.h"
    2121#include "mythdbcon.h"
     22#include "asyncdb.h"
    2223
    2324using namespace std;
    2425
     
    13751376    if (playbackHost == "")
    13761377        playbackHost = m_hostname;
    13771378
     1379    // Get the original path it was recorded on
    13781380    tmpURL = GetRecordFilename(gContext->GetSettingOnHost("RecordFilePrefix",
    13791381                                                          hostname));
    13801382
     1383    // if we are playing back on the recording host, just return it
    13811384    if (playbackHost == hostname)
    13821385        return tmpURL;
    13831386
     1387    // else if we are playing back on this host, check if the path is accessable, if so, use it
    13841388    if (playbackHost == m_hostname)
    13851389    {
    13861390        QFile checkFile(tmpURL);
     
    13961400            return tmpURL;
    13971401    }
    13981402
     1403    // else contruct a url to use myth file transfer protocol
    13991404    tmpURL = QString("myth://") +
    14001405             gContext->GetSettingOnHost("BackendServerIP", hostname) + ":" +
    14011406             gContext->GetSettingOnHost("BackendServerPort", hostname) + "/" +
     
    16061611{
    16071612    filesize = fsize;
    16081613
    1609     MSqlQuery query(MSqlQuery::InitCon());
    1610     query.prepare("UPDATE recorded SET filesize = :FILESIZE"
    1611                   " WHERE chanid = :CHANID"
    1612                   " AND starttime = :STARTTIME ;");
    1613     query.bindValue(":FILESIZE", longLongToString(fsize));
    1614     query.bindValue(":CHANID", chanid);
    1615     query.bindValue(":STARTTIME", recstartts);
     1614    QString query = QString("UPDATE recorded SET filesize = %1"
     1615                            " WHERE chanid = %2"
     1616                            " AND starttime = \"%3\" ;")
     1617      .arg(longLongToString(fsize))
     1618      .arg(chanid)
     1619      .arg(recstartts.toString("yyyyMMddhhmmss"));
    16161620   
    1617     if (!query.exec() || !query.isActive())
    1618         MythContext::DBError("File size update",
    1619                              query);
     1621    gAsyncDB->AddCommand(query);
    16201622}
    16211623
    16221624/** \fn ProgramInfo::GetFilesize(void)
     
    23102312
    23112313void ProgramInfo::ClearPositionMap(int type) const
    23122314{
     2315    QString query;
     2316 
     2317    if (isVideo)
     2318    {
     2319        query = QString("DELETE FROM filemarkup"
     2320                        " WHERE filename = \"%1\"")
     2321        .arg(pathname);
     2322    }
     2323    else
     2324    {
     2325        query = QString("DELETE FROM recordedmarkup"
     2326                      " WHERE chanid = %1"
     2327                      " AND starttime = \"%2\"")
     2328        .arg(chanid)
     2329        .arg(recstartts.toString("yyyyMMddhhmmss"));
     2330    }
     2331    query += QString(" AND type = %1 ;").arg(type);
     2332                               
     2333    /* Hand it to the async thread */
     2334    gAsyncDB->AddCommand(query);
     2335}
     2336
     2337void ProgramInfo::ClearPositionMap(int type, bool sync) const
     2338{
    23132339    MSqlQuery query(MSqlQuery::InitCon());
    23142340 
    23152341    if (isVideo)
     
    24272453}
    24282454
    24292455void ProgramInfo::SetPositionMapDelta(frm_pos_map_t &posMap,
    2430                                       int type) const
     2456                                      int type)
    24312457{
    24322458    QMap<long long, long long>::Iterator i;
    2433     MSqlQuery query(MSqlQuery::InitCon());
     2459    QString insert;
    24342460
     2461    if( posMap.isEmpty() )
     2462      return;
     2463
     2464    if (isVideo)
     2465      {
     2466        insert = QString("INSERT INTO filemarkup"
     2467                         " (filename, mark, type, offset)"
     2468                         " VALUES");
     2469      }
     2470    else
     2471      {
     2472        insert = QString("INSERT INTO recordedmarkup"
     2473                         " (chanid, starttime, mark, type, offset)"
     2474                         " VALUES");
     2475      }
     2476    QString sep = " ";
     2477
     2478    /* Assemble these these updates into a single multi-row insert
     2479     * statement -- much more efficient */
    24352480    for (i = posMap.begin(); i != posMap.end(); ++i)
    24362481    {
    24372482        long long frame = i.key();
     
    24462491        QString offset_str = tempc;
    24472492
    24482493        if (isVideo)
    2449         {
    2450             query.prepare("INSERT INTO filemarkup"
    2451                           " (filename, mark, type, offset)"
    2452                           " VALUES"
    2453                           " ( :PATH , :MARK , :TYPE , :OFFSET );");
    2454             query.bindValue(":PATH", pathname);
    2455         }
     2494          {
     2495            insert += sep + QString("( \"%1\", %2, %3, %4 )")
     2496              .arg(pathname).arg(i.key()).arg(type).arg(i.data());
     2497          }
    24562498        else
    2457         {
    2458             query.prepare("INSERT INTO recordedmarkup"
    2459                           " (chanid, starttime, mark, type, offset)"
    2460                           " VALUES"
    2461                           " ( :CHANID , :STARTTIME , :MARK , :TYPE , :OFFSET );");
    2462             query.bindValue(":CHANID", chanid);
    2463             query.bindValue(":STARTTIME", recstartts);
    2464         }
    2465         query.bindValue(":MARK", frame_str);
    2466         query.bindValue(":TYPE", type);
    2467         query.bindValue(":OFFSET", offset_str);
    2468        
    2469         if (!query.exec() || !query.isActive())
    2470             MythContext::DBError("delta position map insert",
    2471                                  query);
     2499          {
     2500            insert += sep + QString("( %1 , \"%2\" , %3 , %4 , %5 )")
     2501              .arg(chanid).arg(recstartts.toString("yyyyMMddhhmmss"))
     2502              .arg(i.key()).arg(type).arg(i.data());
     2503          }
     2504        sep = ",";
    24722505    }
     2506
     2507    insert += QString(";");
     2508    /* Hand it to the async thread */
     2509    gAsyncDB->AddCommand(insert);
    24732510}
    24742511
    24752512/** \fn ProgramInfo::ReactivateRecording(void)
  • libs/libmyth/exitcodes.h

     
    5757#define BACKEND_BUGGY_EXIT_NO_CAP_CARD            GENERIC_EXIT_START-11
    5858#define BACKEND_BUGGY_EXIT_NO_CHAN_DATA           GENERIC_EXIT_START-12
    5959#define BACKEND_EXIT_START                        GENERIC_EXIT_START-12
     60#define BACKEND_EXIT_ASYNCDB_ERROR                GENERIC_EXIT_START-13
    6061
    6162// mythtranscode
    6263#define TRANSCODE_EXIT_OK                         GENERIC_EXIT_OK
  • libs/libmyth/libmyth.pro

     
    2020HEADERS += langsettings.h audiooutputnull.h
    2121HEADERS += DisplayResScreen.h util-x11.h mythdeque.h qmdcodec.h
    2222HEADERS += exitcodes.h virtualkeyboard.h mythobservable.h mythevent.h
     23HEADERS += asyncdb.h
    2324
    2425SOURCES += dialogbox.cpp lcddevice.cpp mythcontext.cpp mythwidgets.cpp
    2526SOURCES += oldsettings.cpp remotefile.cpp settings.cpp themedmenu.cpp
     
    3233SOURCES += langsettings.cpp mythdbcon.cpp audiooutputnull.cpp
    3334SOURCES += DisplayResScreen.cpp util-x11.cpp qmdcodec.cpp
    3435SOURCES += virtualkeyboard.cpp mythobservable.cpp
     36SOURCES += asyncdb.cpp
    3537
    3638INCLUDEPATH += ../libmythsamplerate ../libmythsoundtouch ../..
    3739DEPENDPATH += ../libmythsamplerate ../libmythsoundtouch
     
    5961inc.files += visual.h volumebase.h output.h langsettings.h qmdcodec.h
    6062inc.files += exitcodes.h mythconfig.h mythconfig.mak virtualkeyboard.h
    6163inc.files += mythevent.h mythobservable.h
     64inc.files += asyncdb.h
    6265
    6366using_oss {
    6467    DEFINES += USING_OSS
  • libs/libmyth/asyncdb.h

     
     1#ifndef ASYNCDB_H_
     2#define ASYNCDB_H_
     3
     4// ANSI C headers
     5#include <cstdio>
     6#include <cstdlib>
     7#include <cerrno>
     8
     9#include "mythdbcon.h"
     10
     11#include <qstring.h>
     12
     13using namespace std;
     14
     15typedef struct adb_cmd_list {
     16    struct adb_cmd_list *next;
     17    QString cmd;
     18} adb_cmd_list_t;
     19
     20class AsyncDB
     21{
     22 public:
     23    AsyncDB(void);
     24    ~AsyncDB();
     25    bool Init(void);
     26    void AddCommand(QString); 
     27
     28 private:
     29    pthread_t thread;
     30    bool threadRunning;
     31    QStringList list;
     32//    adb_cmd_list_t *list;
     33    QMutex listLock;
     34    MSqlQuery query;
     35    bool ListRunner(adb_cmd_list_t *);
     36
     37 protected:
     38    static void *StartThread(void *);
     39    void Worker(void);
     40};
     41
     42extern AsyncDB *gAsyncDB;
     43#endif
  • libs/libmyth/asyncdb.cpp

     
     1#include "asyncdb.h"
     2#include <sys/time.h>
     3#include <sys/resource.h>
     4#include <sys/mman.h>
     5
     6AsyncDB *gAsyncDB = NULL;
     7#define ADB QString("AsyncDB: ")
     8
     9/** \class AsyncDB
     10 *  \brief This class supports asynchronous database inserts.
     11 *
     12 *   This class allows us to toss those database queries for which
     13 *   we do not require values or status to be run by a separate thread.
     14 *   This helps the enocder threads to keep up with the datastream.
     15 */
     16
     17/** \fn AsyncDB
     18 *  \brief Initialize the class
     19 */
     20AsyncDB::AsyncDB(void):
     21  query(MSqlQuery::InitCon()), threadRunning(false)
     22{
     23  list.clear();
     24}
     25
     26/** \fn Init()
     27 *  \brief Starts the thread
     28 *
     29 *   Create a thread and return false if this fails
     30 */
     31bool AsyncDB::Init(void)
     32{
     33  int rv;
     34  if(  ( rv = pthread_create(&thread, NULL, StartThread, this) ) ) {
     35    VERBOSE(VB_IMPORTANT, ADB + QString("Can't start thread"));
     36    return false;
     37  }
     38  threadRunning = true;
     39  return(true);
     40}
     41
     42/** \fn StartThread(AsyncDB *)
     43 *  \brief Runs the worker function
     44 *
     45 *   Drop the priority on this thread and invoke the worker function
     46 */
     47void *AsyncDB::StartThread(void *wotzit)
     48{
     49  AsyncDB *pi = (AsyncDB *)wotzit;
     50  VERBOSE(VB_IMPORTANT,QString("Starting async db thread"));
     51  // Loser priority, to avoid problems with recordings.
     52  setpriority(PRIO_PROCESS, 0, 3);
     53  pi->Worker();
     54  return(NULL);
     55}
     56
     57/** \fn AddCommand(QString)
     58 *  \brief Adds a database command to the list
     59 *
     60 *  \param QString   The sql command
     61 */
     62void AsyncDB::AddCommand(QString cmd)
     63{
     64  listLock.lock();
     65  list.append(cmd);
     66  listLock.unlock();
     67//  adb_cmd_list_t *item = new adb_cmd_list_t;
     68//  item->cmd = cmd;
     69//  listLock.lock();
     70//  item->next = list;
     71//  list = item;
     72//  listLock.unlock();
     73}
     74
     75/** \fn ~AsyncDB
     76 *  \brief Shut down the thread
     77 *
     78 *   Add a "done" command to the list to make the thread
     79 *   shutdown and reap it.
     80 */
     81AsyncDB::~AsyncDB(void)
     82{
     83  AddCommand(QString("done"));
     84  pthread_join(thread, NULL);
     85  VERBOSE(VB_IMPORTANT,QString("Ending async db thread"));
     86}
     87
     88/** \fn Worker()
     89 *  \brief Run the lists of commands
     90 *
     91 *   Swap the list for an empty one and call ListRunner
     92 *   to execute the commands.
     93 */
     94void AsyncDB::Worker(void)
     95{
     96  bool done = false;
     97
     98  while( ! done ) {
     99    if( list.empty() ) {
     100      sleep(1);
     101    } else {
     102      listLock.lock();
     103      QStringList mylist = list;
     104      list.clear();
     105      listLock.unlock();
     106      for ( QStringList::Iterator it = mylist.begin(); it != mylist.end(); ++it ) {
     107        if( *it == QString("done") ) {
     108          done = true;
     109          break;
     110        }
     111        query.prepare(*it);
     112        if (!query.exec() || !query.isActive())
     113          MythContext::DBError("delta position map insert",
     114                               query);
     115      }
     116      mylist.clear();
     117    }
     118  }
     119//  while( ! done ) {
     120//    if( list == NULL ) {
     121//      sleep(1);
     122//    } else {
     123//      listLock.lock();
     124//      adb_cmd_list_t *mylist = list;
     125//      list = NULL;
     126//      listLock.unlock();
     127//      done = ListRunner(mylist);
     128//    }
     129//  }
     130}
     131
     132/** \fn ListRunner( adb_cmd_list_t * )
     133 *  \brief Execute the accumulated commands
     134 *
     135 *   Standard recursive routine. Shoot down to the end of the
     136 *   list and as we return back execute the commands and clean
     137 *   up the objects. This maintains order, since the newest
     138 *   commands are at the head of the list.
     139 *
     140 *   If we find the command "done" return true.
     141 *
     142 *  \param adb_cmd_list_t*  The rest of the list
     143 */
     144bool AsyncDB::ListRunner( adb_cmd_list_t *list ) {
     145  bool done = false;
     146  if( list != NULL ) {
     147    done = ListRunner(list->next);
     148    if( list->cmd == QString("done") ) {
     149          done = true;
     150    } else {
     151      query.prepare(list->cmd);
     152      if (!query.exec() || !query.isActive())
     153        MythContext::DBError("async command failed",
     154                             query);
     155    }
     156    delete list->cmd;
     157    delete list;
     158  }
     159  return( done );
     160}
     161
  • programs/mythfrontend/globalsettings.cpp

     
    22082208    return gc;
    22092209}
    22102210
     2211static HostCheckBox *ReaderRealtimePriority()
     2212{
     2213    HostCheckBox *gc = new HostCheckBox("ReaderRealtimePriority");
     2214    gc->setLabel(QObject::tr("Enable realtime priority reader"));
     2215    gc->setHelpText(QObject::tr("Makes the threads that read data from "
     2216                    "the video device run at super high priority. "
     2217                    "Disable this if your system locks up."));
     2218    gc->setValue(false);
     2219    return gc;
     2220}
     2221
     2222static HostCheckBox *WriterRealtimePriority()
     2223{
     2224    HostCheckBox *gc = new HostCheckBox("WriterRealtimePriority");
     2225    gc->setLabel(QObject::tr("Enable realtime priority writer"));
     2226    gc->setHelpText(QObject::tr("Makes the threads that writes data to "
     2227                    "disk run at super high priority. "
     2228                    "Disable this if your system locks up."));
     2229    gc->setValue(false);
     2230    return gc;
     2231}
     2232
    22112233static HostComboBox *XboxBlinkBIN()
    22122234{
    22132235    HostComboBox *gc = new HostComboBox("XboxBlinkBIN");
     
    30273049    general->addChild(SetupPinCode());
    30283050    general->addChild(EnableMediaMon());
    30293051    general->addChild(EnableXbox());
     3052    general->addChild(ReaderRealtimePriority());
     3053    general->addChild(WriterRealtimePriority());
    30303054    addChild(general);
    30313055
    30323056    MythLogSettings *mythlog = new MythLogSettings();
  • programs/mythfrontend/main.cpp

     
    689689                {
    690690                    pthread_t *target_thread = (pthread_t *)(req.getData());
    691691                    // Raise the given thread to realtime priority
    692                     struct sched_param sp = {1};
     692                    struct sched_param sp = {2};
    693693                    if (target_thread)
    694694                    {
    695695                        int status = pthread_setschedparam(
     
    697697                        if (status)
    698698                        {
    699699                            // perror("pthread_setschedparam");
    700                             VERBOSE(VB_GENERAL, "Realtime priority would require SUID as root.");
     700                          VERBOSE(VB_GENERAL, QString("Setting realtime priority failed: %1.").arg(strerror(errno)));
    701701                        }
    702702                        else
    703703                            VERBOSE(VB_GENERAL, "Using realtime priority.");
  • programs/mythtranscode/transcode.cpp

     
    809809    {
    810810        if (m_proginfo)
    811811        {
    812             m_proginfo->ClearPositionMap(MARK_KEYFRAME);
    813             m_proginfo->ClearPositionMap(MARK_GOP_START);
    814             m_proginfo->ClearPositionMap(MARK_GOP_BYFRAME);
     812          m_proginfo->ClearPositionMap(MARK_KEYFRAME, true);
     813            m_proginfo->ClearPositionMap(MARK_GOP_START, true);
     814            m_proginfo->ClearPositionMap(MARK_GOP_BYFRAME, true);
    815815        }
    816816
    817817        nvr->WriteSeekTable();
     
    6465    bool build_index = false, fifosync = false, showprogress = false, mpeg2 = false;
    6566    QMap<long long, int> deleteMap;
    6667    QMap<long long, long long> posMap;
     68    int fd;
    6769    srand(time(NULL));
    6870
     71    /* Let this process migrate on openMosix */
     72    if( ( fd = open( "/proc/self/lock", O_WRONLY ) ) >= 0 ) {
     73      write( fd, "0\n", 2 );
     74      close( fd );
     75    }
     76
    6977    QApplication a(argc, argv, false);
    7078
    7179    print_verbose_messages = VB_IMPORTANT;
  • programs/mythtranscode/main.cpp

     
    470482{
    471483    if (pginfo && ! mapfile)
    472484    {
    473         pginfo->ClearPositionMap(MARK_KEYFRAME);
    474         pginfo->ClearPositionMap(MARK_GOP_START);
     485        pginfo->ClearPositionMap(MARK_KEYFRAME, true);
     486        pginfo->ClearPositionMap(MARK_GOP_START, true);
    475487        pginfo->SetPositionMap(posMap, MARK_GOP_BYFRAME);
    476488    }
    477489    else if (mapfile)
  • programs/mythbackend/main.cpp

     
    3333#include "libmythtv/programinfo.h"
    3434#include "libmythtv/dbcheck.h"
    3535#include "libmythtv/jobqueue.h"
     36#include "libmyth/asyncdb.h"
    3637
    3738QMap<int, EncoderLink *> tvList;
    3839AutoExpire *expirer = NULL;
     
    171172
    172173void cleanup(void)
    173174{
     175    delete gAsyncDB;
    174176    delete gContext;
    175177
    176178    if (sched)
     
    412414    }   
    413415    gContext->ActivateSettingsCache(true);
    414416
     417    gAsyncDB = new AsyncDB();
     418    if( gAsyncDB->Init() == false )
     419      {
     420        VERBOSE(VB_IMPORTANT, "Couldn't start async database thread");
     421        return BACKEND_EXIT_ASYNCDB_ERROR;
     422      }
     423
    415424    if (printsched || testsched)
    416425    {
    417426        gContext->SetBackend(false);