From fbb44fae1ddb3dfac6f10bc921b1fed4f763ff42 Mon Sep 17 00:00:00 2001 From: TJ Holowaychuk Date: Sun, 19 Nov 2017 10:05:09 -0800 Subject: [PATCH] add concurrency. Closes #5 --- Readme.md | 16 ++++++++-------- prune.go | 33 ++++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/Readme.md b/Readme.md index e016432..f2dc59e 100644 --- a/Readme.md +++ b/Readme.md @@ -13,10 +13,10 @@ In your app directory: ``` $ node-prune -files total 25,042 -files removed 5,851 -size removed 21 MB - duration 433ms +files total 27,330 +files removed 3,989 +size removed 13 MB + duration 211ms ``` Somewhere else: @@ -24,10 +24,10 @@ Somewhere else: ``` $ node-prune path/to/node_modules -files total 25,042 -files removed 5,851 -size removed 21 MB - duration 433ms +files total 27,330 +files removed 3,989 +size removed 13 MB + duration 211ms ``` ## What? diff --git a/prune.go b/prune.go index a92038c..0114c48 100644 --- a/prune.go +++ b/prune.go @@ -4,9 +4,9 @@ package prune import ( "os" "path/filepath" + "runtime" "github.com/apex/log" - "github.com/pkg/errors" ) // DefaultFiles pruned. @@ -76,6 +76,7 @@ type Pruner struct { dirs map[string]struct{} exts map[string]struct{} files map[string]struct{} + ch chan func() } // Option function. @@ -89,6 +90,7 @@ func New(options ...Option) *Pruner { exts: toMap(DefaultExtensions), dirs: toMap(DefaultDirectories), files: toMap(DefaultFiles), + ch: make(chan func()), } for _, o := range options { @@ -130,6 +132,11 @@ func WithFiles(s []string) Option { func (p Pruner) Prune() (*Stats, error) { var stats Stats + for i := 0; i < runtime.NumCPU(); i++ { + go p.start() + } + defer p.stop() + err := filepath.Walk(p.dir, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -164,15 +171,19 @@ func (p Pruner) Prune() (*Stats, error) { // remove and skip dir if info.IsDir() { - if err := os.RemoveAll(path); err != nil { - return errors.Wrap(err, "removing dir") + p.ch <- func() { + if err := os.RemoveAll(path); err != nil { + ctx.WithError(err).Error("removing directory") + } } return filepath.SkipDir } // remove file - if err := os.Remove(path); err != nil { - return errors.Wrap(err, "removing") + p.ch <- func() { + if err := os.Remove(path); err != nil { + ctx.WithError(err).Error("removing file") + } } return nil @@ -201,6 +212,18 @@ func (p Pruner) prune(path string, info os.FileInfo) bool { return ok } +// start loop. +func (p Pruner) start() { + for fn := range p.ch { + fn() + } +} + +// stop loop. +func (p Pruner) stop() { + close(p.ch) +} + // dirStats returns stats for files in dir. func dirStats(dir string) (*Stats, error) { var stats Stats