Skip to content

Commit 39bca17

Browse files
committed
osmpbf: reuse memory if filter is false
1 parent b4ef53e commit 39bca17

File tree

3 files changed

+201
-92
lines changed

3 files changed

+201
-92
lines changed

osmpbf/decode_data.go

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,9 @@ func (dec *dataDecoder) scanPrimitiveBlock(data []byte) error {
147147
func (dec *dataDecoder) scanPrimitiveGroup(data []byte) error {
148148
msg := protoscan.New(data)
149149

150+
way := &osm.Way{Visible: true}
151+
relation := &osm.Relation{Visible: true}
152+
150153
for msg.Next() {
151154
fn := msg.FieldNumber()
152155
if fn == 1 {
@@ -173,11 +176,20 @@ func (dec *dataDecoder) scanPrimitiveGroup(data []byte) error {
173176
return err
174177
}
175178

176-
err = dec.scanWays(data)
179+
way, err = dec.scanWays(data, way)
177180
if err != nil {
178181
return err
179182
}
180183

184+
if dec.scanner.FilterWay == nil || dec.scanner.FilterWay(way) {
185+
dec.q = append(dec.q, way)
186+
way = &osm.Way{Visible: true}
187+
} else {
188+
tags := way.Tags
189+
nodes := way.Nodes
190+
*way = osm.Way{Visible: true, Nodes: nodes[:0], Tags: tags[:0]}
191+
}
192+
181193
continue
182194
}
183195

@@ -187,11 +199,20 @@ func (dec *dataDecoder) scanPrimitiveGroup(data []byte) error {
187199
return err
188200
}
189201

190-
err = dec.scanRelations(data)
202+
relation, err = dec.scanRelations(data, relation)
191203
if err != nil {
192204
return err
193205
}
194206

207+
if dec.scanner.FilterRelation == nil || dec.scanner.FilterRelation(relation) {
208+
dec.q = append(dec.q, relation)
209+
relation = &osm.Relation{Visible: true}
210+
} else {
211+
tags := relation.Tags
212+
members := relation.Members
213+
*relation = osm.Relation{Visible: true, Members: members[:0], Tags: tags[:0]}
214+
}
215+
195216
continue
196217
}
197218

@@ -465,28 +486,21 @@ func (dec *dataDecoder) extractDenseNodes() error {
465486
n.Tags = append(n.Tags, osm.Tag{Key: st[k], Value: st[v]})
466487
}
467488
}
468-
if dec.scanner.NodeFilter == nil || dec.scanner.NodeFilter(*n) {
489+
490+
if dec.scanner.FilterNode == nil || dec.scanner.FilterNode(n) {
491+
dec.q = append(dec.q, n)
492+
n = &osm.Node{Visible: true}
493+
} else {
469494
// skip unwanted nodes
470-
index++
471-
}
472-
}
473-
if len(nodes) != index {
474-
/* copy to an array just large enough */
475-
tmp := make([]osm.Node, index)
476-
copy(tmp, nodes)
477-
for i := range tmp {
478-
dec.q = append(dec.q, &tmp[i])
479-
}
480-
} else {
481-
for i := range nodes {
482-
dec.q = append(dec.q, &nodes[i])
495+
tags := n.Tags
496+
*n = osm.Node{Visible: true, Tags: tags[:0]}
483497
}
484498
}
485499

486500
return nil
487501
}
488502

489-
func (dec *dataDecoder) scanWays(data []byte) error {
503+
func (dec *dataDecoder) scanWays(data []byte, way *osm.Way) (*osm.Way, error) {
490504
st := dec.primitiveBlock.GetStringtable().GetS()
491505
granularity := int64(dec.primitiveBlock.GetGranularity())
492506
dateGranularity := int64(dec.primitiveBlock.GetDateGranularity())
@@ -496,7 +510,10 @@ func (dec *dataDecoder) scanWays(data []byte) error {
496510

497511
msg := protoscan.New(data)
498512

499-
way := &osm.Way{Visible: true}
513+
if way == nil {
514+
way = &osm.Way{Visible: true}
515+
}
516+
500517
var foundKeys, foundVals bool
501518
for msg.Next() {
502519
var i64 int64
@@ -515,7 +532,7 @@ func (dec *dataDecoder) scanWays(data []byte) error {
515532
case 4: // info
516533
d, err := msg.MessageData()
517534
if err != nil {
518-
return err
535+
return nil, err
519536
}
520537

521538
info := protoscan.New(d)
@@ -524,38 +541,38 @@ func (dec *dataDecoder) scanWays(data []byte) error {
524541
case 1:
525542
v, err := info.Int32()
526543
if err != nil {
527-
return err
544+
return nil, err
528545
}
529546
way.Version = int(v)
530547
case 2:
531548
v, err := info.Int64()
532549
if err != nil {
533-
return err
550+
return nil, err
534551
}
535552
millisec := time.Duration(v*dateGranularity) * time.Millisecond
536553
way.Timestamp = time.Unix(0, millisec.Nanoseconds()).UTC()
537554
case 3:
538555
v, err := info.Int64()
539556
if err != nil {
540-
return err
557+
return nil, err
541558
}
542559
way.ChangesetID = osm.ChangesetID(v)
543560
case 4:
544561
v, err := info.Int32()
545562
if err != nil {
546-
return err
563+
return nil, err
547564
}
548565
way.UserID = osm.UserID(v)
549566
case 5:
550567
v, err := info.Uint32()
551568
if err != nil {
552-
return err
569+
return nil, err
553570
}
554571
way.User = st[v]
555572
case 6:
556573
v, err := info.Bool()
557574
if err != nil {
558-
return err
575+
return nil, err
559576
}
560577
way.Visible = v
561578
default:
@@ -564,12 +581,12 @@ func (dec *dataDecoder) scanWays(data []byte) error {
564581
}
565582

566583
if info.Err() != nil {
567-
return info.Err()
584+
return nil, info.Err()
568585
}
569586
case 8: // refs or nodes
570587
dec.nodes, err = msg.Iterator(dec.nodes)
571588
if err != nil {
572-
return err
589+
return nil, err
573590
}
574591

575592
var prev, index int64
@@ -579,7 +596,7 @@ func (dec *dataDecoder) scanWays(data []byte) error {
579596
for dec.nodes.HasNext() {
580597
v, err := dec.nodes.Sint64()
581598
if err != nil {
582-
return err
599+
return nil, err
583600
}
584601
prev = v + prev // delta encoding
585602
way.Nodes[index].ID = osm.NodeID(prev)
@@ -588,7 +605,7 @@ func (dec *dataDecoder) scanWays(data []byte) error {
588605
case 9: // lat
589606
dec.wlats, err = msg.Iterator(dec.wlats)
590607
if err != nil {
591-
return err
608+
return nil, err
592609
}
593610

594611
var prev, index int64
@@ -598,7 +615,7 @@ func (dec *dataDecoder) scanWays(data []byte) error {
598615
for dec.wlats.HasNext() {
599616
v, err := dec.wlats.Sint64()
600617
if err != nil {
601-
return err
618+
return nil, err
602619
}
603620
prev = v + prev // delta encoding
604621
way.Nodes[index].Lat = 1e-9 * float64(latOffset+(granularity*prev))
@@ -607,7 +624,7 @@ func (dec *dataDecoder) scanWays(data []byte) error {
607624
case 10: // lon
608625
dec.wlons, err = msg.Iterator(dec.wlons)
609626
if err != nil {
610-
return err
627+
return nil, err
611628
}
612629

613630
var prev, index int64
@@ -617,7 +634,7 @@ func (dec *dataDecoder) scanWays(data []byte) error {
617634
for dec.wlons.HasNext() {
618635
v, err := dec.wlons.Sint64()
619636
if err != nil {
620-
return err
637+
return nil, err
621638
}
622639
prev = v + prev // delta encoding
623640
way.Nodes[index].Lon = 1e-9 * float64(lonOffset+(granularity*prev))
@@ -628,25 +645,23 @@ func (dec *dataDecoder) scanWays(data []byte) error {
628645
}
629646

630647
if err != nil {
631-
return err
648+
return nil, err
632649
}
633650
}
634651

635652
if msg.Err() != nil {
636-
return msg.Err()
653+
return nil, msg.Err()
637654
}
638655

639656
if foundKeys && foundVals {
640657
var err error
641658
way.Tags, err = scanTags(st, dec.keys, dec.vals)
642659
if err != nil {
643-
return err
660+
return nil, err
644661
}
645662
}
646-
if dec.scanner.WayFilter == nil || dec.scanner.WayFilter(*way) {
647-
dec.q = append(dec.q, way)
648-
}
649-
return nil
663+
664+
return way, nil
650665
}
651666

652667
// Make relation members from stringtable and three parallel arrays of IDs.
@@ -693,13 +708,16 @@ func extractMembers(
693708
return members, nil
694709
}
695710

696-
func (dec *dataDecoder) scanRelations(data []byte) error {
711+
func (dec *dataDecoder) scanRelations(data []byte, relation *osm.Relation) (*osm.Relation, error) {
697712
st := dec.primitiveBlock.GetStringtable().GetS()
698713
dateGranularity := int64(dec.primitiveBlock.GetDateGranularity())
699714

700715
msg := protoscan.New(data)
701716

702-
relation := &osm.Relation{Visible: true}
717+
if relation == nil {
718+
relation = &osm.Relation{Visible: true}
719+
}
720+
703721
var foundKeys, foundVals, foundRoles, foundMemids, foundTypes bool
704722
for msg.Next() {
705723
var i64 int64
@@ -718,7 +736,7 @@ func (dec *dataDecoder) scanRelations(data []byte) error {
718736
case 4: // info
719737
d, err := msg.MessageData()
720738
if err != nil {
721-
return err
739+
return nil, err
722740
}
723741

724742
info := protoscan.New(d)
@@ -727,38 +745,38 @@ func (dec *dataDecoder) scanRelations(data []byte) error {
727745
case 1:
728746
v, err := info.Int32()
729747
if err != nil {
730-
return err
748+
return nil, err
731749
}
732750
relation.Version = int(v)
733751
case 2:
734752
v, err := info.Int64()
735753
if err != nil {
736-
return err
754+
return nil, err
737755
}
738756
millisec := time.Duration(v*dateGranularity) * time.Millisecond
739757
relation.Timestamp = time.Unix(0, millisec.Nanoseconds()).UTC()
740758
case 3:
741759
v, err := info.Int64()
742760
if err != nil {
743-
return err
761+
return nil, err
744762
}
745763
relation.ChangesetID = osm.ChangesetID(v)
746764
case 4:
747765
v, err := info.Int32()
748766
if err != nil {
749-
return err
767+
return nil, err
750768
}
751769
relation.UserID = osm.UserID(v)
752770
case 5:
753771
v, err := info.Uint32()
754772
if err != nil {
755-
return err
773+
return nil, err
756774
}
757775
relation.User = st[v]
758776
case 6:
759777
v, err := info.Bool()
760778
if err != nil {
761-
return err
779+
return nil, err
762780
}
763781
relation.Visible = v
764782
default:
@@ -767,7 +785,7 @@ func (dec *dataDecoder) scanRelations(data []byte) error {
767785
}
768786

769787
if info.Err() != nil {
770-
return info.Err()
788+
return nil, info.Err()
771789
}
772790
case 8: // refs or nodes
773791
dec.roles, err = msg.Iterator(dec.roles)
@@ -783,20 +801,20 @@ func (dec *dataDecoder) scanRelations(data []byte) error {
783801
}
784802

785803
if err != nil {
786-
return err
804+
return nil, err
787805
}
788806
}
789807

790808
if msg.Err() != nil {
791-
return msg.Err()
809+
return nil, msg.Err()
792810
}
793811

794812
// possible for relation to not have tags
795813
if foundKeys && foundVals {
796814
var err error
797815
relation.Tags, err = scanTags(st, dec.keys, dec.vals)
798816
if err != nil {
799-
return err
817+
return nil, err
800818
}
801819
}
802820

@@ -805,13 +823,11 @@ func (dec *dataDecoder) scanRelations(data []byte) error {
805823
var err error
806824
relation.Members, err = extractMembers(st, dec.roles, dec.memids, dec.types)
807825
if err != nil {
808-
return err
826+
return nil, err
809827
}
810828
}
811-
if dec.scanner.RelationFilter == nil || dec.scanner.RelationFilter(*relation) {
812-
dec.q = append(dec.q, relation)
813-
}
814-
return nil
829+
830+
return relation, nil
815831
}
816832

817833
func scanTags(stringTable []string, keys, vals *protoscan.Iterator) (osm.Tags, error) {

osmpbf/scanner.go

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ var _ osm.Scanner = &Scanner{}
2121
// https://golang.org/pkg/bufio/#Scanner
2222
type Scanner struct {
2323
// Skip element types that are not needed. The data is skipped
24-
// at the encoded protobuf level, but each block still
25-
// needs to be decompressed.
26-
SkipNodes bool
27-
SkipWays bool
28-
SkipRelations bool
29-
NodeFilter func(osm.Node) bool
30-
WayFilter func(osm.Way) bool
31-
RelationFilter func(osm.Relation) bool
24+
// at the encoded protobuf level, but each block still needs to be decompressed.
25+
SkipNodes bool
26+
SkipWays bool
27+
SkipRelations bool
28+
29+
// If the Filter function is false, the element well be skipped
30+
// at the decoding level. The functions should be fast, they block the
31+
// decoder, there are `procs` number of concurrent decoders.
32+
FilterNode func(*osm.Node) bool
33+
FilterWay func(*osm.Way) bool
34+
FilterRelation func(*osm.Relation) bool
3235

3336
ctx context.Context
3437
closed bool

0 commit comments

Comments
 (0)