@ -0,0 +1,110 @@ | |||||
package benchmarks | |||||
import ( | |||||
"testing" | |||||
"github.com/tendermint/go-crypto" | |||||
"github.com/tendermint/go-p2p" | |||||
"github.com/tendermint/go-wire" | |||||
proto "github.com/tendermint/tendermint/benchmarks/proto" | |||||
ctypes "github.com/tendermint/tendermint/rpc/core/types" | |||||
) | |||||
func BenchmarkEncodeStatusWire(b *testing.B) { | |||||
b.StopTimer() | |||||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||||
status := &ctypes.ResultStatus{ | |||||
NodeInfo: &p2p.NodeInfo{ | |||||
PubKey: pubKey, | |||||
Moniker: "SOMENAME", | |||||
Network: "SOMENAME", | |||||
RemoteAddr: "SOMEADDR", | |||||
ListenAddr: "SOMEADDR", | |||||
Version: "SOMEVER", | |||||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||||
}, | |||||
PubKey: pubKey, | |||||
LatestBlockHash: []byte("SOMEBYTES"), | |||||
LatestBlockHeight: 123, | |||||
LatestBlockTime: 1234, | |||||
} | |||||
b.StartTimer() | |||||
counter := 0 | |||||
for i := 0; i < b.N; i++ { | |||||
jsonBytes := wire.JSONBytes(status) | |||||
counter += len(jsonBytes) | |||||
} | |||||
} | |||||
func BenchmarkEncodeNodeInfoWire(b *testing.B) { | |||||
b.StopTimer() | |||||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||||
nodeInfo := &p2p.NodeInfo{ | |||||
PubKey: pubKey, | |||||
Moniker: "SOMENAME", | |||||
Network: "SOMENAME", | |||||
RemoteAddr: "SOMEADDR", | |||||
ListenAddr: "SOMEADDR", | |||||
Version: "SOMEVER", | |||||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||||
} | |||||
b.StartTimer() | |||||
counter := 0 | |||||
for i := 0; i < b.N; i++ { | |||||
jsonBytes := wire.JSONBytes(nodeInfo) | |||||
counter += len(jsonBytes) | |||||
} | |||||
} | |||||
func BenchmarkEncodeNodeInfoBinary(b *testing.B) { | |||||
b.StopTimer() | |||||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||||
nodeInfo := &p2p.NodeInfo{ | |||||
PubKey: pubKey, | |||||
Moniker: "SOMENAME", | |||||
Network: "SOMENAME", | |||||
RemoteAddr: "SOMEADDR", | |||||
ListenAddr: "SOMEADDR", | |||||
Version: "SOMEVER", | |||||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||||
} | |||||
b.StartTimer() | |||||
counter := 0 | |||||
for i := 0; i < b.N; i++ { | |||||
jsonBytes := wire.BinaryBytes(nodeInfo) | |||||
counter += len(jsonBytes) | |||||
} | |||||
} | |||||
func BenchmarkEncodeNodeInfoProto(b *testing.B) { | |||||
b.StopTimer() | |||||
pubKey := crypto.GenPrivKeyEd25519().PubKey().(crypto.PubKeyEd25519) | |||||
pubKey2 := &proto.PubKey{Ed25519: &proto.PubKeyEd25519{Bytes: pubKey[:]}} | |||||
nodeInfo := &proto.NodeInfo{ | |||||
PubKey: pubKey2, | |||||
Moniker: "SOMENAME", | |||||
Network: "SOMENAME", | |||||
RemoteAddr: "SOMEADDR", | |||||
ListenAddr: "SOMEADDR", | |||||
Version: "SOMEVER", | |||||
Other: []string{"SOMESTRING", "OTHERSTRING"}, | |||||
} | |||||
b.StartTimer() | |||||
counter := 0 | |||||
for i := 0; i < b.N; i++ { | |||||
bytes, err := nodeInfo.Marshal() | |||||
if err != nil { | |||||
b.Fatal(err) | |||||
return | |||||
} | |||||
//jsonBytes := wire.JSONBytes(nodeInfo) | |||||
counter += len(bytes) | |||||
} | |||||
} |
@ -0,0 +1,2 @@ | |||||
Doing some protobuf tests here. | |||||
Using gogoprotobuf. |
@ -0,0 +1,25 @@ | |||||
message ResultStatus { | |||||
optional NodeInfo nodeInfo = 1; | |||||
required PubKey pubKey = 2; | |||||
required bytes latestBlockHash = 3; | |||||
required int64 latestBlockHeight = 4; | |||||
required int64 latestBlocktime = 5; | |||||
} | |||||
message NodeInfo { | |||||
required PubKey pubKey = 1; | |||||
required string moniker = 2; | |||||
required string network = 3; | |||||
required string remoteAddr = 4; | |||||
required string listenAddr = 5; | |||||
required string version = 6; | |||||
repeated string other = 7; | |||||
} | |||||
message PubKey { | |||||
optional PubKeyEd25519 ed25519 = 1; | |||||
} | |||||
message PubKeyEd25519 { | |||||
required bytes bytes = 1; | |||||
} |
@ -0,0 +1,56 @@ | |||||
package main | |||||
import ( | |||||
"encoding/binary" | |||||
"time" | |||||
//"encoding/hex" | |||||
"fmt" | |||||
"github.com/gorilla/websocket" | |||||
. "github.com/tendermint/go-common" | |||||
"github.com/tendermint/go-wire" | |||||
"github.com/tendermint/tendermint/rpc/client" | |||||
// ctypes "github.com/tendermint/tendermint/rpc/core/types" | |||||
"github.com/tendermint/tendermint/rpc/types" | |||||
) | |||||
func main() { | |||||
ws := rpcclient.NewWSClient("ws://127.0.0.1:46657/websocket") | |||||
// ws := rpcclient.NewWSClient("ws://104.236.69.128:46657/websocket") | |||||
_, err := ws.Start() | |||||
if err != nil { | |||||
Exit(err.Error()) | |||||
} | |||||
// Read a bunch of responses | |||||
go func() { | |||||
for { | |||||
_, ok := <-ws.ResultsCh | |||||
if !ok { | |||||
break | |||||
} | |||||
//fmt.Println("Received response", string(wire.JSONBytes(res))) | |||||
} | |||||
}() | |||||
// Make a bunch of requests | |||||
buf := make([]byte, 32) | |||||
for i := 0; ; i++ { | |||||
binary.LittleEndian.PutUint64(buf, uint64(i)) | |||||
//txBytes := hex.EncodeToString(buf[:n]) | |||||
request := rpctypes.NewRPCRequest("fakeid", "broadcast_tx", Arr(buf[:8])) | |||||
reqBytes := wire.JSONBytes(request) | |||||
//fmt.Println("!!", string(reqBytes)) | |||||
fmt.Print(".") | |||||
err := ws.WriteMessage(websocket.TextMessage, reqBytes) | |||||
if err != nil { | |||||
Exit(err.Error()) | |||||
} | |||||
if i%1000 == 0 { | |||||
fmt.Println(i) | |||||
} | |||||
time.Sleep(time.Microsecond * 250) | |||||
} | |||||
ws.Stop() | |||||
} |
@ -0,0 +1,7 @@ | |||||
package proxy | |||||
import ( | |||||
"github.com/tendermint/go-logger" | |||||
) | |||||
var log = logger.New("module", "proxy") |
@ -0,0 +1,126 @@ | |||||
package rpcclient | |||||
import ( | |||||
"net/http" | |||||
"strings" | |||||
"time" | |||||
"github.com/gorilla/websocket" | |||||
. "github.com/tendermint/go-common" | |||||
"github.com/tendermint/go-wire" | |||||
ctypes "github.com/tendermint/tendermint/rpc/core/types" | |||||
"github.com/tendermint/tendermint/rpc/types" | |||||
) | |||||
const ( | |||||
wsEventsChannelCapacity = 10 | |||||
wsResultsChannelCapacity = 10 | |||||
wsWriteTimeoutSeconds = 10 | |||||
) | |||||
type WSClient struct { | |||||
QuitService | |||||
Address string | |||||
*websocket.Conn | |||||
EventsCh chan ctypes.ResultEvent // closes upon WSClient.Stop() | |||||
ResultsCh chan ctypes.Result // closes upon WSClient.Stop() | |||||
} | |||||
// create a new connection | |||||
func NewWSClient(addr string) *WSClient { | |||||
wsClient := &WSClient{ | |||||
Address: addr, | |||||
Conn: nil, | |||||
EventsCh: make(chan ctypes.ResultEvent, wsEventsChannelCapacity), | |||||
ResultsCh: make(chan ctypes.Result, wsResultsChannelCapacity), | |||||
} | |||||
wsClient.QuitService = *NewQuitService(log, "WSClient", wsClient) | |||||
return wsClient | |||||
} | |||||
func (wsc *WSClient) OnStart() error { | |||||
wsc.QuitService.OnStart() | |||||
err := wsc.dial() | |||||
if err != nil { | |||||
return err | |||||
} | |||||
go wsc.receiveEventsRoutine() | |||||
return nil | |||||
} | |||||
func (wsc *WSClient) dial() error { | |||||
// Dial | |||||
dialer := websocket.DefaultDialer | |||||
rHeader := http.Header{} | |||||
con, _, err := dialer.Dial(wsc.Address, rHeader) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
// Set the ping/pong handlers | |||||
con.SetPingHandler(func(m string) error { | |||||
// NOTE: https://github.com/gorilla/websocket/issues/97 | |||||
go con.WriteControl(websocket.PongMessage, []byte(m), time.Now().Add(time.Second*wsWriteTimeoutSeconds)) | |||||
return nil | |||||
}) | |||||
con.SetPongHandler(func(m string) error { | |||||
// NOTE: https://github.com/gorilla/websocket/issues/97 | |||||
return nil | |||||
}) | |||||
wsc.Conn = con | |||||
return nil | |||||
} | |||||
func (wsc *WSClient) OnStop() { | |||||
wsc.QuitService.OnStop() | |||||
// EventsCh and ResultsCh are closed in receiveEventsRoutine. | |||||
} | |||||
func (wsc *WSClient) receiveEventsRoutine() { | |||||
for { | |||||
_, data, err := wsc.ReadMessage() | |||||
if err != nil { | |||||
log.Info("WSClient failed to read message", "error", err, "data", string(data)) | |||||
wsc.Stop() | |||||
break | |||||
} else { | |||||
var response ctypes.Response | |||||
wire.ReadJSON(&response, data, &err) | |||||
if err != nil { | |||||
log.Info("WSClient failed to parse message", "error", err) | |||||
wsc.Stop() | |||||
break | |||||
} | |||||
if strings.HasSuffix(response.ID, "#event") { | |||||
wsc.EventsCh <- *response.Result.(*ctypes.ResultEvent) | |||||
} else { | |||||
wsc.ResultsCh <- response.Result | |||||
} | |||||
} | |||||
} | |||||
// Cleanup | |||||
close(wsc.EventsCh) | |||||
close(wsc.ResultsCh) | |||||
} | |||||
// subscribe to an event | |||||
func (wsc *WSClient) Subscribe(eventid string) error { | |||||
err := wsc.WriteJSON(rpctypes.RPCRequest{ | |||||
JSONRPC: "2.0", | |||||
ID: "", | |||||
Method: "subscribe", | |||||
Params: []interface{}{eventid}, | |||||
}) | |||||
return err | |||||
} | |||||
// unsubscribe from an event | |||||
func (wsc *WSClient) Unsubscribe(eventid string) error { | |||||
err := wsc.WriteJSON(rpctypes.RPCRequest{ | |||||
JSONRPC: "2.0", | |||||
ID: "", | |||||
Method: "unsubscribe", | |||||
Params: []interface{}{eventid}, | |||||
}) | |||||
return err | |||||
} |