all: Store assets as strings (#6611)
Storing assets as []byte requires every compiled-in asset to be copied into writable memory at program startup. That currently takes up 1.6MB per syncthing process. Strings stay in the RODATA section and should be shared between processes running the same binary.
This commit is contained in:
@@ -7,14 +7,14 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -27,7 +27,7 @@ const themePrefix = "theme-assets/"
|
||||
|
||||
type staticsServer struct {
|
||||
assetDir string
|
||||
assets map[string][]byte
|
||||
assets map[string]string
|
||||
availableThemes []string
|
||||
|
||||
mut sync.RWMutex
|
||||
@@ -168,16 +168,15 @@ func (s *staticsServer) serveAsset(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
w.Header().Set("Content-Length", strconv.Itoa(len(bs)))
|
||||
io.WriteString(w, bs)
|
||||
} else {
|
||||
// ungzip if browser not send gzip accepted header
|
||||
var gr *gzip.Reader
|
||||
gr, _ = gzip.NewReader(bytes.NewReader(bs))
|
||||
bs, _ = ioutil.ReadAll(gr)
|
||||
gr, _ = gzip.NewReader(strings.NewReader(bs))
|
||||
io.Copy(w, gr)
|
||||
gr.Close()
|
||||
}
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(bs)))
|
||||
|
||||
w.Write(bs)
|
||||
}
|
||||
|
||||
func (s *staticsServer) serveThemes(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
+3
-3
@@ -152,19 +152,19 @@ func TestAssetsDir(t *testing.T) {
|
||||
gw := gzip.NewWriter(buf)
|
||||
gw.Write([]byte("default"))
|
||||
gw.Close()
|
||||
def := buf.Bytes()
|
||||
def := buf.String()
|
||||
|
||||
buf = new(bytes.Buffer)
|
||||
gw = gzip.NewWriter(buf)
|
||||
gw.Write([]byte("foo"))
|
||||
gw.Close()
|
||||
foo := buf.Bytes()
|
||||
foo := buf.String()
|
||||
|
||||
e := &staticsServer{
|
||||
theme: "foo",
|
||||
mut: sync.NewRWMutex(),
|
||||
assetDir: "testdata",
|
||||
assets: map[string][]byte{
|
||||
assets: map[string]string{
|
||||
"foo/a": foo, // overridden in foo/a
|
||||
"foo/b": foo,
|
||||
"default/a": def, // overridden in default/a (but foo/a takes precedence)
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/auto"
|
||||
@@ -23,10 +24,10 @@ func TestAssets(t *testing.T) {
|
||||
}
|
||||
|
||||
var gr *gzip.Reader
|
||||
gr, _ = gzip.NewReader(bytes.NewReader(idx))
|
||||
idx, _ = ioutil.ReadAll(gr)
|
||||
gr, _ = gzip.NewReader(strings.NewReader(idx))
|
||||
html, _ := ioutil.ReadAll(gr)
|
||||
|
||||
if !bytes.Contains(idx, []byte("<html")) {
|
||||
if !bytes.Contains(html, []byte("<html")) {
|
||||
t.Fatal("No html in index.html")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user