2011-10-18 50 views
1

(出于好奇纯)在VB.net,我测试串联100K串并独自发现了一个线程在23毫秒做到了。两个线程(每个连接50k)然后在最后加入两个线程需要30毫秒。性能方面,在处理仅100k串联时使用多线程似乎不是有益的。然后我尝试了300万字符串连接,每个处理1.5MM的两个线程总是拆除一个处理全部300万个线程的线程。我想在某些时候使用3个线程变得有益,然后是4,依此类推。有没有更有效的方法来连接.NET中的数百万个字符串?线程值得使用吗?字符串连接和线程在.NET

At around 1MM string concatenations, it appears multiple threads can improve performance

仅供参考,这是我写的代码:

Imports System.Text 
Imports System.Threading 
Imports System.IO 
Public Class Form1 
    Dim sbOne As StringBuilder 
    Dim sbTwo As StringBuilder 
    Dim roof As Integer 
    Dim results As DataTable 
    Sub clicked(s As Object, e As EventArgs) Handles Button1.Click 
     results = New DataTable 
     results.Columns.Add("one thread") 
     results.Columns.Add("two threads") 
     results.Columns.Add("roof") 

     For i As Integer = 1 To 3000000 Step 100000 
      roof = i 
      Dim test() As Double = runTest() 
      results.Rows.Add(test(0), test(1), i) 
      Console.WriteLine(roof) 
     Next 

     Dim output As New StringBuilder 
     For Each C As DataColumn In results.Columns 
      output.Append(C) 
      output.Append(Chr(9)) 
     Next 
     output.Append(vbCrLf) 
     For Each R As DataRow In results.Rows 
      For Each C As DataColumn In results.Columns 
       output.Append(R(C)) 
       output.Append(Chr(9)) 
      Next 
      output.Append(vbCrLf) 
     Next 
     File.WriteAllText("c:\users\username\desktop\sbtest.xls", output.ToString) 
     Console.WriteLine("done") 

    End Sub 
    Function runTest() As Double() 
     Dim sb As New StringBuilder 
     Dim started As DateTime = Now 
     For i As Integer = 1 To roof 
      sb.Append(i) 
     Next 
     Dim result As String = sb.ToString 
     Dim test1 As Double = Now.Subtract(started).TotalMilliseconds 

     sbOne = New StringBuilder 
     sbTwo = New StringBuilder 
     Dim one As New Thread(AddressOf tOne) 
     Dim two As New Thread(AddressOf tTwo) 
     started = Now 
     one.Start() 
     two.Start() 
     Do While one.IsAlive Or two.IsAlive 
     Loop 
     result = String.Concat(one.ToString, two.ToString) 
     Dim test2 As Double = Now.Subtract(started).TotalMilliseconds 
     Return {test1, test2} 
    End Function 
    Sub tOne() 
     For i As Integer = 1 To roof/2 
      sbOne.Append(i) 
     Next 
    End Sub 
    Sub tTwo() 
     For i As Integer = roof/2 To roof 
      sbTwo.Append(i) 
     Next 
    End Sub 
End Class 
+1

“StringBuffer”可能会更好。 –

+0

尝试从'System.Text'使用'StringBuilder'类 –

+1

这取决于您编写代码的方式以及您拥有的核心数量。出于好奇:这是一个研究还是现实世界的例子?也尝试使用ThreadPool(看看异步委托和QueueUserWOrkItem)。不要忘记,线程初始化需要一些时间 - 当.NET和OS准备新线程时,您的单线程算法已经开始连接。线程不是为了各种目的。 –

回答

2

检查出的StringBuilder的.EnsureCapacity子程序。如果您正在进行大量的连接并且大致了解字符数量,则可以一次初始化stringbuilder的缓冲区,而不是让它动态发生。你应该看到更多的改进。

http://msdn.microsoft.com/en-us/library/system.text.stringbuilder.ensurecapacity.aspx

+0

这是很好的建议,但它不是OP问题的答案。 –

+0

酷我会去看看谢谢 – DontFretBrett

+0

这不是?他直接问“在.NET中连接数百万个字符串是否有更高效的方法?线程是否值得使用?”。我回答了第一个问题。其他人已经指出,线程不是要走的路。 –

3

螺纹设计用于任务比字符串连接更加昂贵。

字符串连接包括分配和复制存储器;这不是一个非常繁重的任务。
处理计算密集型任务时应使用多线程,并避免阻塞UI线程。

线程也可以是parallize等候上不同的东西有用的任务(例如,网络IO到多个较慢的服务器或网络与磁盘IO)

+0

或者可以并行执行的性能关键任务。 –

+0

@MarcinSeredynski:并行化通常只对计算绑定任务有帮助。 – SLaks

+0

这非常值得商榷。绝大多数线程仅用于异步。不要阻止用户界面。 –