@@ -5,8 +5,11 @@ import (
55 "fmt"
66 "os"
77 "path/filepath"
8+ "runtime"
89 "runtime/pprof"
910 "strings"
11+ "sync"
12+ "sync/atomic"
1013
1114 "github.com/xaionaro-go/binder/tools/pkg/parcelspec"
1215 "gopkg.in/yaml.v3"
@@ -46,14 +49,21 @@ func main() {
4649 }
4750}
4851
52+ type fileWork struct {
53+ path string
54+ packageName string
55+ src []byte
56+ }
57+
4958func run (
5059 frameworksBase string ,
5160 outputDir string ,
5261) error {
53- generated := 0
54- skipped := 0
55- extractor := parcelspec .NewJavaExtractor ()
62+ var generated atomic.Int64
63+ var skipped atomic.Int64
5664
65+ // Collect files to process.
66+ var files []fileWork
5767 err := filepath .Walk (frameworksBase , func (path string , info os.FileInfo , err error ) error {
5868 if err != nil {
5969 return err
@@ -78,26 +88,56 @@ func run(
7888 return nil
7989 }
8090
81- specs := extractor .ExtractSpecs (string (src ), packageName )
82- for _ , spec := range specs {
83- if len (spec .Fields ) == 0 {
84- skipped ++
85- continue
86- }
87-
88- if err := writeSpec (outputDir , spec ); err != nil {
89- return fmt .Errorf ("writing spec for %s.%s: %w" , spec .Package , spec .Type , err )
90- }
91- generated ++
92- }
93-
91+ files = append (files , fileWork {path : path , packageName : packageName , src : src })
9492 return nil
9593 })
9694 if err != nil {
9795 return fmt .Errorf ("walking %s: %w" , frameworksBase , err )
9896 }
9997
100- fmt .Fprintf (os .Stderr , "genparcelspec: generated %d specs, skipped %d empty specs\n " , generated , skipped )
98+ // Process files in parallel. Each worker has its own ANTLR parser
99+ // (not thread-safe), fed from a shared channel.
100+ work := make (chan fileWork , len (files ))
101+ for _ , f := range files {
102+ work <- f
103+ }
104+ close (work )
105+
106+ numWorkers := runtime .NumCPU ()
107+ var wg sync.WaitGroup
108+ var firstErr atomic.Value
109+
110+ for range numWorkers {
111+ wg .Add (1 )
112+ go func () {
113+ defer wg .Done ()
114+ extractor := parcelspec .NewJavaExtractor ()
115+
116+ for fw := range work {
117+ specs := extractor .ExtractSpecs (string (fw .src ), fw .packageName )
118+ for _ , spec := range specs {
119+ if len (spec .Fields ) == 0 {
120+ skipped .Add (1 )
121+ continue
122+ }
123+
124+ if err := writeSpec (outputDir , spec ); err != nil {
125+ firstErr .CompareAndSwap (nil , fmt .Errorf ("writing spec for %s.%s: %w" , spec .Package , spec .Type , err ))
126+ return
127+ }
128+ generated .Add (1 )
129+ }
130+ }
131+ }()
132+ }
133+
134+ wg .Wait ()
135+
136+ if v := firstErr .Load (); v != nil {
137+ return v .(error )
138+ }
139+
140+ fmt .Fprintf (os .Stderr , "genparcelspec: generated %d specs, skipped %d empty specs\n " , generated .Load (), skipped .Load ())
101141 return nil
102142}
103143
0 commit comments