Skip to content

Commit

Permalink
Improve init performance by not calling posh-tabcomplete during init (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
domsleee authored Sep 16, 2023
1 parent 2931010 commit 256ccc3
Show file tree
Hide file tree
Showing 9 changed files with 43 additions and 36 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ The completions packaged with the binary in [completions.nu](./resource/completi
## Benchmarks
To run these, run `./benchmark/benchmark_all.ps1`

| Benchmark | Results |
| ---------------------------------------------------- | ------------------------------------------------------- |
| `benchmark/init` - startup time | posh-tabcomplete: 102ms, posh-git: 432ms (4.24x faster) |
| `benchmark/complete` - tab completion (100 branches) | posh-tabcomplete: 71ms, posh-git: 172ms (2.42x faster) |
| Benchmark | Results |
| ---------------------------------------------------- | ------------------------------------------------------ |
| `benchmark/init` - startup time | posh-tabcomplete: 80ms, posh-git: 307ms (3.84x faster) |
| `benchmark/complete` - tab completion (100 branches) | posh-tabcomplete: 80ms, posh-git: 178ms (2.22x faster) |

## Aliases / Function support
Functions are supported. For example, the completion of `gco` in the demo is:
Expand Down
18 changes: 9 additions & 9 deletions benchmark/all.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
# All results

file size: 14286336
file size: 14286848
## Init

| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| `pwsh -NoProfile -File ./../profiles/ProfileBaseline.ps1` | 234.5 ± 6.0 | 226.0 | 250.7 | 1.00 |
| `pwsh -NoProfile -File ./../profiles/ProfilePoshGit.ps1` | 525.4 ± 6.2 | 514.2 | 541.2 | 2.24 ± 0.06 |
| `pwsh -NoProfile -File ./../profiles/ProfileTabComplete.ps1` | 295.1 ± 4.9 | 288.2 | 311.9 | 1.26 ± 0.04 |
| `pwsh -NoProfile -File ./../profiles/ProfileBaseline.ps1` | 227.1 ± 4.8 | 220.2 | 240.1 | 1.00 |
| `pwsh -NoProfile -File ./../profiles/ProfilePoshGit.ps1` | 534.8 ± 30.9 | 505.8 | 624.0 | 2.35 ± 0.14 |
| `pwsh -NoProfile -File ./../profiles/ProfileTabComplete.ps1` | 307.8 ± 22.4 | 268.0 | 370.3 | 1.36 ± 0.10 |

tabcomplete: 60ms, posh-git: 290ms (4.83x faster)
posh-tabcomplete: 80ms, posh-git: 307ms (3.84x faster)
## Complete

| Command | Mean [ms] | Min [ms] | Max [ms] | Relative |
|:---|---:|---:|---:|---:|
| `pwsh -NoProfile -File CompleteBaseline.ps1` | 574.8 ± 9.2 | 561.8 | 599.1 | 1.00 |
| `pwsh -NoProfile -File CompletePoshGit.ps1` | 761.5 ± 8.6 | 746.9 | 780.7 | 1.32 ± 0.03 |
| `pwsh -NoProfile -File CompleteTabComplete.ps1` | 660.5 ± 10.5 | 647.3 | 694.2 | 1.15 ± 0.03 |
| `pwsh -NoProfile -File CompleteBaseline.ps1` | 546.7 ± 7.8 | 536.8 | 574.4 | 1.00 |
| `pwsh -NoProfile -File CompletePoshGit.ps1` | 724.9 ± 7.3 | 713.6 | 746.7 | 1.33 ± 0.02 |
| `pwsh -NoProfile -File CompleteTabComplete.ps1` | 627.3 ± 5.4 | 617.5 | 641.5 | 1.15 ± 0.02 |

tabcomplete: 85ms, posh-git: 186ms (2.19x faster)
posh-tabcomplete: 80ms, posh-git: 178ms (2.22x faster)
5 changes: 1 addition & 4 deletions benchmark/complete/benchmark_complete.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ if (Test-Path "$childRepoDir") {
Remove-Item -r -fo "$childRepoDir"
}

# ensure posh-git is installed
$(Get-InstalledModule -Name "posh-git").Version

Write-Output "set up childRepoDir"
mkdir "$childRepoDir"
Set-Location "$childRepoDir"
Expand All @@ -22,7 +19,7 @@ git commit -m "init"
Set-Location "$PSScriptRoot"
hyperfine `
--warmup 3 `
--runs 25 `
--runs 75 `
-L script CompleteBaseline.ps1,CompletePoshGit.ps1,CompleteTabComplete.ps1 `
"pwsh -NoProfile -File {script}" `
--export-markdown $PSScriptRoot/complete.md `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/init/benchmark_init.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
Set-Location $PSScriptRoot
hyperfine `
--warmup 3 `
--runs 25 `
--runs 75 `
-L profile ./../profiles/ProfileBaseline.ps1,./../profiles/ProfilePoshGit.ps1,./../profiles/ProfileTabComplete.ps1 `
"pwsh -NoProfile -File {profile}" `
--export-markdown init.md `
Expand Down
2 changes: 1 addition & 1 deletion benchmark/profiles/ProfileTabComplete.ps1
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Invoke-Expression (&tabcomplete init | Out-String)
Invoke-Expression (&posh-tabcomplete init | Out-String)
2 changes: 1 addition & 1 deletion benchmark/util.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ function GetMs {

function GetSummary {
param ([double] $poshMs, [double] $tabMs)
return "tabcomplete: ${tabMs}ms, posh-git: ${poshMs}ms ($([math]::Round($poshMs / $tabMs, 2))x faster)"
return "posh-tabcomplete: ${tabMs}ms, posh-git: ${poshMs}ms ($([math]::Round($poshMs / $tabMs, 2))x faster)"
}
6 changes: 4 additions & 2 deletions resource/init.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ $null = New-Module posh-tabcomplete {
"($($executables -join '|'))"
}
$EnableProxyFunctionExpansion = $true
$knownExecutables = @(&posh-tabcomplete nu-commands)#"git", "burrito"
$GitProxyFunctionRegex = "(^|[;`n])(\s*)(?<cmd>$(Get-JoinPattern $knownExecutables))(?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)(([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)(\s|``\r?\n)*($|[|;`n])"
$knownExecutables = ::TABCOMPLETE_NU_COMMANDS:: # @("git", "npm", "cargo") # @(&posh-tabcomplete nu-commands)
$GitProxyFunctionRegex = '(^|[;`n])(\s*)(?<cmd>' + (Get-JoinPattern $knownExecutables) + ')(?<params>(([^\S\r\n]|[^\S\r\n]`\r?\n)+\S+)*)(([^\S\r\n]|[^\S\r\n]`\r?\n)+\$args)(\s|`\r?\n)*($|[|;`n])'
# $GitProxyFunctionRegex = "(^|[;`n])(\s*)(?<cmd>$(Get-JoinPattern $knownExecutables))(?<params>(([^\S\r\n]|[^\S\r\n]``\r?\n)+\S+)*)(([^\S\r\n]|[^\S\r\n]``\r?\n)+\`$args)(\s|``\r?\n)*($|[|;`n])"


function Main {
$cmdNames = Get-CommandNamesUsingRegex
Expand Down
1 change: 1 addition & 0 deletions scripts/watch.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
cargo watch -i ./src/*,./resource/* -s 'cargo install --path . --debug'
35 changes: 21 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,8 @@ fn main() -> Result<(), std::io::Error> {
pub fn run_with_args(root_args: &RootArgs) -> Result<(), std::io::Error> {
match &root_args.subcommand {
TabCompleteSubCommand::Complete(complete_args) => complete(root_args, complete_args),
TabCompleteSubCommand::NuCommands => get_nu_commands(root_args),
TabCompleteSubCommand::Init => {
init();
Ok(())
}
TabCompleteSubCommand::NuCommands => print_nu_commands(root_args),
TabCompleteSubCommand::Init => init(root_args),
}?;
Ok(())
}
Expand Down Expand Up @@ -70,22 +67,32 @@ fn get_string_from_files(root_args: &RootArgs) -> String {
}

static INIT_DATA: &[u8] = include_bytes!("../resource/init.ps1");
pub fn init() {
println!("{}", str::from_utf8(INIT_DATA).unwrap());
pub fn init(root_args: &RootArgs) -> Result<(), io::Error> {
let string_data = str::from_utf8(INIT_DATA).unwrap();
let commands = get_nu_commands(root_args)?;
let joined_commands = format!("@('{}')", commands.iter().join("', '"));
let replaced_string = string_data.replace("::TABCOMPLETE_NU_COMMANDS::", &joined_commands);
println!("{}", replaced_string);
Ok(())
}

pub fn print_nu_commands(root_args: &RootArgs) -> Result<(), io::Error> {
let s = get_nu_commands(root_args)?;
println!("{}", s.iter().join("\n"));
Ok(())
}

pub fn get_nu_commands(root_args: &RootArgs) -> Result<(), io::Error> {
let _string_from_files = get_string_from_files(root_args);
let nu_file_data = if _string_from_files.is_empty() {
pub fn get_nu_commands(root_args: &RootArgs) -> Result<HashSet<String>, io::Error> {
let string_from_files = get_string_from_files(root_args);
let nu_file_data = if string_from_files.is_empty() {
String::from_utf8_lossy(DEFAULT_CONFIG_DATA).to_string()
} else {
_string_from_files
string_from_files
};
let re = Regex::new(r#"(?:^|\n)\s*export extern "\S+"#).unwrap();
let matches = re
.find_iter(&nu_file_data)
.map(|x| x.as_str().split('"').nth(1).unwrap());
let s: HashSet<&str> = HashSet::from_iter(matches);
println!("{}", s.iter().join("\n"));
Ok(())
let s: HashSet<String> = HashSet::from_iter(matches.map(|m| m.to_string()));
Ok(s)
}

0 comments on commit 256ccc3

Please sign in to comment.