最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang利用位運(yùn)算實(shí)現(xiàn)為程序加速

 更新時(shí)間:2022年08月02日 15:07:46   作者:crossoverJie  
這篇文章主要為大家詳細(xì)介紹了如何在Golang中利用位運(yùn)算實(shí)現(xiàn)為程序加速功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下

前言

最近在持續(xù)優(yōu)化之前編寫(xiě)的 JSON 解析庫(kù) xjson,主要是兩個(gè)方面的優(yōu)化。

第一個(gè)是支持將一個(gè) JSONObject 對(duì)象輸出為 JSON 字符串。

這點(diǎn)在上個(gè)版本中只是利用自帶的 Print 函數(shù)打印數(shù)據(jù):

func TestJson4(t *testing.T)  {
	str := `{"people":{"name":{"first":"bob"}}}`
	first := xjson.Get(str, "people.name.first")
	assert.Equal(t, first.String(), "bob")
	get := xjson.Get(str, "people")
	fmt.Println(get.String())
	//assert.Equal(t, get.String(),`{"name":{"first":"bob"}}`)
}

Output:

map[name:map[first:bob]]

本次優(yōu)化之后便能直接輸出 JSON 字符串了:

實(shí)現(xiàn)過(guò)程也很簡(jiǎn)單,只需要遞歸遍歷 object 中的數(shù)據(jù),然后拼接字符串即可,核心代碼如下:

func (r Result) String() string {
	switch r.Token {
	case String:
		return fmt.Sprint(r.object)
	case Bool:
		return fmt.Sprint(r.object)
	case Number:
		i, _ := strconv.Atoi(fmt.Sprint(r.object))
		return fmt.Sprintf("%d", i)
	case Float:
		i, _ := strconv.ParseFloat(fmt.Sprint(r.object), 64)
		return fmt.Sprintf("%f", i)
	case JSONObject:
		return object2JSONString(r.object)
	case ArrayObject:
		return object2JSONString(r.Array())
	default:
		return ""
	}
}

用位運(yùn)算優(yōu)化

第二個(gè)優(yōu)化主要是提高了性能,查詢一個(gè)復(fù)雜 JSON 數(shù)據(jù)的時(shí)候性能提高了大約 ?16%.

# 優(yōu)化前
BenchmarkDecode-12         90013             66905 ns/op           42512 B/op       1446 allocs/op

# 優(yōu)化后
BenchmarkDecode-12        104746             59766 ns/op           37749 B/op       1141 allocs/op

這里截取了一些重點(diǎn)改動(dòng)的部分:

在 JSON 解析過(guò)程中會(huì)有一個(gè)有限狀態(tài)機(jī)狀態(tài)遷移的過(guò)程,而遷移的時(shí)候可能會(huì)出現(xiàn)多個(gè)狀態(tài)。

比如當(dāng)前解析到的 token 值為 {,那它接下來(lái)的 token 可能會(huì)為 ObjectKey:"name",也可能會(huì)是 BeginObject:{,當(dāng)然也可能會(huì)是 EndObject:}
所以在優(yōu)化之前我是將狀態(tài)全部存放在一個(gè)集合中的,在解析過(guò)程中如果發(fā)現(xiàn)狀態(tài)不滿足預(yù)期的列表時(shí)則會(huì)拋出語(yǔ)法異常的錯(cuò)誤。

所以優(yōu)化之前是遍歷這個(gè)集合來(lái)進(jìn)行判斷的,這樣的時(shí)間復(fù)雜度為 O(N),但當(dāng)我們換成位運(yùn)算就不一樣了,時(shí)間復(fù)雜度直接就變?yōu)?code>O(1)了,同時(shí)還節(jié)省了一個(gè)切片的存儲(chǔ)空間。

我們簡(jiǎn)單來(lái)分析下這個(gè)位運(yùn)算為什么會(huì)達(dá)到判斷一個(gè)數(shù)據(jù)是否在一個(gè)集合中同樣的效果。

首先以這兩個(gè)狀態(tài)為例:

	StatusObjectKey   status = 0x0002
	StatusColon       status = 0x0004

他們分別對(duì)應(yīng)的二進(jìn)制數(shù)據(jù)為:

	StatusObjectKey   status = 0x0002 //0010
	StatusColon       status = 0x0004 //0100

當(dāng)我們對(duì)這兩個(gè)數(shù)據(jù)求 | 運(yùn)算得到的數(shù)據(jù)是 0110

A:0010
B:0100

C:0110

這時(shí)候如何我們?nèi)绻眠@兩個(gè)原始數(shù)據(jù)與 C:0110 做 & 運(yùn)算時(shí)就會(huì)還原為剛才的兩個(gè)數(shù)據(jù)。

// input:
A:0010
C:0110

// output:
A:0010

----------
// input:
B:0100
C:0110

// output:
B:0100

但我們換一個(gè) D 與 C 求 & 時(shí):

D: 1000 // 0x0008 對(duì)應(yīng)的二進(jìn)制為 1000
C: 0110
D':0000

將會(huì)得到一個(gè) 0 值,只要得出的數(shù)據(jù)大于 0 我們就能判斷一個(gè)數(shù)據(jù)是否在給定的集合中了。

當(dāng)然這里有一個(gè)前提條件就是,我們輸入的數(shù)據(jù)高位永遠(yuǎn)都是是 1 才行,也就是2的冪。

同樣的優(yōu)化在解析查詢語(yǔ)法時(shí)也有使用:

其他奇淫巧技

當(dāng)然位運(yùn)算還有一些其他技巧,比如判斷奇偶數(shù):

// 偶數(shù)
a & 1 == 0

// 奇數(shù)
a & 1 == 1

乘法和除法,右移1一位是除以2,左移一位是乘以2.

x := 2
fmt.Println(x>>1) //1
fmt.Println(x<<1) //4

總結(jié)

位運(yùn)算在帶來(lái)程序性能提升的同時(shí)也降低代碼可讀性,所以我們得按需選擇是否使用;

再一些底層庫(kù)、框架代碼對(duì)性能有極致追求的場(chǎng)景推薦使用,但在業(yè)務(wù)代碼中對(duì)數(shù)據(jù)做加減乘除就沒(méi)必要用位運(yùn)算了,只會(huì)讓后續(xù)的維護(hù)者一臉懵逼。

到此這篇關(guān)于Golang利用位運(yùn)算實(shí)現(xiàn)為程序加速的文章就介紹到這了,更多相關(guān)Golang位運(yùn)算內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go 互斥鎖和讀寫(xiě)互斥鎖的實(shí)現(xiàn)

    Go 互斥鎖和讀寫(xiě)互斥鎖的實(shí)現(xiàn)

    本文主要介紹了Go 互斥鎖和讀寫(xiě)互斥鎖的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 關(guān)于golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接的問(wèn)題

    關(guān)于golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接的問(wèn)題

    這篇文章主要介紹了golang監(jiān)聽(tīng)rabbitmq消息隊(duì)列任務(wù)斷線自動(dòng)重連接,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • golang 如何通過(guò)反射創(chuàng)建新對(duì)象

    golang 如何通過(guò)反射創(chuàng)建新對(duì)象

    這篇文章主要介紹了golang 通過(guò)反射創(chuàng)建新對(duì)象的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-04-04
  • golang 實(shí)用庫(kù)gotable的具體使用

    golang 實(shí)用庫(kù)gotable的具體使用

    使用gotable框架以實(shí)現(xiàn)在CLI命令行界面中打印表格。本文就介紹一下golang 實(shí)用庫(kù)gotable的使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • 一文帶你深入了解Go語(yǔ)言中切片的奧秘

    一文帶你深入了解Go語(yǔ)言中切片的奧秘

    切片是數(shù)組的一個(gè)引用,因此切片是引用類型。但自身是結(jié)構(gòu)體,值拷貝傳遞。本文將通過(guò)示例帶大家一起探索一下Go語(yǔ)言中切片的奧秘,感興趣的可以了解一下
    2022-11-11
  • golang實(shí)現(xiàn)webgis后端開(kāi)發(fā)的步驟詳解

    golang實(shí)現(xiàn)webgis后端開(kāi)發(fā)的步驟詳解

    這篇文章主要介紹如何用golang結(jié)合postgis數(shù)據(jù)庫(kù),使用gin、grom框架實(shí)現(xiàn)后端的MVC的接口搭建,文中有詳細(xì)的流程步驟及代碼示例,需要的朋友可以參考下
    2023-06-06
  • 詳解go如何優(yōu)雅的使用接口與繼承

    詳解go如何優(yōu)雅的使用接口與繼承

    Go語(yǔ)言中的接口和嵌套結(jié)構(gòu)體是兩種重要的代碼設(shè)計(jì)方式,接口定義了一組方法簽名,使得不同的類型能夠以相同的方式進(jìn)行交互,本文將給大家介紹go語(yǔ)言如何優(yōu)雅的使用接口與繼承,文中有詳細(xì)的代碼供大家參考,需要的朋友可以參考下
    2024-06-06
  • golang?對(duì)象深拷貝的常見(jiàn)方式及性能

    golang?對(duì)象深拷貝的常見(jiàn)方式及性能

    這篇文章主要介紹了golang?對(duì)象深拷貝的常見(jiàn)方式及性能,Go語(yǔ)言中所有賦值操作都是值傳遞,如果結(jié)構(gòu)中不含指針,則直接賦值就是深度拷貝,文章圍繞主題展開(kāi)更多相關(guān)資料,需要的小伙伴可以參考一下
    2022-06-06
  • 一文帶你掌握Go語(yǔ)言中的文件讀取操作

    一文帶你掌握Go語(yǔ)言中的文件讀取操作

    這篇文章主要和大家分享一下Go語(yǔ)言中的文件讀取操作,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Go語(yǔ)言有一定的幫助,需要的小伙伴可以參考一下
    2022-12-12
  • Go語(yǔ)言context上下文管理的使用

    Go語(yǔ)言context上下文管理的使用

    本文主要介紹了Go語(yǔ)言context上下文管理的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03

最新評(píng)論

西青区| 瑞丽市| 奈曼旗| 广西| 聊城市| 天水市| 衢州市| 肇州县| 临漳县| 马龙县| 宜春市| 铜山县| 金塔县| 福建省| 察雅县| 皮山县| 东源县| 深圳市| 苗栗县| 涿州市| 诏安县| 通山县| 皋兰县| 洞头县| 高青县| 景德镇市| 旬阳县| 台中县| 桃园市| 英吉沙县| 德清县| 永清县| 且末县| 阜新| 亚东县| 高碑店市| 清涧县| 莱芜市| 宁南县| 扶沟县| 会同县|