Skip to content

Commit

Permalink
Improve unmarshal performance (#149)
Browse files Browse the repository at this point in the history
  • Loading branch information
at-wat authored Feb 17, 2021
1 parent f769d2b commit d967435
Show file tree
Hide file tree
Showing 6 changed files with 116 additions and 59 deletions.
19 changes: 11 additions & 8 deletions block.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,21 @@ func UnmarshalBlock(r io.Reader, n int64) (*Block, error) {
var b Block
var err error
var nRead int
if b.TrackNumber, nRead, err = readVUInt(r); err != nil {

vd := &valueDecoder{}

if b.TrackNumber, nRead, err = vd.readVUInt(r); err != nil {
return nil, err
}
n -= int64(nRead)
if v, err := readInt(r, 2); err == nil {
if v, err := vd.readInt(r, 2); err == nil {
b.Timecode = int16(v.(int64))
} else {
return nil, err
}
n -= 2

var bs [1]byte
switch _, err := io.ReadFull(r, bs[:]); err {
switch _, err := r.Read(vd.bs[:]); err {
case nil:
case io.EOF:
return nil, io.ErrUnexpectedEOF
Expand All @@ -92,16 +94,17 @@ func UnmarshalBlock(r io.Reader, n int64) (*Block, error) {
return nil, io.ErrUnexpectedEOF
}

if bs[0]&blockFlagMaskKeyframe != 0 {
f := vd.bs[0]
if f&blockFlagMaskKeyframe != 0 {
b.Keyframe = true
}
if bs[0]&blockFlagMaskInvisible != 0 {
if f&blockFlagMaskInvisible != 0 {
b.Invisible = true
}
if bs[0]&blockFlagMaskDiscardable != 0 {
if f&blockFlagMaskDiscardable != 0 {
b.Discardable = true
}
b.Lacing = LacingMode((bs[0] & blockFlagMaskLacing) >> 1)
b.Lacing = LacingMode((f & blockFlagMaskLacing) >> 1)

var ul Unlacer
switch b.Lacing {
Expand Down
3 changes: 2 additions & 1 deletion elementtable.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,8 +272,9 @@ func init() {
}

func initReverseLookupTable(revTb elementRevTable, tb elementTable) {
vd := &valueDecoder{}
for k, v := range tb {
e, _, err := readVUInt(bytes.NewBuffer(v.b))
e, _, err := vd.readVUInt(bytes.NewBuffer(v.b))
if err != nil {
panic(err)
}
Expand Down
15 changes: 8 additions & 7 deletions unlacer.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func NewNoUnlacer(r io.Reader, n int64) (Unlacer, error) {
func NewXiphUnlacer(r io.Reader, n int64) (Unlacer, error) {
var nFrame int
var b [1]byte
switch _, err := io.ReadFull(r, b[:]); err {
switch _, err := r.Read(b[:]); err {
case nil:
nFrame = int(b[0]) + 1
case io.EOF:
Expand All @@ -70,8 +70,7 @@ func NewXiphUnlacer(r io.Reader, n int64) (Unlacer, error) {
}
for i := 0; i < nFrame-1; i++ {
for {
var b [1]byte
switch _, err := io.ReadFull(ul.r, b[:]); err {
switch _, err := ul.r.Read(b[:]); err {
case nil:
case io.EOF:
return nil, io.ErrUnexpectedEOF
Expand All @@ -98,7 +97,7 @@ func NewXiphUnlacer(r io.Reader, n int64) (Unlacer, error) {
func NewFixedUnlacer(r io.Reader, n int64) (Unlacer, error) {
var nFrame int
var b [1]byte
switch _, err := io.ReadFull(r, b[:]); err {
switch _, err := r.Read(b[:]); err {
case nil:
nFrame = int(b[0]) + 1
case io.EOF:
Expand Down Expand Up @@ -127,7 +126,7 @@ func NewFixedUnlacer(r io.Reader, n int64) (Unlacer, error) {
func NewEBMLUnlacer(r io.Reader, n int64) (Unlacer, error) {
var nFrame int
var b [1]byte
switch _, err := io.ReadFull(r, b[:]); err {
switch _, err := r.Read(b[:]); err {
case nil:
nFrame = int(b[0]) + 1
case io.EOF:
Expand All @@ -137,11 +136,13 @@ func NewEBMLUnlacer(r io.Reader, n int64) (Unlacer, error) {
}
n--

vd := &valueDecoder{}

ul := &unlacer{
r: r,
size: make([]int, nFrame),
}
un64, nRead, err := readVUInt(ul.r)
un64, nRead, err := vd.readVUInt(ul.r)
if err != nil {
return nil, err
}
Expand All @@ -151,7 +152,7 @@ func NewEBMLUnlacer(r io.Reader, n int64) (Unlacer, error) {
ul.size[nFrame-1] -= int(n64)

for i := 1; i < nFrame-1; i++ {
n64Diff, nRead, err := readVInt(ul.r)
n64Diff, nRead, err := vd.readVInt(ul.r)
n64 += int64(n64Diff)
if err != nil {
return nil, err
Expand Down
14 changes: 8 additions & 6 deletions unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,11 @@ func Unmarshal(r io.Reader, val interface{}, opts ...UnmarshalOption) error {
return wrapErrorf(ErrIncompatibleType, "unmarshalling to %T", val)
}

vd := &valueDecoder{}

voe := vo.Elem()
for {
if _, err := readElement(r, SizeUnknown, voe, 0, 0, nil, options); err != nil {
if _, err := vd.readElement(r, SizeUnknown, voe, 0, 0, nil, options); err != nil {
if err == io.EOF {
return nil
}
Expand All @@ -62,7 +64,7 @@ func Unmarshal(r io.Reader, val interface{}, opts ...UnmarshalOption) error {
}
}

func readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64, parent *Element, options *UnmarshalOptions) (io.Reader, error) {
func (vd *valueDecoder) readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64, parent *Element, options *UnmarshalOptions) (io.Reader, error) {
pos0 := pos
var r rollbackReader
if options.ignoreUnknown {
Expand Down Expand Up @@ -105,7 +107,7 @@ func readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64,
r.Reset()

var headerSize uint64
e, nb, err := readVUInt(r)
e, nb, err := vd.readVUInt(r)
headerSize += uint64(nb)
if err != nil {
if nb == 0 && err == io.ErrUnexpectedEOF {
Expand All @@ -126,7 +128,7 @@ func readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64,
return nil, wrapErrorf(ErrUnknownElement, "unmarshalling element 0x%x", e)
}

size, nb, err := readDataSize(r)
size, nb, err := vd.readDataSize(r)
headerSize += uint64(nb)

if n != SizeUnknown && pos+headerSize+size > pos0+uint64(n) {
Expand Down Expand Up @@ -192,15 +194,15 @@ func readElement(r0 io.Reader, n int64, vo reflect.Value, depth int, pos uint64,
if elem != nil {
elem.Value = vn.Interface()
}
r0, err := readElement(r, int64(size), vn, depth+1, pos+headerSize, elem, options)
r0, err := vd.readElement(r, int64(size), vn, depth+1, pos+headerSize, elem, options)
if err != nil && err != io.EOF {
return r0, err
}
if r0 != nil {
r.Set(io.MultiReader(r0, r.Get()))
}
default:
val, err := perTypeReader[v.t](r, size)
val, err := vd.decode(v.t, r, size)
if err != nil {
if options.ignoreUnknown {
r.RollbackTo(1)
Expand Down
Loading

0 comments on commit d967435

Please sign in to comment.