Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

As a server Shortcuts/Optimisations? #627

Open
@freman

Description

@freman

Hi

I'm trying to write a caching proxy server that we can use to cache locally various repos from github (and other places) that we use heavily but I'm running into a performance issue

I'm more than happy to concede that we won't beat github for speed but I'm finding this to be a great deal slower.

This is a greatly simplified version of what I'm running in the main codebase

package main

import (
	"compress/gzip"
	"io"
	"net/http"
	"os"
	"path"
	"strings"

	"gopkg.in/src-d/go-git.v4/plumbing/protocol/packp"
	"gopkg.in/src-d/go-git.v4/plumbing/transport"
	"gopkg.in/src-d/go-git.v4/plumbing/transport/server"
)

func main() {
	wd, _ := os.Getwd()
	http.ListenAndServe(":8822", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Cache-Control", "no-cache")

		s := strings.SplitN(strings.TrimLeft(r.URL.Path, "/"), "/", 2)
		ep, _ := transport.NewEndpoint(path.Join("file://", wd, s[0]))
		ups, _ := server.DefaultServer.NewUploadPackSession(ep, nil)
		if strings.Contains(r.URL.Path, "info") {
			advs, _ := ups.AdvertisedReferences()
			advs.Prefix = [][]byte{
				[]byte("# service=git-upload-pack"),
				[]byte(""),
			}
			w.Header().Set("Content-Type", "application/x-git-upload-pack-advertisement")
			advs.Encode(w)
			return
		}
		defer r.Body.Close()
		var rdr io.ReadCloser = r.Body

		if r.Header.Get("Content-Encoding") == "gzip" {
			rdr, _ = gzip.NewReader(r.Body)
		}

		upakreq := packp.NewUploadPackRequest()
		upakreq.Decode(rdr)

		up, _ := ups.UploadPack(r.Context(), upakreq)
		w.Header().Set("Content-Type", "application/x-git-upload-pack-result")
		up.Encode(w)
	}))
}

if you clone the aws/aws-sdk-go repo git clone --quiet --mirror https://github.com/aws/aws-sdk-go aws-sdk-go into the same directory as you put this go file

Then go run main.go you can do the following tests

$ time git clone --quiet https://github.com/aws/aws-sdk-go

real	0m23.816s
user	0m4.047s
sys	0m1.289s
$ time git clone --quiet http://localhost:8822/aws-sdk-go

real	2m18.718s
user	0m3.793s
sys	0m1.165s

The time cost here is entirely in cloning from scratch, pulling seems plenty fast.

I did profile my code and I found it spent most of it's time in encoder.go
image

Can anyone think of any way to shortcut this process for a clone if not optimise the code?

If instead of using git clone --mirror to create the aws-sdk-dir and I use go-git to clone it I even get pre-packed files

./objects/pack/pack-41174c775d8b7f517d5db3c20d52b0e5379fe9de.idx
./objects/pack/pack-41174c775d8b7f517d5db3c20d52b0e5379fe9de.pack

Perhaps for a fresh clone I can just ship that?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions