-
Notifications
You must be signed in to change notification settings - Fork 91
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Indexing: use one ctags process per shard (#702)
Currently, we use a single ctags process for indexing an entire repository. Even though we build shards in parallel, they all share the same (single threaded) ctags process. Since ctags is one of the most expensive parts of shard building, this creates a bottleneck that can really slow down indexing. This change proposes to launch a new ctags process per shard. For `sgtest/megarepo`, this speeds up indexing by almost 2x (enabling scip-ctags and setting `-parallelism=4`): * Before: took 4 min 48 sec to index repo * After: took 2 min 30 sec to index repo
- Loading branch information
1 parent
d982320
commit 5c51794
Showing
7 changed files
with
161 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// Copyright 2017 Google Inc. All rights reserved. | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package ctags | ||
|
||
import ( | ||
"bytes" | ||
"fmt" | ||
"log" | ||
"os" | ||
"os/exec" | ||
"strings" | ||
|
||
goctags "github.com/sourcegraph/go-ctags" | ||
) | ||
|
||
type CTagsParserType uint8 | ||
|
||
const ( | ||
UnknownCTags CTagsParserType = iota | ||
NoCTags | ||
UniversalCTags | ||
ScipCTags | ||
) | ||
|
||
type LanguageMap = map[string]CTagsParserType | ||
|
||
func ParserToString(parser CTagsParserType) string { | ||
switch parser { | ||
case UnknownCTags: | ||
return "unknown" | ||
case NoCTags: | ||
return "no" | ||
case UniversalCTags: | ||
return "universal" | ||
case ScipCTags: | ||
return "scip" | ||
default: | ||
panic("Reached impossible CTagsParserType state") | ||
} | ||
} | ||
|
||
func StringToParser(str string) CTagsParserType { | ||
switch str { | ||
case "no": | ||
return NoCTags | ||
case "universal": | ||
return UniversalCTags | ||
case "scip": | ||
return ScipCTags | ||
default: | ||
return UniversalCTags | ||
} | ||
} | ||
|
||
type ParserFactory map[CTagsParserType]string | ||
|
||
func NewParserFactory( | ||
ctagsPath string, | ||
scipCTagsPath string, | ||
languageMap LanguageMap, | ||
cTagsMustSucceed bool, | ||
) (ParserFactory, error) { | ||
validBins := make(map[CTagsParserType]string) | ||
requiredBins := map[CTagsParserType]string{UniversalCTags: ctagsPath} | ||
for _, parserType := range languageMap { | ||
if parserType == ScipCTags { | ||
requiredBins[ScipCTags] = scipCTagsPath | ||
break | ||
} | ||
} | ||
|
||
for parserType, bin := range requiredBins { | ||
if bin == "" && cTagsMustSucceed { | ||
return nil, fmt.Errorf("ctags binary not found for %s parser type", ParserToString(parserType)) | ||
} | ||
if err := checkBinary(parserType, bin); err != nil && cTagsMustSucceed { | ||
return nil, fmt.Errorf("ctags.NewParserFactory: %v", err) | ||
} | ||
validBins[parserType] = bin | ||
} | ||
|
||
return validBins, nil | ||
} | ||
|
||
// checkBinary does checks on bin to ensure we can correctly use the binary | ||
// for symbols. It is more user friendly to fail early in this case. | ||
func checkBinary(typ CTagsParserType, bin string) error { | ||
switch typ { | ||
case UniversalCTags: | ||
helpOutput, err := exec.Command(bin, "--help").CombinedOutput() | ||
if err != nil { | ||
return fmt.Errorf("failed to check if %s is universal-ctags: %w\n--help output:\n%s", bin, err, string(helpOutput)) | ||
} | ||
if !bytes.Contains(helpOutput, []byte("+interactive")) { | ||
return fmt.Errorf("ctags binary is not universal-ctags or is not compiled with +interactive feature: bin=%s", bin) | ||
} | ||
|
||
case ScipCTags: | ||
if !strings.Contains(bin, "scip-ctags") { | ||
return fmt.Errorf("only supports scip-ctags, not %s", bin) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// NewParser creates a parser that is implemented by the given | ||
// ctags binary. The parser is safe for concurrent use. | ||
func (p ParserFactory) NewParser(typ CTagsParserType) Parser { | ||
bin := p[typ] | ||
if bin == "" { | ||
return nil | ||
} | ||
|
||
opts := goctags.Options{Bin: bin} | ||
if debug { | ||
opts.Info = log.New(os.Stderr, "CTAGS INF: ", log.LstdFlags) | ||
opts.Debug = log.New(os.Stderr, "CTAGS DBG: ", log.LstdFlags) | ||
} | ||
return &lockedParser{opts: opts} | ||
} |
Oops, something went wrong.