소스 검색

Performance improvements.

BenchmarkResponseWriter     1239          1304          +5.25%
BenchmarkFullSSE            1469          915           -37.71%
BenchmarkNoRetrySSE         1187          785           -33.87%
BenchmarkSimpleSSE          961           687           -28.51%

benchmark                   old allocs     new allocs     delta
BenchmarkResponseWriter     9              9              +0.00%
BenchmarkFullSSE            12             3              -75.00%
BenchmarkNoRetrySSE         11             2              -81.82%
BenchmarkSimpleSSE          8              2              -75.00%

benchmark                   old bytes     new bytes     delta
BenchmarkResponseWriter     442           442           +0.00%
BenchmarkFullSSE            462           320           -30.74%
BenchmarkNoRetrySSE         473           337           -28.75%
BenchmarkSimpleSSE          426           314           -26.29%
Manu Mtz-Almeida 10 년 전
부모
커밋
404710eaa4
2개의 변경된 파일51개의 추가작업 그리고 20개의 파일을 삭제
  1. 27 20
      sse-encoder.go
  2. 24 0
      writer.go

+ 27 - 20
sse-encoder.go

@@ -10,6 +10,7 @@ import (
 	"io"
 	"io"
 	"net/http"
 	"net/http"
 	"reflect"
 	"reflect"
+	"strconv"
 	"strings"
 	"strings"
 )
 )
 
 
@@ -19,6 +20,9 @@ import (
 
 
 const ContentType = "text/event-stream"
 const ContentType = "text/event-stream"
 
 
+var contentType = []string{ContentType}
+var noCache = []string{"no-cache"}
+
 type Event struct {
 type Event struct {
 	Event string
 	Event string
 	Id    string
 	Id    string
@@ -26,63 +30,66 @@ type Event struct {
 	Data  interface{}
 	Data  interface{}
 }
 }
 
 
-func Encode(w io.Writer, event Event) error {
+func Encode(writer io.Writer, event Event) error {
+	w := checkWriter(writer)
 	writeId(w, event.Id)
 	writeId(w, event.Id)
 	writeEvent(w, event.Event)
 	writeEvent(w, event.Event)
 	writeRetry(w, event.Retry)
 	writeRetry(w, event.Retry)
 	return writeData(w, event.Data)
 	return writeData(w, event.Data)
 }
 }
 
 
-func writeId(w io.Writer, id string) {
+func writeId(w stringWriter, id string) {
 	if len(id) > 0 {
 	if len(id) > 0 {
-		w.Write([]byte("id: "))
-		w.Write([]byte(escape(id)))
-		w.Write([]byte("\n"))
+		w.WriteString("id: ")
+		w.WriteString(escape(id))
+		w.WriteString("\n")
 	}
 	}
 }
 }
 
 
-func writeEvent(w io.Writer, event string) {
+func writeEvent(w stringWriter, event string) {
 	if len(event) > 0 {
 	if len(event) > 0 {
-		w.Write([]byte("event: "))
-		w.Write([]byte(escape(event)))
-		w.Write([]byte("\n"))
+		w.WriteString("event: ")
+		w.WriteString(escape(event))
+		w.WriteString("\n")
 	}
 	}
 }
 }
 
 
-func writeRetry(w io.Writer, retry uint) {
+func writeRetry(w stringWriter, retry uint) {
 	if retry > 0 {
 	if retry > 0 {
-		fmt.Fprintf(w, "retry: %d\n", retry)
+		w.WriteString("retry: ")
+		w.WriteString(strconv.FormatUint(uint64(retry), 10))
+		w.WriteString("\n")
 	}
 	}
 }
 }
 
 
-func writeData(w io.Writer, data interface{}) error {
-	w.Write([]byte("data: "))
-	switch typeOfData(data) {
+func writeData(w stringWriter, data interface{}) error {
+	w.WriteString("data: ")
+	switch kindOfData(data) {
 	case reflect.Struct, reflect.Slice, reflect.Map:
 	case reflect.Struct, reflect.Slice, reflect.Map:
 		err := json.NewEncoder(w).Encode(data)
 		err := json.NewEncoder(w).Encode(data)
 		if err != nil {
 		if err != nil {
 			return err
 			return err
 		}
 		}
-		w.Write([]byte("\n"))
+		w.WriteString("\n")
 	default:
 	default:
 		text := fmt.Sprint(data)
 		text := fmt.Sprint(data)
-		w.Write([]byte(escape(text)))
-		w.Write([]byte("\n\n"))
+		w.WriteString(escape(text))
+		w.WriteString("\n\n")
 	}
 	}
 	return nil
 	return nil
 }
 }
 
 
 func (r Event) Write(w http.ResponseWriter) error {
 func (r Event) Write(w http.ResponseWriter) error {
 	header := w.Header()
 	header := w.Header()
-	header.Set("Content-Type", ContentType)
+	header["Content-Type"] = contentType
 
 
 	if _, exist := header["Cache-Control"]; !exist {
 	if _, exist := header["Cache-Control"]; !exist {
-		header.Set("Cache-Control", "no-cache")
+		header["Cache-Control"] = noCache
 	}
 	}
 	return Encode(w, r)
 	return Encode(w, r)
 }
 }
 
 
-func typeOfData(data interface{}) reflect.Kind {
+func kindOfData(data interface{}) reflect.Kind {
 	value := reflect.ValueOf(data)
 	value := reflect.ValueOf(data)
 	valueType := value.Kind()
 	valueType := value.Kind()
 	if valueType == reflect.Ptr {
 	if valueType == reflect.Ptr {

+ 24 - 0
writer.go

@@ -0,0 +1,24 @@
+package sse
+
+import "io"
+
+type stringWriter interface {
+	io.Writer
+	WriteString(string) (int, error)
+}
+
+type stringWrapper struct {
+	io.Writer
+}
+
+func (w stringWrapper) WriteString(str string) (int, error) {
+	return w.Writer.Write([]byte(str))
+}
+
+func checkWriter(writer io.Writer) stringWriter {
+	if w, ok := writer.(stringWriter); ok {
+		return w
+	} else {
+		return stringWrapper{writer}
+	}
+}