mirror of
https://github.com/anchore/syft.git
synced 2026-10-30 14:02:26 +01:00
feat: parallelize catalogers per-file and hash contents in parallel (#3636)
Signed-off-by: Keith Zantow <kzantow@gmail.com>
This commit is contained in:
@@ -5,11 +5,8 @@ import (
|
||||
"fmt"
|
||||
"runtime/debug"
|
||||
"slices"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/internal/unknown"
|
||||
@@ -18,64 +15,17 @@ import (
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type Executor struct {
|
||||
numWorkers int
|
||||
tasks chan Task
|
||||
}
|
||||
|
||||
func NewTaskExecutor(tasks []Task, numWorkers int) *Executor {
|
||||
p := &Executor{
|
||||
numWorkers: numWorkers,
|
||||
tasks: make(chan Task, len(tasks)),
|
||||
func RunTask(ctx context.Context, tsk Task, resolver file.Resolver, s sbomsync.Builder, prog *monitor.CatalogerTaskProgress) error {
|
||||
err := runTaskSafely(ctx, tsk, resolver, s)
|
||||
unknowns, remainingErrors := unknown.ExtractCoordinateErrors(err)
|
||||
if len(unknowns) > 0 {
|
||||
appendUnknowns(s, tsk.Name(), unknowns)
|
||||
}
|
||||
|
||||
for i := range tasks {
|
||||
p.tasks <- tasks[i]
|
||||
if remainingErrors != nil {
|
||||
prog.SetError(remainingErrors)
|
||||
}
|
||||
close(p.tasks)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Executor) Execute(ctx context.Context, resolver file.Resolver, s sbomsync.Builder, prog *monitor.CatalogerTaskProgress) error {
|
||||
var lock sync.Mutex
|
||||
withLock := func(fn func()) {
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
fn()
|
||||
}
|
||||
var errs error
|
||||
wg := &sync.WaitGroup{}
|
||||
for i := 0; i < p.numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
for {
|
||||
tsk, ok := <-p.tasks
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
err := runTaskSafely(ctx, tsk, resolver, s)
|
||||
unknowns, remainingErrors := unknown.ExtractCoordinateErrors(err)
|
||||
if len(unknowns) > 0 {
|
||||
appendUnknowns(s, tsk.Name(), unknowns)
|
||||
}
|
||||
if remainingErrors != nil {
|
||||
withLock(func() {
|
||||
errs = multierror.Append(errs, fmt.Errorf("failed to run task: %w", remainingErrors))
|
||||
prog.SetError(remainingErrors)
|
||||
})
|
||||
}
|
||||
prog.Increment()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return errs
|
||||
prog.Increment()
|
||||
return remainingErrors
|
||||
}
|
||||
|
||||
func appendUnknowns(builder sbomsync.Builder, taskName string, unknowns []unknown.CoordinateError) {
|
||||
|
||||
@@ -16,9 +16,8 @@ func Test_TaskExecutor_PanicHandling(t *testing.T) {
|
||||
tsk := NewTask("panicking-cataloger", func(_ context.Context, _ file.Resolver, _ sbomsync.Builder) error {
|
||||
panic("something bad happened")
|
||||
})
|
||||
ex := NewTaskExecutor([]Task{tsk}, 1)
|
||||
|
||||
err := ex.Execute(context.Background(), nil, nil, &monitor.CatalogerTaskProgress{
|
||||
err := RunTask(context.Background(), tsk, nil, nil, &monitor.CatalogerTaskProgress{
|
||||
Manual: progress.NewManual(-1),
|
||||
})
|
||||
|
||||
|
||||
@@ -120,14 +120,14 @@ func newExecutableCatalogerTaskFactory(tags ...string) factory {
|
||||
}
|
||||
|
||||
func newExecutableCatalogerTask(selection file.Selection, cfg executable.Config, tags ...string) Task {
|
||||
fn := func(_ context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
if selection == file.NoFilesSelection {
|
||||
return nil
|
||||
}
|
||||
|
||||
accessor := builder.(sbomsync.Accessor)
|
||||
|
||||
result, err := executable.NewCataloger(cfg).Catalog(resolver)
|
||||
result, err := executable.NewCataloger(cfg).CatalogCtx(ctx, resolver)
|
||||
|
||||
accessor.WriteToSBOM(func(sbom *sbom.SBOM) {
|
||||
sbom.Artifacts.Executables = result
|
||||
|
||||
Reference in New Issue
Block a user