Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize Error Pages - Reduce content size #361

Open
ferristocrat opened this issue Sep 11, 2023 · 11 comments
Open

Optimize Error Pages - Reduce content size #361

ferristocrat opened this issue Sep 11, 2023 · 11 comments

Comments

@ferristocrat
Copy link
Contributor

ferristocrat commented Sep 11, 2023

Summary

  • Our error pages are really large so even though we are implementing rate limiting when we serve the error page (such as 429s) we are still suffering from too much load
  • We're serving 16gbps of error pages

Acceptance Criteria

  • Identify and implement optimizations to error pages to reduce the size

Possible Solutions

  • Stripping away unnecessary bootstrap (use only what we need if we are just using the entirety of bootstrap)
  • Serve bootstrap (and any other large files) from CDN
  • Don't use bootstrap
  • Get rid of background image
@ferristocrat ferristocrat changed the title Optimize Error Pages Optimize Error Pages - Reduce content size Sep 11, 2023
@storj-gerrit
Copy link

storj-gerrit bot commented Sep 11, 2023

Change pkg/linksharing/sharing: optimize 429 responses mentions this issue.

@storj-gerrit
Copy link

storj-gerrit bot commented Sep 11, 2023

Change pkg/linksharing/web: serve bootstrap from CDN mentions this issue.

@halkyon
Copy link
Contributor

halkyon commented Sep 11, 2023

Should we keep this open for a few more improvements? The static background could be another thing to optimize.

@amwolff, did you intend for it to close after that change?

storjBuildBot pushed a commit that referenced this issue Sep 11, 2023
Updates #361

Change-Id: I1e1bc22f2773fcbe516b77c55836991811b23540
@egonelbre
Copy link
Member

egonelbre commented Sep 12, 2023

Are we missing caching headers for the content? I don't see a reason why they should be such a big impact.

Also, are we missing compression for the assets?

@egonelbre egonelbre reopened this Sep 12, 2023
@halkyon
Copy link
Contributor

halkyon commented Sep 12, 2023

Few other points mentioned in a Slack thread:

  • Make sure cache headers are correct (this will probably solve a lot of the issue)
  • Compress assets?
  • Strip down bootstrap to only whatever it is we use.
  • remove the need for leaflet.js and css (is it used, can it be replaced for the map?)
  • Map loading is not async
  • collapse.svg / expand.svg are served, but these could be replaced by symbols in the font

See the PageSpeed report here: https://pagespeed.web.dev/analysis/https-link-storjshare-io-s-jwur4oa5atf5ireddlrxtk4g7yqq-uptime-checks-hello-world-txt/kny8inzxcm?form_factor=mobile

Generally it might be good to check out the network tab in the browser and see if we can spot anything else that looks like a big download or not optimal.

@storj-gerrit
Copy link

storj-gerrit bot commented Sep 13, 2023

Change pkg/linksharing: enable caching for static files mentions this issue.

@halkyon
Copy link
Contributor

halkyon commented Sep 13, 2023

I found https://github.com/vearutop/statigz that looked good, but it didn't have cache busting features.

Egon had a great idea (thanks!), that looks something like this:

type StaticCache struct {
	prefix string // if needed
	data fs.FS
	mu   sync.Mutex
	comp map[string]Entry
}

type Entry struct {
	Path        string
	Etag        string
	ContentType string

	Data []byte
	Gzip []byte
}

func (cache *StaticCache) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Allow", http.MethodGet + "," + http.MethodHead)
	if r.Method != http.MethodGet || r.Method != http.MethodHead {
		http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
		return
	}

	entry, ok := cache.Entry(r.URL.Path)
	if !ok {
		http.Error(...)
		return
	}

	w.Header().Add("Content-Type", entry.ContentType)
	w.Header().Add("Etag", entry.Etag)
	// add caching header

	data := entry.Data
	if acceptsGzip(r) && len(entry.Gzip) > 0 {
		w.Header().Add("Content-Encoding", "gzip")
		data = entry.Gzip
	}

	if r.Method == http.MethodHead {
		return
	}

	w.Write(data)
}

func (cache *StaticCache) Link(urlpath string) template.HTML {
	// return canonicallink + "?etag" + etag
}

func (cache *StaticCache) Entry(urlpath string) (Entry, bool) {
	target := path.Clean(urlpath)

	cache.mu.Lock()
	entry, ok := cache.comp[target]
	cache.mu.Unlock()

	if !ok {
		entry, ok = cache.load(target)
		if !ok {
			return Entry{}, false
		}

		cache.mu.Lock()
		cache.comp[target] = entry
		cache.mu.Unlock()
	}

	return entry, true
}

func (cache *StaticCache) load(target string) (Entry, bool) {
	// load data
	// compute some hash for etag
	// compress gzip
	// determine content type based on ext
}

func acceptsGzip(r *http.Request) bool {
	// todo:
}

storjBuildBot pushed a commit that referenced this issue Sep 14, 2023
This change turns on Cache-Control header for static file responses
with a very long age.

It also appends a version hash to static file requests from the HTML
so caches are refreshed on new releases.

Updates #361

Change-Id: Id748fd636e0e24654c4e5ec703bcbc02ccaa70c1
@ferristocrat
Copy link
Contributor Author

@boshevski - let's take a look at the Linksharing UI and discuss if it needs a refresh to make it more consistent with the Satellite UI.

@boshevski
Copy link
Member

@ferristocrat I made a pr that optimizes the logo and the background image 3x. I'm working on updating the ui designs next

@egonelbre
Copy link
Member

AFAIK, #361 (comment) has not yet been implemented or will that be handled in a separate issue?

@halkyon halkyon reopened this Oct 12, 2023
@halkyon
Copy link
Contributor

halkyon commented Oct 12, 2023

yes, this isn't complete. I reopened it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants