diff --git a/pkg/cutils/byteslice.go b/pkg/cutils/byteslice.go deleted file mode 100644 index a506b3b..0000000 --- a/pkg/cutils/byteslice.go +++ /dev/null @@ -1,26 +0,0 @@ -package cutils - -import "C" - -import ( - "reflect" - "unsafe" -) - -// ByteSlice builds a byte Slice over a C pointer returned by a -// C function. -// The C pointer has to be passed as an unsafe.Pointer -// and the size of the pointed memery area has to be -// indicated through the size parameter. -// No memory allocation is done by that function. It -// just consists in mapping a Go object too a C one. -func ByteSlice(pointer unsafe.Pointer, size int) []byte { - var s []byte - - h := (*reflect.SliceHeader)((unsafe.Pointer(&s))) - h.Cap = size - h.Len = size - h.Data = uintptr(pointer) - - return s -} diff --git a/pkg/obialign/alignment.go b/pkg/obialign/alignment.go index fd9656f..0b1bc80 100644 --- a/pkg/obialign/alignment.go +++ b/pkg/obialign/alignment.go @@ -71,10 +71,10 @@ func _BuildAlignment(seqA, seqB []byte, path []int, gap byte, bufferA, bufferB * func BuildAlignment(seqA, seqB *obiseq.BioSequence, path []int, gap byte) (*obiseq.BioSequence, *obiseq.BioSequence) { - bufferSA := obiseq.GetSlice() + bufferSA := obiseq.GetSlice(seqA.Length()) defer obiseq.RecycleSlice(&bufferSA) - bufferSB := obiseq.GetSlice() + bufferSB := obiseq.GetSlice(seqB.Length()) defer obiseq.RecycleSlice(&bufferSB) _BuildAlignment(seqA.Sequence(), seqB.Sequence(), path, gap, @@ -115,12 +115,12 @@ func BuildAlignment(seqA, seqB *obiseq.BioSequence, // return. func BuildQualityConsensus(seqA, seqB *obiseq.BioSequence, path []int) (*obiseq.BioSequence, int) { - bufferSA := obiseq.GetSlice() - bufferSB := obiseq.GetSlice() + bufferSA := obiseq.GetSlice(seqA.Length()) + bufferSB := obiseq.GetSlice(seqB.Length()) defer obiseq.RecycleSlice(&bufferSB) - bufferQA := obiseq.GetSlice() - bufferQB := obiseq.GetSlice() + bufferQA := obiseq.GetSlice(seqA.Length()) + bufferQB := obiseq.GetSlice(seqB.Length()) defer obiseq.RecycleSlice(&bufferQB) _BuildAlignment(seqA.Sequence(), seqB.Sequence(), path, ' ', diff --git a/pkg/obiformats/fastseq_read.go b/pkg/obiformats/fastseq_read.go index 3f5dccb..0b3ee7c 100644 --- a/pkg/obiformats/fastseq_read.go +++ b/pkg/obiformats/fastseq_read.go @@ -13,7 +13,6 @@ import ( log "github.com/sirupsen/logrus" - "git.metabarcoding.org/lecasofts/go/obitools/pkg/cutils" "git.metabarcoding.org/lecasofts/go/obitools/pkg/obiiter" "git.metabarcoding.org/lecasofts/go/obitools/pkg/obiseq" ) @@ -31,13 +30,7 @@ func _FastseqReader(seqfile C.fast_kseq_p, s := seqfile.seq - csequence := cutils.ByteSlice(unsafe.Pointer(s.seq.s), int(s.seq.l)) - sequence := obiseq.GetSlice() - sequence = append(sequence, csequence...) - - //sequence := C.GoBytes(unsafe.Pointer(s.seq.s), - // C.int(s.seq.l)) - + sequence := C.GoBytes(unsafe.Pointer(s.seq.s), C.int(s.seq.l)) name := C.GoString(s.name.s) if s.comment.l > C.ulong(0) { @@ -49,12 +42,23 @@ func _FastseqReader(seqfile C.fast_kseq_p, rep := obiseq.NewBioSequence(name, sequence, comment) if s.qual.l > C.ulong(0) { - cquality := cutils.ByteSlice(unsafe.Pointer(s.qual.s), int(s.qual.l)) + cquality := unsafe.Slice(s.qual.s, C.int(s.qual.l)) l := int(s.qual.l) - quality := obiseq.GetSlice() + quality := obiseq.GetSlice(l) shift := uint8(seqfile.shift) + for j := 0; j < l; j++ { - quality = append(quality, uint8(cquality[j])-shift) + func() { + defer func() { + if err := recover(); err != nil { + log.Println("cquality:", cquality, + "s.qual.s:", s.qual.s, + "quality:", quality) + log.Panic("panic occurred:", err) + } + }() + quality = append(quality, uint8(cquality[j])-shift) + }() } rep.SetQualities(quality) diff --git a/pkg/obiseq/biosequence.go b/pkg/obiseq/biosequence.go index d5bafc3..8392374 100644 --- a/pkg/obiseq/biosequence.go +++ b/pkg/obiseq/biosequence.go @@ -129,9 +129,9 @@ func (s *BioSequence) Copy() *BioSequence { newSeq.id = s.id newSeq.definition = s.definition - newSeq.sequence = GetSlice(s.sequence...) - newSeq.qualities = GetSlice(s.qualities...) - newSeq.feature = GetSlice(s.feature...) + newSeq.sequence = CopySlice(s.sequence) + newSeq.qualities = CopySlice(s.qualities) + newSeq.feature = CopySlice(s.feature) if len(s.annotations) > 0 { newSeq.annotations = GetAnnotation(s.annotations) @@ -340,7 +340,6 @@ func (s *BioSequence) ClearQualities() { s.qualities = s.qualities[0:0] } - // A method that appends a byte slice to the sequence. func (s *BioSequence) Write(data []byte) (int, error) { s.sequence = append(s.sequence, data...) diff --git a/pkg/obiseq/pool.go b/pkg/obiseq/pool.go index 182086d..5db9c95 100644 --- a/pkg/obiseq/pool.go +++ b/pkg/obiseq/pool.go @@ -1,6 +1,7 @@ package obiseq import ( + "log" "sync" "git.metabarcoding.org/lecasofts/go/obitools/pkg/goutils" @@ -14,22 +15,36 @@ var _BioSequenceByteSlicePool = sync.Pool{ } func RecycleSlice(s *[]byte) { - if s != nil && *s != nil { + if s != nil && cap(*s) > 0 { *s = (*s)[:0] + if cap(*s) == 0 { + log.Panicln("trying to store a NIL slice in the pool", s == nil, *s == nil, cap(*s)) + } _BioSequenceByteSlicePool.Put(s) } } -func GetSlice(values ...byte) []byte { - s := *(_BioSequenceByteSlicePool.Get().(*[]byte)) +// It returns a slice of bytes from a pool of slices. +// +// the slice can be prefilled with the provided values +func GetSlice(capacity int) []byte { + p := _BioSequenceByteSlicePool.Get().(*[]byte) - if len(values) > 0 { - s = append(s, values...) + if p == nil || *p == nil || cap(*p) < capacity { + s := make([]byte, 0, capacity) + p = &s } + s := *p return s } +func CopySlice(src []byte) []byte { + sl := GetSlice(len(src)) + copy(sl,src) + return sl +} + var BioSequenceAnnotationPool = sync.Pool{ New: func() interface{} { bs := make(Annotation, 5)