[Swift] 性能的一些測(cè)試

1.Swift中數(shù)組性能的對(duì)比

編寫性能要求高的算法時(shí)调俘,發(fā)現(xiàn)Swift對(duì)使用Array還是ContiguousArray葵孤;使用Class或者Struct作為元素咏尝,都會(huì)對(duì)性能帶來(lái)明顯的影響茎匠。

對(duì)于"向數(shù)組增加元素"的操作岭辣,對(duì)性能提升起占主導(dǎo)作用的是要使用Struct。

圖1

而對(duì)于"獲取數(shù)組中的元素"财著,使用ContiguousArray是最敏感的因素联四。

圖2

如果算法跟數(shù)組操作十分相關(guān),遇到性能不理想時(shí)撑教,在條件允許的情況下首先應(yīng)該用ContiguousArray替換Array朝墩。其次再考慮數(shù)據(jù)結(jié)構(gòu)是Class改為用Struct。

附上性能測(cè)試代碼

static let LogName = "swift"

public class MyPoint {
    public var X :Float = 0
    public var Y :Float = 0
}

public struct MyPointStruct {
    public var X :Float = 0
    public var Y :Float = 0
}

public static func testAll(){
    
    
    let startTime1 = CFAbsoluteTimeGetCurrent()
    //float_multi_test()
    let endTime1 = CFAbsoluteTimeGetCurrent()
    let diff1:Double = (endTime1 - startTime1) * 1000
    print(LogName + " 浮點(diǎn)乘法 " + String(diff1))

    //-------------------------------
    
    let startTime2 = CFAbsoluteTimeGetCurrent()
    element_add()
    let endTime2 = CFAbsoluteTimeGetCurrent()
    let diff2:Double = (endTime2 - startTime2) * 1000
    print(LogName + " 數(shù)組增加元素 " + String(diff2))
    
    let startTime2_a = CFAbsoluteTimeGetCurrent()
    element_add_contiguousArray()
    let endTime2_a = CFAbsoluteTimeGetCurrent()
    let diff2_a:Double = (endTime2_a - startTime2_a) * 1000
    print(LogName + " 數(shù)組增加元素contiguous " + String(diff2_a))

    let startTime2_b = CFAbsoluteTimeGetCurrent()
    element_add_struct()
    let endTime2_b = CFAbsoluteTimeGetCurrent()
    let diff2_b:Double = (endTime2_b - startTime2_b) * 1000
    print(LogName + " 數(shù)組增加元素struct " + String(diff2_b))
    
    let startTime2_c = CFAbsoluteTimeGetCurrent()
    element_add_contiguousArray_struct()
    let endTime2_c = CFAbsoluteTimeGetCurrent()
    let diff2_c:Double = (endTime2_c - startTime2_c) * 1000
    print(LogName + " 數(shù)組增加元素contiguous_struct " + String(diff2_c))
    //-------------------------------
    
    
    let startTime3 = CFAbsoluteTimeGetCurrent()
    element_get()
    let endTime3 = CFAbsoluteTimeGetCurrent()
    let diff3:Double = (endTime3 - startTime3) * 1000
    print(LogName + " 數(shù)組獲取元素 " + String(diff3))
    
    let startTime3_a = CFAbsoluteTimeGetCurrent()
    element_get_contiguousArray()
    let endTime3_a = CFAbsoluteTimeGetCurrent()
    let diff3_a:Double = (endTime3_a - startTime3_a) * 1000
    print(LogName + " 數(shù)組獲取元素contiguous " + String(diff3_a))
    
    let startTime3_b = CFAbsoluteTimeGetCurrent()
    element_get_struct()
    let endTime3_b = CFAbsoluteTimeGetCurrent()
    let diff3_b:Double = (endTime3_b - startTime3_b) * 1000
    print(LogName + " 數(shù)組獲取元素struct " + String(diff3_b))
    
    let startTime3_c = CFAbsoluteTimeGetCurrent()
    element_get_contiguousArray_struct()
    let endTime3_c = CFAbsoluteTimeGetCurrent()
    let diff3_c:Double = (endTime3_c - startTime3_c) * 1000
    print(LogName + " 數(shù)組獲取元素contiguous " + String(diff3_c))
}

//浮點(diǎn)乘法
public static func float_multi_test(){
    
    let times = 5999999
    var result:Float = 1

    for _ in 0 ..< times {
        for i in 2 ..< 999 {
            result = Float(1/Float(i)+0.5) * result + 0.5
        }
    }
    print(result)
}


//集合增加元素
public static func element_add(){
    let times = 5000
    var array = [MyPoint]()
    
    for _ in 0 ..< times {
        array = [MyPoint]()
        for i in 1 ..< 9999 {
            let p = MyPoint()
            p.X = (Float(i) - 1 )/Float(i)
            p.Y = p.X * 1/Float(i)
            array.append(p)
        }
    }
    print(array.count)
}

//集合增加元素struct
public static func element_add_struct(){
    let times = 5000
    var array = [MyPointStruct]()
    
    for _ in 0 ..< times {
        array = [MyPointStruct]()
        for i in 1 ..< 9999 {
            var p = MyPointStruct()
            p.X = (Float(i) - 1 )/Float(i)
            p.Y = p.X * 1/Float(i)
            array.append(p)
        }
    }
    print(array.count)
}

//集合增加元素contiguous
public static func element_add_contiguousArray(){
    
    let times = 5000
    var array = ContiguousArray<MyPoint>()
    
    for _ in 0 ..< times {
        array = ContiguousArray<MyPoint>()
        for i in 1 ..< 9999 {
            let p = MyPoint()
            p.X = (Float(i) - 1 )/Float(i)
            p.Y = p.X * 1/Float(i)
            array.append(p)
        }
    }
    print(array.count)
}

//集合增加元素contiguous_struct
public static func element_add_contiguousArray_struct(){
    
    let times = 5000
    var array = ContiguousArray<MyPointStruct>()
    
    for _ in 0 ..< times {
        array = ContiguousArray<MyPointStruct>()
        for i in 1 ..< 9999 {
            var p = MyPointStruct()
            p.X = (Float(i) - 1 )/Float(i)
            p.Y = p.X * 1/Float(i)
            array.append(p)
        }
    }
    print(array.count)
}

//集合獲取元素
public static func element_get(){
    
    let times = 5000
    var array = [MyPoint]()
    for i in 1 ..< 9999 {
        let p = MyPoint()
        p.X = (Float(i) - 1 )/Float(i)
        p.Y = p.X * 1/Float(i)
        array.append(p)
    }
    
    var result:Float = 0
    for _ in 0 ..< times {
        for i in 2 ..< 9999 {
            let p = array[i-2]
            let m = array[i-1]
            result = result + p.X + p.Y + m.X + m.Y
        }
    }
    print(result)
}

//集合獲取元素contiguous
public static func element_get_contiguousArray(){
    
    let times = 5000
    var array = ContiguousArray<MyPoint>()
    for i in 1 ..< 9999 {
        let p = MyPoint()
        p.X = (Float(i) - 1 )/Float(i)
        p.Y = p.X * 1/Float(i)
        array.append(p)
    }
    
    var result:Float = 0
    for _ in 0 ..< times {
        for i in 2 ..< 9999 {
            let p = array[i-2]
            let m = array[i-1]
            result = result + p.X + p.Y + m.X + m.Y
        }
    }
    print(result)
}

//集合獲取元素struct
public static func element_get_struct(){
    
    let times = 5000
    var array = [MyPointStruct]()
    for i in 1 ..< 9999 {
        var p = MyPointStruct()
        p.X = (Float(i) - 1 )/Float(i)
        p.Y = p.X * 1/Float(i)
        array.append(p)
    }
    
    var result:Float = 0
    for _ in 0 ..< times {
        for i in 2 ..< 9999 {
            let p = array[i-2]
            let m = array[i-1]
            result = result + p.X + p.Y + m.X + m.Y
        }
    }
    print(result)
}

//集合獲取元素contiguous_struct
public static func element_get_contiguousArray_struct(){
    
    let times = 5000
    var array = ContiguousArray<MyPointStruct>()
    for i in 1 ..< 9999 {
        var p = MyPointStruct()
        p.X = (Float(i) - 1 )/Float(i)
        p.Y = p.X * 1/Float(i)
        array.append(p)
    }
    
    var result:Float = 0
    for _ in 0 ..< times {
        for i in 2 ..< 9999 {
            let p = array[i-2]
            let m = array[i-1]
            result = result + p.X + p.Y + m.X + m.Y
        }
    }
    print(result)
}
記錄一次實(shí)戰(zhàn)效果大概是這樣的

1)沒(méi)有改善前伟姐,算法運(yùn)行耗時(shí)【124s】

2)改用ContiguousArray后收苏,算法運(yùn)行耗時(shí)【60s】

3)在ContiguousArray的基礎(chǔ)上再把關(guān)鍵數(shù)據(jù)類型改用Struct,運(yùn)行耗時(shí)變成【50s】

我想這樣的結(jié)果應(yīng)該和大部分算法的調(diào)優(yōu)過(guò)程會(huì)很接近愤兵,畢竟通常情況下讀取數(shù)組比寫數(shù)組的操作頻率要高鹿霸,那么ContiguousArray的使用會(huì)顯得更要緊一些。

2.Swift和ObjectC在乘法和數(shù)組操作上的對(duì)比

在安卓開(kāi)發(fā)時(shí)秆乳,高性能要求的部分可能就不會(huì)再用java實(shí)現(xiàn)了懦鼠。所以對(duì)于性能優(yōu)先的情況下钻哩,ios開(kāi)發(fā)平臺(tái)選擇哪種開(kāi)發(fā)語(yǔ)言也需要做個(gè)決斷。
性能測(cè)試代碼還是跟上面貼的那段一樣肛冶,改用ObjectC實(shí)現(xiàn)街氢。
簡(jiǎn)單測(cè)試得出的結(jié)論是,Swift用來(lái)寫算法問(wèn)題不大睦袖。

圖3

Swift的乘法性能比Object稍差珊肃,但是集合操作有優(yōu)勢(shì)。不過(guò)這也取決于ObjectC的集合操作用法馅笙。鑒于題目是高性能要求的算法是否要ObjectC改寫Swift伦乔,這里已經(jīng)基本得到大致結(jié)論,ObjectC應(yīng)該不會(huì)提升相對(duì)于Swift幾何倍數(shù)的性能延蟹。所以不是非常極限的情況下评矩,用Swift寫算法是可以的。

3.Swift和Java在乘法和數(shù)組操作上的對(duì)比

最后再把鄙人經(jīng)常干的事情阱飘,就是各個(gè)平臺(tái)移植算法需要考慮的一個(gè)測(cè)試也做了。自從Swift產(chǎn)生虱颗,看到的都是好評(píng)一片沥匈。私以為,那是以O(shè)bjectC為參照的罷了忘渔。測(cè)試邏輯還是一樣高帖,最前面貼出的代碼Swift翻版Java實(shí)現(xiàn)。結(jié)論大概就是下圖這樣的畦粮。


圖4

圖5

這里Swift的添加和獲取元素的操作散址,用的是它最快的組合ContiguousArray+Struct了。
在這樣簡(jiǎn)單的測(cè)試用例下宣赔, Swift還是能看到Java的車尾燈预麸。性能有差距,對(duì)于這樣的新語(yǔ)言來(lái)說(shuō)請(qǐng)繼續(xù)等待它的發(fā)展儒将。

最近一次Swift發(fā)展的后果就是吏祸,鄙人在不改算法的情況下,升級(jí)了系統(tǒng)版本和XCode钩蚊,把Swift3升級(jí)到Swift3.3贡翘,結(jié)果就是性能下降10%。不管是OS有升級(jí)還是是Xcode有升級(jí)砰逻,反正都是蘋果的鍋鸣驱。我只能說(shuō)慶幸不是Swift當(dāng)主打語(yǔ)言的開(kāi)發(fā)者,對(duì)于是的人蝠咆,你們辛苦了踊东。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子递胧,更是在濱河造成了極大的恐慌碑韵,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缎脾,死亡現(xiàn)場(chǎng)離奇詭異祝闻,居然都是意外死亡可很,警方通過(guò)查閱死者的電腦和手機(jī)肯腕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門疾呻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)耙厚,“玉大人嫉入,你說(shuō)我怎么就攤上這事批什∧寻疲” “怎么了囚聚?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵贺拣,是天一觀的道長(zhǎng)蓖谢。 經(jīng)常有香客問(wèn)我,道長(zhǎng)譬涡,這世上最難降的妖魔是什么闪幽? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮涡匀,結(jié)果婚禮上盯腌,老公的妹妹穿的比我還像新娘。我一直安慰自己陨瘩,他們只是感情好腕够,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著舌劳,像睡著了一般帚湘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上蒿囤,一...
    開(kāi)封第一講書(shū)人閱讀 52,158評(píng)論 1 308
  • 那天客们,我揣著相機(jī)與錄音,去河邊找鬼材诽。 笑死底挫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脸侥。 我是一名探鬼主播建邓,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼睁枕!你這毒婦竟也來(lái)了官边?” 一聲冷哼從身側(cè)響起沸手,我...
    開(kāi)封第一講書(shū)人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎注簿,沒(méi)想到半個(gè)月后契吉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诡渴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年捐晶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妄辩。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惑灵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出眼耀,到底是詐尸還是另有隱情英支,我是刑警寧澤,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布哮伟,位于F島的核電站干花,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏澈吨。R本人自食惡果不足惜把敢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望谅辣。 院中可真熱鬧,春花似錦婶恼、人聲如沸桑阶。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蚣录。三九已至,卻和暖如春眷篇,著一層夾襖步出監(jiān)牢的瞬間萎河,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工蕉饼, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虐杯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓昧港,卻偏偏與公主長(zhǎng)得像擎椰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子创肥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 1达舒、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明先生_X自主閱讀 15,985評(píng)論 3 119
  • 4#時(shí)間管理100-案例課程分享(最幸福的時(shí)候就是你告訴我值朋,你因我而過(guò)得更好by亦凡) 通過(guò)葉老師的學(xué)習(xí)有了很多的...
    飛翔_9215閱讀 279評(píng)論 0 0
  • 想你的時(shí)候 我 站成曠野 風(fēng)干的蘆葦 盈殘的絮 從我的發(fā)際 飄墜 ――伶仃 是我經(jīng)年的風(fēng)景 想你的時(shí)候 我 焦渴成...
    冰之焰閱讀 396評(píng)論 1 2
  • 怨恨就如自己服了毒,卻坐等別人死巩搏∽虻牵— Malachy McCourt ???? 人爭(zhēng)一口氣,佛爭(zhēng)一炷香贯底,一切與茶何...
    GrapeJam閱讀 604評(píng)論 0 0