2016-01-19 63 views
0

當我使用+ =運算符將一個字符串追加到Swift中的另一個字符串時,代碼中執行了哪個進程?如果我做了str1 + = str2,在str1的末尾分配了內存,並且在那裏複製了str2,或者是爲新字符串的組合長度分配的內存,那麼這些字符串會被複制到哪裏? 我寫了一個將字符串附加在一起的線性方法和一個平分方法,並定時了這兩種方法。平分法比直線法快2倍。追加過程中是否有任何機制可以解釋這兩種方法的時代如此相似?swift string append mechanics

var start = NSDate().timeIntervalSince1970 
    let _ = stringMe(400000000, str:"Developers! ") 
    var end = NSDate().timeIntervalSince1970 

    var duration = end - start; 
    print("stringMe takes: \(duration)"); 


    start = NSDate().timeIntervalSince1970 
    let _ = stringMe2(400000000, str:"Developers! ") 
    end = NSDate().timeIntervalSince1970 

    duration = end - start; 
    print("stringMe2 takes: \(duration)"); 


func stringMe(n:Int, str:String)-> String { 

    var string = "" 

    for _ in 0..<n{ 
     string += str 
    } 


    return string 
} 

func stringMe2(n:Int, str:String)->String 
{ 

    var string = str 

    var currentWritten = 1 

    while currentWritten < n { 

     if currentWritten*2>n { 

      string += stringMe2(n-currentWritten, str: str) 

      break 

     } 


     currentWritten*=2 
     string+=string 

    } 

    return string 

} 

回答

1

我不知道你的電腦有多少內存,但是我們正在看最後一組串聯中的4.8G字符串。這意味着,當您按順序增長字符串時,堆管理將不太可能導致頁面錯誤。

讓我們假設每個字符串連接都分配一個新的內存塊,然後複製兩個字符串以獲得結果,然後釋放原始內存以便以後重用。

從第3個連接開始,從前兩個操作釋放的內存足夠大,可以保存下一個結果。這將不會導致頁面錯誤,直到它接近極限(如果它甚至)。

另一方面,指數副本永遠不會找到足夠下一個結果的可重用內存,並且會達到虛擬內存垃圾回收閾值,此時需要分頁輸出部分資源和頁面輸入部分目的地。

連續級聯從不需要比源和目標的大小加上字符串的一個實例更多的內存:即2n + 1個字符串(大約9.6Gb)。在接下來的兩個操作中,它將釋放n和n + 1,這將給它足夠的空間來容納至少一個n + 3副本。

指數級聯需要源的一個副本和兩倍大的目標。存儲器中的n + 2 * n用於複製操作(約14.4Gb)。在下一個操作中它將釋放3 * n,但結果所需的內存塊將是4 * n,然後釋放7 * n將需要8 * n等等,永遠不會找到足夠大的塊

隨着指數複製的進展,它會創建越來越多的分頁,而不是可能達不到閾值的順序方法。

總之,您的數字太大,無法進行有意義的比較,因爲您遇到了干擾結果的內存問題。

相關問題