tendermint / go-amino

Protobuf3 with Interface support - Designed for blockchains (deterministic, upgradeable, fast, and compact)
Other
260 stars 84 forks source link

Binary hooks and HowTo to optimize hot-paths for binary/json encoding #301

Open jaekwon opened 4 years ago

jaekwon commented 4 years ago

The easiest way to override amino binary encoding for speed is prob to mirror these json hooks:

// Handle override if a pointer to rv implements json.Unmarshaler.
        if rv.Addr().Type().Implements(jsonUnmarshalerType) {
                err = rv.Addr().Interface().(json.Unmarshaler).UnmarshalJSON(bz)
                return
        }

and

        // Handle override if rv implements json.Marshaler.
        if rv.CanAddr() { // Try pointer first.
                if rv.Addr().Type().Implements(jsonMarshalerType) {
                        err = invokeMarshalJSON(w, rv.Addr())
                        return
                } 
        } else if rv.Type().Implements(jsonMarshalerType) {
                err = invokeMarshalJSON(w, rv)
                return
        }

The binary and json were intentionally written to mirror the code structure, so this kind of translation is easy.

To help keep the convention, please ping me for reviews... there's definitely a lot of value in the way that amino was coded, IMO, so I'd like to preserve that as we keep it as a canonical implementation for go-reflection based proto3 (subset), if anything.

jaekwon commented 4 years ago

Also, it may help to also include thin (non-reflection-based, but o.(interface) direct Go based) optimization in the top-level amino.go files. But we should only add lines of code here for proven needs, such that the code itself can act as a standard.