Skip to content

Commit ea5c725

Browse files
added example of profiling and benchmark testing.
1 parent 8a86e5c commit ea5c725

File tree

4 files changed

+12888
-137
lines changed

4 files changed

+12888
-137
lines changed

examples/README.md

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
11
# Optimizely Go SDK Examples
22

3-
4-
### Content
5-
There are 2 functions:
6-
7-
* `examples()`
8-
* `stressTest()`
9-
10-
`examples()` shows how to instantiate and execute various versions of Optimizely Clients
11-
12-
`stressTest()` is used to stress test our optimizely app and run cpu and memory profiling
13-
14-
153
### Profiling
164
Prerequisite: `go get github.com/pkg/profile`
175

18-
* CPU profile. Execute: `go build -ldflags "-X main.RunCPUProfile=true" main.go && ./main`. It will create cpu.pprof file in your current directory. Then run: `go tool pprof -http=:8080 cpu.pprof` and profile cpu usage using web browser.
19-
* Memory profile. Execute: `go build -ldflags "-X main.RunMemProfile=true" main.go && ./main`. It will create mem.pprof file in your current directory. Then run: `go tool pprof -http=:8080 mem.pprof` and profile memory using browser.
6+
* CPU profile. Execute: `go build -ldflags "-X main.RunCPUProfile=true" main_profile_feature.go && ./main_profile_feature`. It will create cpu.pprof file in your current directory. Then run: `go tool pprof -http=:8080 cpu.pprof` and profile cpu usage using web browser.
7+
* Memory profile. Execute: `go build -ldflags "-X main.RunMemProfile=true" main_profile_feature.go.go && ./main_profile_feature`. It will create mem.pprof file in your current directory. Then run: `go tool pprof -http=:8080 mem.pprof` and profile memory using browser.

examples/main.go

Lines changed: 7 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -5,110 +5,24 @@ package main
55

66
import (
77
"context"
8-
"encoding/json"
98
"fmt"
10-
"io/ioutil"
11-
"log"
12-
"os"
13-
"path"
149
"time"
1510

1611
"github.com/optimizely/go-sdk/optimizely/client"
17-
"github.com/optimizely/go-sdk/optimizely/decision"
1812
"github.com/optimizely/go-sdk/optimizely/entities"
1913
"github.com/optimizely/go-sdk/optimizely/logging"
20-
"github.com/optimizely/go-sdk/optimizely/notification"
21-
22-
"github.com/pkg/profile"
2314
)
2415

25-
// stressTest has everything that test app has. it is used to run profile
26-
func stressTest() {
27-
/*
28-
For the test app, the biggest json file is used with 100 entities.
29-
DATAFILES_DIR has to be set to point to the path where 100_entities.json is located.
30-
*/
31-
type isFeatureEnabledRequestParams struct {
32-
FeatureKey string `json:"feature_flag_key"`
33-
UserID string `json:"user_id"`
34-
Attributes map[string]interface{} `json:"attributes"`
35-
}
36-
37-
type Context struct {
38-
CustomEventDispatcher string `json:"custom_event_dispatcher"`
39-
RequestID string `json:"request_id"`
40-
UserProfileService string `json:"user_profile_service"`
41-
Datafile string `json:"datafile"`
42-
DispatchedEvents []map[string]interface{} `json:"dispatched_events"`
43-
}
44-
45-
strBytes := []byte(` { "context": {
46-
"datafile": "100_entities.json",
47-
"custom_event_dispatcher": "ProxyEventDispatcher",
48-
"request_id": "4e3e37e3-c7ae-4cb6-bbb5-f6ef93c84d43",
49-
"user_profile_service": "NoOpService",
50-
"user_profiles": [],
51-
"with_listener": []
52-
},
53-
"user_id": "test_user_1",
54-
"feature_flag_key": "feature_5",
55-
"attributes": {
56-
"attr_5": "testvalue"
57-
}
58-
}`)
59-
60-
var params isFeatureEnabledRequestParams
61-
err := json.Unmarshal(strBytes, &params)
62-
if err != nil {
63-
log.Fatal(err)
64-
}
65-
66-
var requestBodyMap map[string]*json.RawMessage
67-
68-
err = json.Unmarshal(strBytes, &requestBodyMap)
69-
if err != nil {
70-
log.Fatal(err)
71-
}
72-
73-
var fscCtx Context
74-
err = json.Unmarshal(*requestBodyMap["context"], &fscCtx)
75-
if err != nil {
76-
log.Fatal(err)
77-
}
78-
79-
var datafileDir = path.Join(os.Getenv("DATAFILES_DIR"), fscCtx.Datafile)
80-
81-
datafile, err := ioutil.ReadFile(datafileDir)
82-
if err != nil {
83-
log.Fatal(err)
84-
}
85-
86-
optlyClient := &client.OptimizelyFactory{
87-
Datafile: datafile,
88-
}
16+
func main() {
8917

18+
logging.SetLogLevel(logging.LogLevelDebug)
9019
user := entities.UserContext{
91-
ID: params.UserID,
92-
Attributes: params.Attributes,
93-
}
94-
95-
// Creates a default, canceleable context
96-
notificationCenter := notification.NewNotificationCenter()
97-
decisionService := decision.NewCompositeService(notificationCenter)
98-
99-
clientOptions := client.Options{
100-
DecisionService: decisionService,
101-
}
102-
clientApp, err := optlyClient.ClientWithOptions(clientOptions)
103-
if err != nil {
104-
log.Fatal(err)
20+
ID: "mike ng",
21+
Attributes: map[string]interface{}{
22+
"country": "Unknown",
23+
"likes_donuts": true,
24+
},
10525
}
106-
107-
clientApp.IsFeatureEnabled(params.FeatureKey, user)
108-
}
109-
110-
func examples() {
111-
logging.SetLogLevel(logging.LogLevelDebug)
11226
optimizelyFactory := &client.OptimizelyFactory{
11327
SDKKey: "4SLpaJA1r1pgE6T2CoMs9q",
11428
}
@@ -122,14 +36,6 @@ func examples() {
12236
return
12337
}
12438

125-
user := entities.UserContext{
126-
ID: "mike ng",
127-
Attributes: map[string]interface{}{
128-
"country": "Unknown",
129-
"likes_donuts": true,
130-
},
131-
}
132-
13339
enabled, _ := app.IsFeatureEnabled("mutext_feat", user)
13440
fmt.Printf("Is feature enabled? %v\n", enabled)
13541

@@ -176,27 +82,5 @@ func examples() {
17682

17783
enabled, _ = app.IsFeatureEnabled("mutext_feat", user)
17884
fmt.Printf("Is feature enabled? %v\n", enabled)
179-
}
180-
181-
var RunMemProfile = "false"
182-
var RunCPUProfile = "false"
183-
184-
func main() {
185-
186-
if RunMemProfile == "true" || RunCPUProfile == "true" {
187-
188-
const RUN_NUMBER = 50
189-
if RunMemProfile == "true" {
190-
defer profile.Start(profile.MemProfile, profile.ProfilePath("."), profile.MemProfileRate(1)).Stop()
191-
} else if RunCPUProfile == "true" {
192-
defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop()
193-
}
194-
195-
for i := 0; i < RUN_NUMBER; i++ {
196-
stressTest()
197-
}
198-
} else {
199-
examples()
200-
}
20185

20286
}

optimizely/config/datafileprojectconfig/json_parser_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
package datafileprojectconfig
1818

1919
import (
20+
"encoding/json"
2021
"fmt"
22+
"io/ioutil"
23+
"log"
2124
"testing"
2225

2326
"github.com/optimizely/go-sdk/optimizely/config/datafileprojectconfig/entities"
@@ -59,3 +62,18 @@ func TestParseDatafilePasses(t *testing.T) {
5962

6063
assert.Equal(t, expectedDatafile, parsedDatafile)
6164
}
65+
66+
func BenchmarkParseDatafilePasses(b *testing.B) {
67+
for n := 0; n < b.N; n++ {
68+
datafile, err := ioutil.ReadFile("test/100_entities.json")
69+
if err != nil {
70+
log.Fatal(err)
71+
}
72+
73+
datafileStruct := &entities.Datafile{}
74+
75+
json.Unmarshal(datafile, &datafileStruct)
76+
77+
}
78+
79+
}

0 commit comments

Comments
 (0)