relvacode / storm

A Modern Deluge Interface
MIT License
135 stars 11 forks source link

Performance improvement suggestions #57

Open malwinmp opened 10 months ago

malwinmp commented 10 months ago

Hi, I observed that some json responses can get really huge really fast. Dealing with deluge instance containing lots of items generates in my case 2MB json response sending to client every 2 secs. While it's not a big deal when using server-client locally it can be serious performance issue.

What do you think about implementing some performance improvements like:

1) instead of dealin with plain json data, compress response servers-side and uncompress client-side. Those data is highly compressible. 2) do some basic filtering server-side - for example when use filter only for Active or Downloading or Paused items return only items matching those criteria instead of sending whole list 3) reduce response size by removing unused parameters like, "Peers" / "Files" / "FileProgress" / "FilePriorities" and many more that are not used for data presentation.

Edit: point 2 removed it already works that way (filtered by deluge daemon)

malwinmp commented 10 months ago

Never programmed in go language but this change in http.go Send function seems to work.

Before transferred : 2.03MB After transferred : 172KB

package storm

import (
    "compress/gzip"
    "encoding/json"
    "net/http"
)

// HandlerFunc is an adaptor for the http.HandlerFunc that returns JSON data.
type HandlerFunc func(r *http.Request) (interface{}, error)

// Send sends JSON data to the client using the supplied HTTP status code.
func Send(rw http.ResponseWriter, code int, data interface{}) {
    enc := json.NewEncoder(rw)
    enc.SetIndent("", "  ")

    rw.Header().Set("Content-Type", "application/json")
    rw.Header().Set("Content-Encoding", "gzip")
    rw.WriteHeader(code)

    body, err := json.Marshal(data)
    if err != nil {
        return
    }
    writer, err := gzip.NewWriterLevel(rw, gzip.BestCompression)
    if err != nil {
        return
    }
    defer writer.Close()
    writer.Write(body)
}

// NoContent sends a 204 No Content response
func NoContent(rw http.ResponseWriter) {
    rw.WriteHeader(http.StatusNoContent)
}

func Handle(rw http.ResponseWriter, r *http.Request, handler HandlerFunc) error {
    response, err := handler(r)
    if err != nil {
        SendError(rw, err)
        return err
    }

    if response == nil {
        NoContent(rw)
        return nil
    }

    Send(rw, http.StatusOK, response)
    return nil
}