improve (performance): increase performance as per the benchmark observation

This commit is contained in:
Mickael KERJEAN 2019-02-19 02:34:33 +11:00
parent 7f820b8cd4
commit 36f937da80
8 changed files with 69 additions and 57 deletions

View file

@ -8,6 +8,7 @@ import (
"crypto/rand"
"crypto/sha256"
"encoding/base64"
"hash/fnv"
"io"
"io/ioutil"
mathrand "math/rand"
@ -62,6 +63,24 @@ func Hash(str string, n int) string {
return h
}
func QuickHash(str string, n int) string {
hash := fnv.New32()
hash.Write([]byte(str))
d := string(hash.Sum(nil))
h := ""
for i:=0; i<len(d); i++ {
if n > 0 && len(h) >= n {
break
}
h += ReversedBaseChange(Letters, int(d[i]))
}
if len(h) > n {
return h[0:len(h) - 1]
}
return h
}
func ReversedBaseChange(alphabet []rune, i int) string {
str := ""
for {

View file

@ -6,7 +6,12 @@ import (
"strings"
)
var MOCK_CURRENT_DIR string
func GetCurrentDir() string {
if MOCK_CURRENT_DIR != "" {
return MOCK_CURRENT_DIR
}
ex, _ := os.Executable()
return filepath.Dir(ex)
}

View file

@ -33,6 +33,17 @@ func SendSuccessResult(res http.ResponseWriter, data interface{}) {
encoder.Encode(APISuccessResult{"ok", data})
}
func SendSuccessResultWithEtag(res http.ResponseWriter, req *http.Request, data interface{}) {
json, _ := json.Marshal(APISuccessResult{"ok", data})
hash := QuickHash(string(json), 20)
if req.Header.Get("If-None-Match") == hash {
res.WriteHeader(http.StatusNotModified)
return
}
res.Header().Set("Etag", hash)
res.Write(json)
}
func SendSuccessResults(res http.ResponseWriter, data interface{}) {
encoder := json.NewEncoder(res)
encoder.SetEscapeHTML(false)

View file

@ -76,21 +76,12 @@ func AdminSessionAuthenticate(ctx App, res http.ResponseWriter, req *http.Reques
SendSuccessResult(res, true)
}
func AdminBackend(ctx App, res http.ResponseWriter, req *http.Request) {
backends := make(map[string]Form)
drivers := Backend.Drivers()
backends := make(map[string]Form, len(drivers))
for key := range drivers {
backends[key] = drivers[key].LoginForm()
}
if c, err := json.Marshal(backends); err == nil {
hash := Hash(string(c), 20)
if req.Header.Get("If-None-Match") == hash {
res.WriteHeader(http.StatusNotModified)
SendSuccessResultWithEtag(res, req, backends)
return
}
res.Header().Set("Etag", hash)
}
SendSuccessResult(res, backends)
}

View file

@ -1,7 +1,6 @@
package ctrl
import (
"encoding/json"
. "github.com/mickael-kerjean/filestash/server/common"
"io"
"io/ioutil"
@ -14,10 +13,11 @@ import (
var (
logpath = filepath.Join(GetCurrentDir(), LOG_PATH, "access.log")
cachepath = filepath.Join(GetCurrentDir(), CONFIG_PATH, "config.json")
pluginpath = filepath.Join(GetCurrentDir(), PLUGIN_PATH)
)
func FetchPluginsHandler(ctx App, res http.ResponseWriter, req *http.Request) {
f, err := os.OpenFile(filepath.Join(GetCurrentDir(), PLUGIN_PATH), os.O_RDONLY, os.ModePerm)
f, err := os.OpenFile(pluginpath, os.O_RDONLY, os.ModePerm)
if err != nil {
SendErrorResult(res, err)
return
@ -90,14 +90,5 @@ func PrivateConfigUpdateHandler(ctx App, res http.ResponseWriter, req *http.Requ
func PublicConfigHandler(ctx App, res http.ResponseWriter, req *http.Request) {
cfg := Config.Export()
if c, err := json.Marshal(cfg); err == nil {
hash := Hash(string(c), 20)
if req.Header.Get("If-None-Match") == hash {
res.WriteHeader(http.StatusNotModified)
return
}
res.Header().Set("Etag", hash)
}
SendSuccessResult(res, cfg)
SendSuccessResultWithEtag(res, req, cfg)
}

View file

@ -1,7 +1,7 @@
package ctrl
import (
"encoding/json"
"fmt"
. "github.com/mickael-kerjean/filestash/server/common"
"github.com/mickael-kerjean/filestash/server/model"
"io"
@ -19,13 +19,12 @@ type FileInfo struct {
}
func FileLs(ctx App, res http.ResponseWriter, req *http.Request) {
var files []FileInfo = make([]FileInfo, 0)
if model.CanRead(&ctx) == false {
if model.CanUpload(&ctx) == false {
SendErrorResult(res, NewError("Permission denied", 403))
return
}
SendSuccessResults(res, files)
SendSuccessResults(res, make([]FileInfo, 0))
return
}
path, err := pathBuilder(ctx, req.URL.Query().Get("path"))
@ -40,21 +39,23 @@ func FileLs(ctx App, res http.ResponseWriter, req *http.Request) {
return
}
for _, entry := range entries {
f := FileInfo{
Name: entry.Name(),
Size: entry.Size(),
files := make([]FileInfo, len(entries))
etag := fmt.Sprintf("%d", len(entries)) + path
for i:=0; i<len(entries); i++ {
etag += files[i].Name
files[i] = FileInfo{
Name: entries[i].Name(),
Size: entries[i].Size(),
Time: func(t time.Time) int64 {
return t.UnixNano() / int64(time.Millisecond)
}(entry.ModTime()),
}(entries[i].ModTime()),
Type: func(isDir bool) string {
if isDir == true {
return "directory"
}
return "file"
}(entry.IsDir()),
}(entries[i].IsDir()),
}
files = append(files, f)
}
var perms Metadata = Metadata{}
@ -79,22 +80,12 @@ func FileLs(ctx App, res http.ResponseWriter, req *http.Request) {
perms.CanShare = NewBool(false)
}
etag := func() string {
tmp := struct {
Tmp0 interface{}
Tmp1 interface{}
}{ files, perms }
if j, err := json.Marshal(tmp); err == nil {
return Hash(string(j), 20)
}
return ""
}()
etag = QuickHash(etag, 20)
res.Header().Set("Etag", etag)
if etag != "" && req.Header.Get("If-None-Match") == etag {
res.WriteHeader(http.StatusNotModified)
return
}
res.Header().Set("Etag", etag)
SendSuccessResultsWithMetadata(res, files, perms)
}

View file

@ -1,9 +1,8 @@
package ctrl
import (
"crypto/md5"
"encoding/base32"
. "github.com/mickael-kerjean/filestash/server/common"
"fmt"
"io"
"text/template"
"net/http"
@ -16,8 +15,8 @@ var ETAGS SafeMapStringString = NewSafeMapStringString()
func StaticHandler(_path string) func(App, http.ResponseWriter, *http.Request) {
return func(ctx App, res http.ResponseWriter, req *http.Request) {
var base string = GetAbsolutePath(_path)
var srcPath string
base := GetAbsolutePath(_path)
if srcPath = JoinPath(base, req.URL.Path); srcPath == base {
http.NotFound(res, req)
return
@ -93,11 +92,12 @@ func hashFile (path string, n int) string {
return ""
}
defer f.Close()
h := md5.New()
if _, err := io.Copy(h, f); err != nil {
return ""
stat, err := f.Stat()
if err != nil {
return "UNKNOWN"
}
return base32.HexEncoding.EncodeToString(h.Sum(nil))[:n]
return QuickHash(fmt.Sprintf("%s %d %d %s", path, stat.Size(), stat.Mode(), stat.ModTime()), n)
}
func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) {
@ -128,6 +128,7 @@ func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) {
head.Set("Etag", etagGzip)
}
io.Copy(res, file)
file.Close()
return
}
}
@ -145,4 +146,5 @@ func ServeFile(res http.ResponseWriter, req *http.Request, filePath string) {
head.Set("Etag", etagNormal)
}
io.Copy(res, file)
file.Close()
}

View file

@ -20,7 +20,9 @@ func NewMiddlewareChain(fn func(App, http.ResponseWriter, *http.Request), m []Mi
f = m[i](f)
}
f(app, &resw, req)
if req.Body != nil {
req.Body.Close()
}
go Logger(app, &resw, req)
}
}