minify icon indicating copy to clipboard operation
minify copied to clipboard

Replace table.go with golang's html#UnescapeString

Open jvoisin opened this issue 1 year ago • 2 comments

html#UnescapeString uses its own table, which while being a subset of the minify's one, should be more than enough.

This would remove a bit less than 150kB from minify's size in memory.

jvoisin avatar Dec 13 '24 19:12 jvoisin

I've noticed before that global maps can take a lot of space, but 150kB is quite a lot while the source code is only about 30kB (I suspect Go is inefficient for built-in maps in binaries). However we can't switch to another table because it maps to unicode values and doesn't integrate with the removal of spaces at the same time.

I found https://github.com/golang/go/issues/20095 which seems to indicate something very similar.

tdewolff avatar Jan 20 '25 19:01 tdewolff

See https://github.com/yuin/goldmark/discussions/469, relevant information copied here:

Having large literal maps excessively inflates the resulting binary, see https://www.dolthub.com/blog/2023-06-16-static-map-initialization-in-go/ for more information.

  • Putting the map's contents in an array of []struct{key, value} and initializing the map in the init() function reduces the binary size by half for that particular map. Quite an improvement! Incidentally, the compiler does something similar but poorly?
  • Exporting the map using the gob encoder results in a file about 1/10th the size! Gzipping it is to about 1/50th the size. Embedding the gob encoded and gzipped map and then initializing it in the init() function results in only the size of that gzipped file being added to the binary, which almost completely removes the excessive size of the literal map. This is at the cost of unzipping and decoding gob at runtime at the start of the program.
// generate gob file once
var literalMap map[key]val

func init() {
	w, err := os.Create("literalMap.gob")
	if err != nil {
		panic(err)
	}
	wgzip := gzip.NewWriter(w)
	if err := gob.NewEncoder(wgzip).Encode(literalMap); err != nil {
		panic(err)
	} else if err := wgzip.Close(); err != nil {
		panic(err)
	} else if err := w.Close(); err != nil {
		panic(err)
	}
}
// include gob file
var literalMap map[key]val

//go:embed literalMap.gob
var _literalMap []byte

func init() {
	if rGzip, err := gzip.NewReader(bytes.NewReader(_literalMap)); err != nil {
		panic(err)
	} else if err := gob.NewDecoder(rGzip).Decode(&literalMap); err != nil {
		panic(err)
	} else if err := rGzip.Close(); err != nil {
		panic(err)
	}
}

tdewolff avatar Feb 24 '25 20:02 tdewolff