Skip to content

Commit 607a651

Browse files
author
XieBiao
committed
make interface
1 parent 47a1946 commit 607a651

File tree

6 files changed

+222
-187
lines changed

6 files changed

+222
-187
lines changed

analysis_connection.go

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
package gorma
2+
3+
import (
4+
"os"
5+
"fmt"
6+
"sort"
7+
"strconv"
8+
"strings"
9+
"github.com/hhxsv5/go-redis-memory-analysis/storages"
10+
)
11+
12+
type AnalysisConnection struct {
13+
redis *storages.RedisClient
14+
Reports DBReports
15+
}
16+
17+
func NewAnalysisConnection(host string, port uint16, password string) (*AnalysisConnection, error) {
18+
redis, err := storages.NewRedisClient(host, port, password)
19+
if err != nil {
20+
return nil, err
21+
}
22+
return &AnalysisConnection{redis, DBReports{}}, nil
23+
}
24+
25+
func (analysis *AnalysisConnection) Close() {
26+
if analysis.redis != nil {
27+
analysis.redis.Close()
28+
}
29+
}
30+
31+
func (analysis AnalysisConnection) Start(delimiters []string) {
32+
fmt.Println("Starting analysis")
33+
match := "*[" + strings.Join(delimiters, "") + "]*"
34+
databases, _ := analysis.redis.GetDatabases()
35+
36+
var (
37+
cursor uint64
38+
r Report
39+
f float64
40+
ttl int64
41+
length uint64
42+
sr SortBySizeReports
43+
mr KeyReports
44+
)
45+
46+
for db, _ := range databases {
47+
fmt.Println("Analyzing db", db)
48+
cursor = 0
49+
mr = KeyReports{}
50+
51+
analysis.redis.Select(db)
52+
53+
for {
54+
keys, _ := analysis.redis.Scan(&cursor, match, 3000)
55+
fd, fp, tmp, nk := "", 0, 0, ""
56+
for _, key := range keys {
57+
fd, fp, tmp, nk, ttl = "", 0, 0, "", 0
58+
for _, delimiter := range delimiters {
59+
tmp = strings.Index(key, delimiter)
60+
if tmp != -1 && (tmp < fp || fp == 0) {
61+
fd, fp = delimiter, tmp
62+
}
63+
}
64+
65+
if fp == 0 {
66+
continue
67+
}
68+
69+
nk = key[0:fp] + fd + "*"
70+
71+
if _, ok := mr[nk]; ok {
72+
r = mr[nk]
73+
} else {
74+
r = Report{nk, 0, 0, 0, 0}
75+
}
76+
77+
ttl, _ = analysis.redis.Ttl(key)
78+
79+
switch ttl {
80+
case -2:
81+
continue
82+
case -1:
83+
r.NeverExpire++
84+
r.Count++
85+
default:
86+
f = float64(r.AvgTtl*(r.Count-r.NeverExpire)+uint64(ttl)) / float64(r.Count+1-r.NeverExpire)
87+
ttl, _ := strconv.ParseUint(fmt.Sprintf("%0.0f", f), 10, 64)
88+
r.AvgTtl = ttl
89+
r.Count++
90+
}
91+
92+
length, _ = analysis.redis.SerializedLength(key)
93+
r.Size += length
94+
95+
mr[nk] = r
96+
}
97+
98+
if cursor == 0 {
99+
break
100+
}
101+
}
102+
103+
//Sort by size
104+
sr = SortBySizeReports{}
105+
for _, report := range mr {
106+
sr = append(sr, report)
107+
}
108+
sort.Sort(sr)
109+
110+
analysis.Reports[db] = sr
111+
}
112+
}
113+
114+
func (analysis AnalysisConnection) SaveReports(folder string) error {
115+
fmt.Println("Saving the results of the analysis into", folder)
116+
if _, err := os.Stat(folder); os.IsNotExist(err) {
117+
os.MkdirAll(folder, os.ModePerm)
118+
}
119+
120+
var (
121+
str string
122+
filename string
123+
size float64
124+
unit string
125+
)
126+
template := fmt.Sprintf("%s%sredis-analysis-%s%s", folder, string(os.PathSeparator), strings.Replace(analysis.redis.Id, ":", "-", -1), "-%d.csv")
127+
for db, reports := range analysis.Reports {
128+
filename = fmt.Sprintf(template, db)
129+
fp, err := storages.NewFile(filename, os.O_CREATE|os.O_WRONLY, os.ModePerm)
130+
if err != nil {
131+
return err
132+
}
133+
fp.Append([]byte("Key,Count,Size,NeverExpire,AvgTtl(excluded never expire)\n"))
134+
for _, value := range reports {
135+
size, unit = HumanSize(value.Size)
136+
str = fmt.Sprintf("%s,%d,%s,%d,%d\n",
137+
value.Key,
138+
value.Count,
139+
fmt.Sprintf("%0.3f %s", size, unit),
140+
value.NeverExpire,
141+
value.AvgTtl)
142+
fp.Append([]byte(str))
143+
}
144+
fp.Close()
145+
}
146+
return nil
147+
}

analysis_interface.go

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package gorma
2+
3+
type AnalysisInterface interface {
4+
Start(delimiters []string)
5+
SaveReports(folder string) error
6+
Close()
7+
}
8+
9+
type Report struct {
10+
Key string
11+
Count uint64
12+
Size uint64
13+
NeverExpire uint64
14+
AvgTtl uint64
15+
}
16+
17+
type DBReports map[uint64][]Report
18+
type KeyReports map[string]Report
19+
type SortBySizeReports []Report
20+
type SortByCountReports []Report
21+
22+
func (sr SortBySizeReports) Len() int {
23+
return len(sr)
24+
}
25+
26+
func (sr SortBySizeReports) Less(i, j int) bool {
27+
return sr[i].Size > sr[j].Size
28+
}
29+
30+
func (sr SortBySizeReports) Swap(i, j int) {
31+
sr[i], sr[j] = sr[j], sr[i]
32+
}
33+
34+
func (sr SortByCountReports) Len() int {
35+
return len(sr)
36+
}
37+
38+
func (sr SortByCountReports) Less(i, j int) bool {
39+
return sr[i].Count > sr[j].Count
40+
}
41+
42+
func (sr SortByCountReports) Swap(i, j int) {
43+
sr[i], sr[j] = sr[j], sr[i]
44+
}

0 commit comments

Comments
 (0)