当前位置:网站首页>Speed up your programs with bitwise operations
Speed up your programs with bitwise operations
2022-08-02 02:00:00 【crossoverJie】

Foreword
The JSON parsing library xjson, which was recently written before continuous optimization, is mainly optimized in two aspects.
The first is to support outputting a JSONObject object as a JSON string.
In the previous version, the data was printed using the built-in Print function:
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]]After this optimization, the JSON string can be output directly:

The implementation process is also very simple, just need to recursively traverse the data in the object, and then splicing strings, the core code is as follows:
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 "" }}
Optimize with bitwise operations
The second optimization is mainly to improve performance. When querying a complex JSON data, the performance is improved by about 16%.
# BenchmarkDecode-12 before optimization 90013 66905 ns/op 42512 B/op 1446 allocs/op# BenchmarkDecode-12 after optimization 104746 59766 ns/op 37749 B/op 1141 allocs/opHere are some important changes:

There will be a finite state machine state transition process during JSON parsing, and there may be multiple states during the transition.
For example, the currently parsed token value is {, then its next token may be ObjectKey:"name", or BeginObject:{, of course it may also be EndObject:}, so before optimization, I store all the states in a collection. During the parsing process, if I find that the state does not meet the expectationsA syntax exception error will be thrown.

So before optimization, we traverse this set to make judgments. This time complexity is O(N), but when we switch to bit operations, it is different, and the time complexity is directlyIt becomes O(1), while saving the storage space of a slice.
Let's simply analyze why this bit operation achieves the same effect of judging whether a data is in a set.
Take these two states as an example:
StatusObjectKey status = 0x0002 StatusColon status = 0x0004The corresponding binary data are:
StatusObjectKey status = 0x0002 //0010 StatusColon status = 0x0004 //0100When we perform the | operation on these two data, the data obtained is 0110:
A:0010B:0100C:0110At this time, if we use these two original data and C:0110 to do the & operation, it will be restored to the two data just now.
// input:A:0010C:0110// output:A:0010----------// input:B:0100C:0110//output:B:0100But when we change a D and C to find &:
D: 1000 // 0x0008 corresponds to binary 1000C: 0110D':0000will get a 0 value, as long as the data obtained is greater than 0, we can judge whether a data is in the given set.
> Of course, there is a precondition here that the high bit of the data we input is always 1, which is a power of 2.
The same optimization is used when parsing query syntax:

Other strange tricks
Of course, there are some other tricks for bit operations, such as judging odd and even numbers:
// even a & 1 == 0// odd a & 1 == 1Multiplication and division, right shift 1 bit is divided by 2, left shift is multiplied by 2.
x := 2fmt.Println(x>>1) //1fmt.Println(x<<1) //4Summary
Bit operations not only improve program performance but also reduce code readability, so we have to choose whether to use it or not;
It is recommended to use some low-level libraries and framework codes that have the ultimate pursuit of performance. However, it is not necessary to use bit operations to add, subtract, multiply and divide data in business code, which will only make subsequent maintainers look confused..
Related code: https://github.com/crossoverJie/xjson
边栏推荐
- Pcie the inbound and outbound
- 用位运算为你的程序加速
- Basic use of typescript34-class
- Local storage in Kubernetes
- Named parameter implementation of JDBC PreparedStatement
- Constructor instance method inheritance of typescript37-class (extends)
- JDBC PreparedStatement 的命名参数实现
- LeetCode brushing diary: 53, the largest sub-array and
- 垃圾回收器CMS和G1
- LeetCode Review Diary: 34. Find the first and last position of an element in a sorted array
猜你喜欢

HSDC和独立生成树相关

The Paddle Open Source Community Quarterly Report is here, everything you want to know is here

数据链路层的数据传输

LeetCode刷题日记:LCP 03.机器人大冒险

Fly propeller power space future PIE - Engine Engine build earth science

The characteristics and principle of typescript29 - enumeration type

2023年起,这些地区软考成绩低于45分也能拿证

typescript35-class的构造函数

typescript38-class的构造函数实例方法继承(implement)

超大规模的产业实用语义分割数据集PSSL与预训练模型开源啦!
随机推荐
Multi-Party Threshold Private Set Intersection with Sublinear Communication-2021: Interpretation
volatile原理解析
typescript30-any类型
Fly propeller power space future PIE - Engine Engine build earth science
电商库存系统的防超卖和高并发扣减方案
Constructor instance method inheritance of typescript37-class (extends)
Redis 底层的数据结构
Understand the big model in seconds | 3 steps to get AI to write a summary
『网易实习』周记(三)
秒懂大模型 | 3步搞定AI写摘要
Day116. Shangyitong: Details of appointment registration ※
哈希表
60种特征工程操作:使用自定义聚合函数【收藏】
MySQL optimization strategy
记录一次数组转集合出现错误的坑点,尽量使用包装类型数组进行转换
Navicat data shows incomplete resolution
软件测试 接口自动化测试 pytest框架封装 requests库 封装统一请求和多个基础路径处理 接口关联封装 测试用例写在yaml文件中 数据热加载(动态参数) 断言
hash table
雇用WordPress开发人员:4个实用的方法
The Paddle Open Source Community Quarterly Report is here, everything you want to know is here