2015-09-25 46 views
0

我寫我的代碼到select在3個線程中併發單線程一個連接;我發現它比1個線程慢;多線程讀取會導致性能下降嗎?

這裏是我的測試數據:
這是一個表(索引uint32)與100000項;

當我在3個一線選擇 10萬項目(所有項目):

0: 1443185531.782627, info: <NSThread: 0x13f99ac40>{number = 4, name = (null)} read ready 
1: 1443185531.782634, cost 0.000007, info: <NSThread: 0x13f99ac40>{number = 4, name = (null)} read start 
2: 1443185533.365550, cost 1.582916, info: <NSThread: 0x13f99ac40>{number = 4, name = (null)} read end 

0: 1443185531.772624, info: <NSThread: 0x13f871e60>{number = 2, name = (null)} read ready 
1: 1443185531.782659, cost 0.010035, info: <NSThread: 0x13f871e60>{number = 2, name = (null)} read start 
2: 1443185533.372972, cost 1.590313, info: <NSThread: 0x13f871e60>{number = 2, name = (null)} read end 

0: 1443185531.773191, info: <NSThread: 0x13f99a6a0>{number = 3, name = (null)} read ready 
1: 1443185531.782636, cost 0.009445, info: <NSThread: 0x13f99a6a0>{number = 3, name = (null)} read start 
2: 1443185533.393716, cost 1.611080, info: <NSThread: 0x13f99a6a0>{number = 3, name = (null)} read end 

你可以看到它的成本1.5秒的平均水平。
但是,當我更改爲選擇 10萬項目(所有項目)在1線:

0: 1443185738.427020, info: <NSThread: 0x14d970990>{number = 2, name = (null)} read ready 
1: 1443185738.427106, cost 0.000086, info: <NSThread: 0x14d970990>{number = 2, name = (null)} read start 
2: 1443185739.020410, cost 0.593304, info: <NSThread: 0x14d970990>{number = 2, name = (null)} read end 

的成本達到0.5秒。

所以我混淆了多線程閱讀會減慢sqlite3的性能。

據我所知,閱讀使用shared-mutex,它可以在多線程中共享。性能下降不應該發生。

有人可以解決我的困惑嗎?


附加:
sqlite3的是在WAL,SQLITE_CONFIG_MULTITHREAD模式,無需任何手動互斥。


附加:
我運行這樣我在3個線程代碼。

//objc code 
dispatch_async(name1, ^{ 
    select * in conn1 
} 
dispatch_async(name2, ^{ 
    select * in conn2 
} 
dispatch_async(name3, ^{ 
    select * in conn3 
} 
+0

而不是在每個線程中使用相同的連接(線程不能同時使用),請爲每個線程創建一個連接。 –

+0

我明白每個線程都有自己的句柄sqlite(單線程一個句柄)。您正在以錯誤的方式使用線程。你讓你的軟件做了3次相同的工作,所以它花了更多的時間。 – user430051

+0

@ColonelThirtyTwo我在每個線程中都使用自己的連接。 (寫單線程一連接) –

回答

0

這並不令人驚訝。你的所有線程都使用與數據庫的共享連接,並對其進行同步。結果,在給定的時刻只有一個線程真正執行。添加上下文切換,並瞭解性能降低的原因。

如果您爲每個線程提供自己的連接,則線程內不會進行同步,您應該看到性能得到提高。

+0

我在每個線程中都使用自己的連接。 (寫成單線程連接) –

0

我試着用一個例子來回答。對於這種情況,客戶端如何與服務器或上下文切換,虛擬化,多核等等進行對話並不重要(但請注意,在設計規範中的系統時需要考慮到這一點):

你有一個N客戶端的服務器。客戶來去,並有不同的要求。一些客戶做出快速,小而頻繁的請求。其他人減少需要更長時間才能返回的請求。

如果您有一個進程/線程,則一次只能處理一個客戶端的一個請求 - 您有一堆客戶端,每個客戶端都有一堆請求。

現在,假設您想要使用線程來並行化您的工作負載,您可以爲每個客戶端分配一個線程(多種可能之一)。你將有一堆線程(每一個代表一個客戶端)。然後每個線程都會有一堆客戶請求。操作系統將在這些多個任務之間分割(上下文切換)處理時間,並且您將有一個連擊總體響應。

你目前的方法並沒有探索使用並行處理 - 你只是要求線程做同樣的工作。

即便如此,單靠這些還不足以讓代碼線性增加時間。我懷疑在某個地方,你可能會分享相同的資源 - 這將是瓶頸。

你可以谷歌大量的材料何時使用線程。我發現瞭解線程的最佳資源之一是C10k problem。您可以找到紙here的歸檔版本。

相關問題