我正在撰寫一個程式,為所有子目錄中的檔案生成哈希,然后將它們放入資料庫或將它們列印到標準輸出:https : //github.com/cherrry9/dedup
在最新的提交中,我為我的程式添加了使用多執行緒(THREADS宏)的選項。
以下是我所做的一些基準測驗:
$ test() { /usr/bin/time -p ./dedup / -v 0 -c 2048 -e "/\(proc\|sys\|dev\|run\)"; }
$ make clean all THREADS=1 test
real 8.03
user 4.34
sys 4.55
$ make clean all THREADS=4 && test
real 3.94
user 7.66
sys 7.42
正如你可以編譯的版本THREADS=4快 2 倍。
現在我將使用第二個位置引數來指定 sqlite3 資料庫:
$ test() { /usr/bin/time -p ./dedup / test.db -v 0 -c 2048 -e "/\(proc\|sys\|dev\|run\)"; }
$ make clean all THREADS=1 && ?test
real 20.40
user 7.58
sys 7.29
$ rm test.db
$ make clean all THREADS=4 && ?test
real 21.86
user 17.17
sys 18.15
編譯的THREADS=4版本比使用的版本慢THREADS=1!
當我使用第二個引數時,dedup.c執行了這段將哈希插入資料庫的代碼:
if (sql != NULL && sql_insert(sql, entry->fpath, hash) != 0) {
// ...
sql_insert使用事務來防止sqlite每次呼叫時寫入資料庫INSERT。
int
sql_insert(SQL *sql, const char *filename, char unsigned hash[])
{
int errcode;
pthread_mutex_lock(&sql->mtx);
sqlite3_bind_text(sql->stmt, 1, filename, -1, NULL);
sqlite3_bind_blob(sql->stmt, 2, hash, SHA256_LENGTH, NULL);
sqlite3_step(sql->stmt);
SQL_TRY(sqlite3_reset(sql->stmt));
if ( sql->insertc >= INSERT_LIM) {
SQL_TRY(sqlite3_exec(sql->database, "COMMIT;BEGIN", NULL, NULL, NULL));
sql->insertc = 0;
}
pthread_mutex_unlock(&sql->mtx);
return 0;
}
該片段針對每個處理過的檔案執行,并且由于某種原因它阻塞了我程式中的所有執行緒。
這是我的問題,如何防止 sqlite 阻塞執行緒并降低程式的性能?
dedup如果您想知道test函式在做什么,這里是選項說明:
1th positional argument - directory to use to generate hashes
2th positional argument - path to databases which will be used by sqlite3
-v level - verbose level (0 means print only errors)
-c nbytes - read nbytes from each file
-e regex - exclude directories that match regex
我在 sqlite3 中使用序列化模式。
uj5u.com熱心網友回復:
您的所有執行緒似乎都使用相同的資料庫連接和陳述句物件。因此,您有一個競爭條件(即使在 SERIALIZED 執行緒模型中),因為多個執行緒正在系結、步進和重置相同的陳述句。在您解決此問題之前,詢問“為什么它很慢”變得無關緊要。
相反,您應該sql_insert使用互斥鎖來包裝您,以確保最多有一個執行緒正在訪問資料庫連接:
int
sql_insert(SQL *sql, const char *filename, char unsigned hash[])
{
pthread_mutex_lock(&sql->mutex);
// ... actual insert and exec code ...
pthread_mutex_unlock(&sql->mutex);
return 0;
}
然后在您的SQL結構中添加并初始化該互斥鎖pthread_mutex_init。
如果您的瓶頸確實是 SHA-256 的計算而不是寫入資料庫,您將看到性能提升。否則這個互斥鎖的開銷應該可以忽略不計,執行緒數不會對運行時產生顯著影響。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/395481.html
