2012-01-16 14 views
3

這是我的問題,我有一個sqlitememory database使用QSql。我有幾個線程每個處理這個公共數據庫的一個不同的表。我用Win API,以確保工作在不同的處理器這些線程,就像這樣:在多處理器線程中優化內存數據庫的QSql

SetThreadAffinityMask (hThread, processorMask); 

如果只有線程處理一個表,它需要10秒,並使用總CPU的25%。但是當有4個線程處理4個不同的表格時,它需要將近40秒,並且只佔總CPU的35%。我認爲原因是在一個數據庫中存在某種thread-safe同步。但由於不同的線程讀取或寫入不同的表格,線程安全性會降低我的程序。我怎樣才能優化它。

更新:最可能的原因是某些類型的鎖的Qt和/或Sqlite 3內減緩我的程序,所以是有可能關閉或繞過這些鎖通過預先設置。

Update2:下面是一個示例。 (也許有點長,對不起)

class MultiProcessorThread 
{ 
public: 
    virtual void run(); 
    bool start() 
    { 
     m_hThread = CreateThread (NULL, 0, MultiProcessorThread::ThreadFunc, this, CREATE_SUSPENDED, NULL); 

     if (m_hThread != INVALID_HANDLE_VALUE) 
     { 
      RunningThreadCount++; 
      m_ProcessorMask = 1 << ((RunningThreadCount - 1) % ProcessorCount); 
      SetThreadAffinityMask (m_hThread, m_ProcessorMask); // Make thread working on different processor 
      ResumeThread (m_hThread); 
      return true; 
     } 
     else 
      return false; 
    } 
protected: 
    static DWORD WINAPI ThreadFunc (LPVOID in); 
    HANDLE m_hThread; 
    DWORD_PTR m_ProcessorMask; 
    static DWORD_PTR ProcessorCount; 
    static DWORD_PTR RunningThreadCount; 
    static DWORD_PTR GetNumCPUs(); 
}; 

DWORD_PTR MultiProcessorThread::ProcessorCount = GetNumCPUs(); 
DWORD_PTR MultiProcessorThread::RunningThreadCount = 0; 
DWORD_PTR MultiProcessorThread::GetNumCPUs() // Get how many processors on this PC 
{ 
    SYSTEM_INFO m_si = {0}; 
    GetSystemInfo (&m_si); 
    return (DWORD_PTR) m_si.dwNumberOfProcessors; 
} 
DWORD WINAPI MultiProcessorThread::ThreadFunc (LPVOID in) 
{ 
    static_cast<MultiProcessorThread*> (in)->run(); 
    return 0; 
} 

class Run : public MultiProcessorThread 
{ 
public: 
    void run() 
    { 
     int i = 0; 
     QString add = "insert into %1 values(1)"; 
     add = add.arg (table); 
     QString sel = "select a from %1 "; 
     sel = sel.arg (table); 
     QString del = "delete from %1 where a=1"; 
     del = del.arg (table); 

     while (++i) // read and write database 
     { 
      query.exec (add); 
      query.exec (sel); 
      query.exec (del); 
     } 
    } 
    QSqlQuery query; 
    QString table; 
}; 

int main (int argc, char *argv[]) 
{ 
    QCoreApplication a (argc, argv); 
    QSqlDatabase db = QSqlDatabase::addDatabase ("QSQLITE", "test"); 
    db.setDatabaseName (":memory:"); // All threads working on the same memory database. 
    db.open(); 
    QSqlQuery q (db), q1 (db), q2 (db); 
    q.exec ("create table A (a)"); 
    q1.exec ("create table B (a)"); 
    q2.exec ("create table C (a)"); // All threads working on different table. 
    Run b[3]; 
    b[0].query = QSqlQuery (q); 
    b[0].table = "A"; 
    b[1].query = QSqlQuery (q1); 
    b[1].table = "B"; 
    b[2].query = QSqlQuery (q2); 
    b[2].table = "C"; 
    b[0].start(); 
    b[1].start(); 
    b[2].start(); 
    return a.exec(); 
} 
+0

這真的取決於你如何使用sqlite3。粘貼你正在用數據庫做的一些例子。 – synthesizerpatel 2012-01-24 11:30:30

+0

在繼續進行優化之前,請看一下這個問題:http://stackoverflow.com/questions/1680249/how-to-use-sqlite-in-a-multi-threaded-application – Neox 2012-01-24 12:18:05

+0

@Neox它會幫助一些,但我的情況有一些差異。首先,在我的程序中,我直接使用'QSql'而不是'sqlite',所以我不能選擇如何編譯sqlite3庫。第二我不需要在線程之間進行同步,因爲它們在不同的表上運行。第三我使用內存數據庫,所以我必須共享相同的連接。 – xucheng 2012-01-24 12:30:51

回答

1

首先,不要顯式設置親和性掩碼,windows會自動爲最空閒的核心分配線程。在這種情況下,最好依靠OS來執行線程分發。

據我所知,sqlite在寫入時鎖定整個數據庫,這就是爲什麼你沒有得到預期的性能提升。看看sqlite鎖定文檔http://www.sqlite.org/lockingv3.html

0

你有沒有測得的線程多少時間在CPU上花費相比,比如說,磁盤I/O吞吐量?

這可能與線程和鎖無關。它可能與Amdahl's law有關。

+0

根本沒有磁盤I/O,它是內存數據庫中的純粹計算。 – xucheng 2012-01-24 15:05:27

+0

好吧,所以它不是磁盤,但那不是重點。它可能是導致Amdahl效應的任何阻塞資源。 – spraff 2012-01-24 15:48:04

0

Qt文檔是明確的。從http://doc.qt.nokia.com/4.7/threads-modules.html#threads-and-the-sql-module

螺紋和SQL模塊

的連接只能從創建它的線程內使用。 不支持在線程之間移動連接或從 不同線程創建查詢。

此外,由QSqlDrivers使用的第三方庫可以在多線程程序中使用SQL模塊時會產生進一步的限制 。請諮詢您的數據庫客戶端的手冊,瞭解更多信息

有沒有辦法做你想要通過Qt的API是什麼。

+0

但是,我可以做到這一點(使用QSql btwn線程),因爲我的代碼是可運行的。我只是不知道如何優化它。 – xucheng 2012-01-27 14:41:16

+0

問題是,這不被支持。您的程序可能會崩潰,您的數據可能會損壞,其他任何事情都可能發生。無論如何,從概念上講,試圖同時寫入同一數據庫中的不同表而不鎖定是沒有意義的。你的表或者是相關的,所以需要鎖定,或者他們不需要,他們根本不需要在同一個數據庫中。這是什麼? – 2012-01-27 14:58:58