Skip to content

Commit

Permalink
性能改进, 每次并发查询从 7000 降低到 700 ns
Browse files Browse the repository at this point in the history
  • Loading branch information
xluohome committed Mar 27, 2017
1 parent 54154f7 commit f2bfbf1
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 28 deletions.
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

### 安装使用


vi test.go

```
package main
Expand All @@ -44,17 +44,25 @@ func main() {
fmt.Print(pr)
}
````
go run test.go
```
PhoneNum: 18957509123
AreaZone: 0575
CardType: 中国电信
City: 绍兴
ZipCode: 312000
Province: 浙江
```
### 性能测试
Thinkpad s3 (Intel(R) Core(TM) i5-4200U CPU @ 1.60GHz)
```
go test -v --bench="."

BenchmarkFindPhone-4 200000 6909 ns/op
BenchmarkFindPhone-4 2000000 710 ns/op

```
Expand Down
82 changes: 59 additions & 23 deletions phonedata.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package phonedata

import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io/ioutil"
"os"
"path"
"runtime"
"strconv"
)

const (
Expand Down Expand Up @@ -45,6 +43,7 @@ var (
CUCC_v: "中国联通虚拟运营商",
CMCC_v: "中国移动虚拟运营商",
}
total_len, firstoffset int32
)

func init() {
Expand All @@ -58,6 +57,8 @@ func init() {
if err != nil {
panic(err)
}
total_len = int32(len(content))
firstoffset = get4(content[INT_LEN : INT_LEN*2])
}

func Debug() {
Expand All @@ -70,6 +71,54 @@ func (pr PhoneRecord) String() string {
return fmt.Sprintf("PhoneNum: %s\nAreaZone: %s\nCardType: %s\nCity: %s\nZipCode: %s\nProvince: %s\n", pr.PhoneNum, pr.AreaZone, pr.CardType, pr.City, pr.ZipCode, pr.Province)
}

func get4(b []byte) int32 {
if len(b) < 4 {
return 0
}
return int32(b[0]) | int32(b[1])<<8 | int32(b[2])<<16 | int32(b[3])<<24
}

func getN(s string) (uint32, error) {
var n, cutoff, maxVal uint32
i := 0
base := 10
cutoff = (1<<32-1)/10 + 1
maxVal = 1<<uint(32) - 1
for ; i < len(s); i++ {
var v byte
d := s[i]
switch {
case '0' <= d && d <= '9':
v = d - '0'
case 'a' <= d && d <= 'z':
v = d - 'a' + 10
case 'A' <= d && d <= 'Z':
v = d - 'A' + 10
default:
return 0, errors.New("invalid syntax")
}
if v >= byte(base) {
return 0, errors.New("invalid syntax")
}

if n >= cutoff {
// n*base overflows
n = (1<<32 - 1)
return n, errors.New("value out of range")
}
n *= uint32(base)

n1 := n + uint32(v)
if n1 < n || n1 > maxVal {
// n+v overflows
n = (1<<32 - 1)
return n, errors.New("value out of range")
}
n = n1
}
return n, nil
}

func version() string {
return string(content[0:INT_LEN])
}
Expand All @@ -79,20 +128,7 @@ func totalRecord() int32 {
}

func firstRecordOffset() int32 {
var offset int32
buffer := bytes.NewBuffer(content[INT_LEN : INT_LEN*2])
binary.Read(buffer, binary.LittleEndian, &offset)
return offset
}

func indexRecord(offset int32) (phone_prefix int32, record_offset int32, card_type byte) {
buffer := bytes.NewBuffer(content[offset : offset+INT_LEN])
binary.Read(buffer, binary.LittleEndian, &phone_prefix)
buffer = bytes.NewBuffer(content[offset+INT_LEN : offset+INT_LEN*2])
binary.Read(buffer, binary.LittleEndian, &record_offset)
buffer = bytes.NewBuffer(content[offset+INT_LEN*2 : offset+INT_LEN*2+CHAR_LEN])
binary.Read(buffer, binary.LittleEndian, &card_type)
return
return get4(content[INT_LEN : INT_LEN*2])
}

// 二分法查询phone数据
Expand All @@ -102,24 +138,24 @@ func Find(phone_num string) (pr *PhoneRecord, err error) {
}

var left int32
phone_seven_int, err := strconv.ParseInt(phone_num[0:7], 10, 32)
phone_seven_int, err := getN(phone_num[0:7])
if err != nil {
return nil, errors.New("illegal phone number")
}
phone_seven_int32 := int32(phone_seven_int)
total_len := int32(len(content))
right := totalRecord()
firstoffset := firstRecordOffset()
right := (total_len - firstoffset) / PHONE_INDEX_LENGTH
for {
if left > right {
break
}
mid := (left + right) / 2
current_offset := firstoffset + mid*PHONE_INDEX_LENGTH
if current_offset >= total_len {
offset := firstoffset + mid*PHONE_INDEX_LENGTH
if offset >= total_len {
break
}
cur_phone, record_offset, card_type := indexRecord(current_offset)
cur_phone := get4(content[offset : offset+INT_LEN])
record_offset := get4(content[offset+INT_LEN : offset+INT_LEN*2])
card_type := content[offset+INT_LEN*2 : offset+INT_LEN*2+CHAR_LEN][0]
switch {
case cur_phone > phone_seven_int32:
right = mid - 1
Expand Down
2 changes: 1 addition & 1 deletion phonedata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func BenchmarkFindPhone(b *testing.B) {
var i = 0
for p.Next() {
i++
_, err := Find(fmt.Sprintf("%s%d%s", "1897", i, "45"))
_, err := Find(fmt.Sprintf("%s%d%s", "1897", i&10000, "45"))
if err != nil {
b.Fatal(err)
}
Expand Down

0 comments on commit f2bfbf1

Please sign in to comment.