Ticket #1660: speedup.patch
File speedup.patch, 21.2 KB (added by , 20 years ago) |
---|
-
libs/libmythtv/ThreadedFileWriter.cpp
8 8 #include <sys/stat.h> 9 9 #include <unistd.h> 10 10 #include <fcntl.h> 11 #include <sys/time.h> 12 #include <sys/resource.h> 13 #include <sys/mman.h> 11 14 12 15 // MythTV headers 13 16 #include "ThreadedFileWriter.h" … … 20 23 #define LOC QString("TFW: ") 21 24 #define LOC_ERR QString("TFW, Error: ") 22 25 23 const uint ThreadedFileWriter::TFW_DEF_BUF_SIZE = 2*1024*1024;26 const uint ThreadedFileWriter::TFW_DEF_BUF_SIZE = 8*1024*1024; 24 27 const uint ThreadedFileWriter::TFW_MAX_WRITE_SIZE = TFW_DEF_BUF_SIZE / 4; 25 28 const uint ThreadedFileWriter::TFW_MIN_WRITE_SIZE = TFW_DEF_BUF_SIZE / 8; 26 29 … … 90 93 void *ThreadedFileWriter::boot_writer(void *wotsit) 91 94 { 92 95 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 } 93 112 fw->DiskLoop(); 94 113 return NULL; 95 114 } … … 140 159 else 141 160 { 142 161 buf = new char[TFW_DEF_BUF_SIZE + 1024]; 162 // mlock(buf,TFW_DEF_BUF_SIZE + 1024); 143 163 bzero(buf, TFW_DEF_BUF_SIZE + 64); 144 164 145 165 tfw_buf_size = TFW_DEF_BUF_SIZE; … … 173 193 174 194 if (buf) 175 195 { 196 // munlock(buf,tfw_buf_size + 1024); 176 197 delete [] buf; 177 198 buf = NULL; 178 199 } … … 300 321 Flush(); 301 322 302 323 buflock.lock(); 324 // munlock(buf,tfw_buf_size+1024); 303 325 delete [] buf; 304 326 rpos = wpos = 0; 305 327 buf = new char[newSize + 1024]; 328 // mlock(buf,newSize+1024); 306 329 bzero(buf, newSize + 64); 307 330 tfw_buf_size = newSize; 308 331 buflock.unlock(); -
libs/libmythtv/programinfo.h
217 217 // Keyframe positions Map 218 218 void GetPositionMap(frm_pos_map_t &, int type) const; 219 219 void ClearPositionMap(int type) const; 220 void ClearPositionMap(int type, bool sync) const; 220 221 void SetPositionMap(frm_pos_map_t &, int type, 221 222 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); 223 224 224 225 225 // GUI stuff 226 226 void showDetails(void) const; 227 227 void EditRecording(void); … … 318 318 private: 319 319 bool ignoreBookmark; 320 320 mutable class ScheduledRecording* record; 321 322 QString inUseForWhat; 321 323 322 QString inUseForWhat;323 324 }; 324 325 325 326 /** \class ProgramList -
libs/libmythtv/tv_rec.cpp
5 5 #include <unistd.h> 6 6 #include <pthread.h> 7 7 #include <sched.h> // for sched_yield 8 #include <sys/time.h> 9 #include <sys/resource.h> 8 10 9 11 // C++ headers 10 12 #include <iostream> … … 1125 1127 void *TVRec::RecorderThread(void *param) 1126 1128 { 1127 1129 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 1128 1147 recorder->StartRecording(); 1129 1148 return NULL; 1130 1149 } -
libs/libmythtv/programinfo.cpp
19 19 #include "remoteutil.h" 20 20 #include "jobqueue.h" 21 21 #include "mythdbcon.h" 22 #include "asyncdb.h" 22 23 23 24 using namespace std; 24 25 … … 1375 1376 if (playbackHost == "") 1376 1377 playbackHost = m_hostname; 1377 1378 1379 // Get the original path it was recorded on 1378 1380 tmpURL = GetRecordFilename(gContext->GetSettingOnHost("RecordFilePrefix", 1379 1381 hostname)); 1380 1382 1383 // if we are playing back on the recording host, just return it 1381 1384 if (playbackHost == hostname) 1382 1385 return tmpURL; 1383 1386 1387 // else if we are playing back on this host, check if the path is accessable, if so, use it 1384 1388 if (playbackHost == m_hostname) 1385 1389 { 1386 1390 QFile checkFile(tmpURL); … … 1396 1400 return tmpURL; 1397 1401 } 1398 1402 1403 // else contruct a url to use myth file transfer protocol 1399 1404 tmpURL = QString("myth://") + 1400 1405 gContext->GetSettingOnHost("BackendServerIP", hostname) + ":" + 1401 1406 gContext->GetSettingOnHost("BackendServerPort", hostname) + "/" + … … 1606 1611 { 1607 1612 filesize = fsize; 1608 1613 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")); 1616 1620 1617 if (!query.exec() || !query.isActive()) 1618 MythContext::DBError("File size update", 1619 query); 1621 gAsyncDB->AddCommand(query); 1620 1622 } 1621 1623 1622 1624 /** \fn ProgramInfo::GetFilesize(void) … … 2310 2312 2311 2313 void ProgramInfo::ClearPositionMap(int type) const 2312 2314 { 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 2337 void ProgramInfo::ClearPositionMap(int type, bool sync) const 2338 { 2313 2339 MSqlQuery query(MSqlQuery::InitCon()); 2314 2340 2315 2341 if (isVideo) … … 2427 2453 } 2428 2454 2429 2455 void ProgramInfo::SetPositionMapDelta(frm_pos_map_t &posMap, 2430 int type) const2456 int type) 2431 2457 { 2432 2458 QMap<long long, long long>::Iterator i; 2433 MSqlQuery query(MSqlQuery::InitCon());2459 QString insert; 2434 2460 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 */ 2435 2480 for (i = posMap.begin(); i != posMap.end(); ++i) 2436 2481 { 2437 2482 long long frame = i.key(); … … 2446 2491 QString offset_str = tempc; 2447 2492 2448 2493 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 } 2456 2498 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 = ","; 2472 2505 } 2506 2507 insert += QString(";"); 2508 /* Hand it to the async thread */ 2509 gAsyncDB->AddCommand(insert); 2473 2510 } 2474 2511 2475 2512 /** \fn ProgramInfo::ReactivateRecording(void) -
libs/libmyth/exitcodes.h
57 57 #define BACKEND_BUGGY_EXIT_NO_CAP_CARD GENERIC_EXIT_START-11 58 58 #define BACKEND_BUGGY_EXIT_NO_CHAN_DATA GENERIC_EXIT_START-12 59 59 #define BACKEND_EXIT_START GENERIC_EXIT_START-12 60 #define BACKEND_EXIT_ASYNCDB_ERROR GENERIC_EXIT_START-13 60 61 61 62 // mythtranscode 62 63 #define TRANSCODE_EXIT_OK GENERIC_EXIT_OK -
libs/libmyth/libmyth.pro
20 20 HEADERS += langsettings.h audiooutputnull.h 21 21 HEADERS += DisplayResScreen.h util-x11.h mythdeque.h qmdcodec.h 22 22 HEADERS += exitcodes.h virtualkeyboard.h mythobservable.h mythevent.h 23 HEADERS += asyncdb.h 23 24 24 25 SOURCES += dialogbox.cpp lcddevice.cpp mythcontext.cpp mythwidgets.cpp 25 26 SOURCES += oldsettings.cpp remotefile.cpp settings.cpp themedmenu.cpp … … 32 33 SOURCES += langsettings.cpp mythdbcon.cpp audiooutputnull.cpp 33 34 SOURCES += DisplayResScreen.cpp util-x11.cpp qmdcodec.cpp 34 35 SOURCES += virtualkeyboard.cpp mythobservable.cpp 36 SOURCES += asyncdb.cpp 35 37 36 38 INCLUDEPATH += ../libmythsamplerate ../libmythsoundtouch ../.. 37 39 DEPENDPATH += ../libmythsamplerate ../libmythsoundtouch … … 59 61 inc.files += visual.h volumebase.h output.h langsettings.h qmdcodec.h 60 62 inc.files += exitcodes.h mythconfig.h mythconfig.mak virtualkeyboard.h 61 63 inc.files += mythevent.h mythobservable.h 64 inc.files += asyncdb.h 62 65 63 66 using_oss { 64 67 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 13 using namespace std; 14 15 typedef struct adb_cmd_list { 16 struct adb_cmd_list *next; 17 QString cmd; 18 } adb_cmd_list_t; 19 20 class 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 42 extern 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 6 AsyncDB *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 */ 20 AsyncDB::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 */ 31 bool 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 */ 47 void *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 */ 62 void 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 */ 81 AsyncDB::~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 */ 94 void 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 */ 144 bool 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
2208 2208 return gc; 2209 2209 } 2210 2210 2211 static 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 2222 static 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 2211 2233 static HostComboBox *XboxBlinkBIN() 2212 2234 { 2213 2235 HostComboBox *gc = new HostComboBox("XboxBlinkBIN"); … … 3027 3049 general->addChild(SetupPinCode()); 3028 3050 general->addChild(EnableMediaMon()); 3029 3051 general->addChild(EnableXbox()); 3052 general->addChild(ReaderRealtimePriority()); 3053 general->addChild(WriterRealtimePriority()); 3030 3054 addChild(general); 3031 3055 3032 3056 MythLogSettings *mythlog = new MythLogSettings(); -
programs/mythfrontend/main.cpp
689 689 { 690 690 pthread_t *target_thread = (pthread_t *)(req.getData()); 691 691 // Raise the given thread to realtime priority 692 struct sched_param sp = { 1};692 struct sched_param sp = {2}; 693 693 if (target_thread) 694 694 { 695 695 int status = pthread_setschedparam( … … 697 697 if (status) 698 698 { 699 699 // 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))); 701 701 } 702 702 else 703 703 VERBOSE(VB_GENERAL, "Using realtime priority."); -
programs/mythtranscode/transcode.cpp
809 809 { 810 810 if (m_proginfo) 811 811 { 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); 815 815 } 816 816 817 817 nvr->WriteSeekTable(); … … 64 65 bool build_index = false, fifosync = false, showprogress = false, mpeg2 = false; 65 66 QMap<long long, int> deleteMap; 66 67 QMap<long long, long long> posMap; 68 int fd; 67 69 srand(time(NULL)); 68 70 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 69 77 QApplication a(argc, argv, false); 70 78 71 79 print_verbose_messages = VB_IMPORTANT; -
programs/mythtranscode/main.cpp
470 482 { 471 483 if (pginfo && ! mapfile) 472 484 { 473 pginfo->ClearPositionMap(MARK_KEYFRAME );474 pginfo->ClearPositionMap(MARK_GOP_START );485 pginfo->ClearPositionMap(MARK_KEYFRAME, true); 486 pginfo->ClearPositionMap(MARK_GOP_START, true); 475 487 pginfo->SetPositionMap(posMap, MARK_GOP_BYFRAME); 476 488 } 477 489 else if (mapfile) -
programs/mythbackend/main.cpp
33 33 #include "libmythtv/programinfo.h" 34 34 #include "libmythtv/dbcheck.h" 35 35 #include "libmythtv/jobqueue.h" 36 #include "libmyth/asyncdb.h" 36 37 37 38 QMap<int, EncoderLink *> tvList; 38 39 AutoExpire *expirer = NULL; … … 171 172 172 173 void cleanup(void) 173 174 { 175 delete gAsyncDB; 174 176 delete gContext; 175 177 176 178 if (sched) … … 412 414 } 413 415 gContext->ActivateSettingsCache(true); 414 416 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 415 424 if (printsched || testsched) 416 425 { 417 426 gContext->SetBackend(false);