Skip to content

Commit d00de78

Browse files
committed
Refactor wsl-perf as Nim
1 parent e6e68ae commit d00de78

File tree

5 files changed

+107
-105
lines changed

5 files changed

+107
-105
lines changed

.github/workflows/release-artifacts.yml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,32 @@ jobs:
2525
echo "version=$version" >> "$env:GITHUB_ENV"
2626
echo "version=$version"
2727
28-
- name: Set up PowerShell
28+
- name: Configure PowerShell
2929
run: |
3030
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
3131
32-
- name: Install ps2exe module
32+
- name: Install ps2exe module to compile PowerShell scripts
3333
run: |
3434
Install-Module -Name ps2exe -Scope CurrentUser -Force
3535
36-
- name: Compile and release scripts
36+
- name: Install Scoop to install Nim
37+
run: |
38+
iex "& {$(irm get.scoop.sh)} -RunAsAdmin"
39+
40+
- name: Install Nim to compile Nim applications
41+
run: |
42+
scoop install nim
43+
44+
- name: Install Nim dependencies for Nim applications
45+
run: |
46+
nimble update -y
47+
nimble install -y puppy
48+
49+
- name: Compile Nim applications
50+
run: |
51+
nim c -d:release -d:static -o:bin\wsl-perf.exe wslperf.nim
52+
53+
- name: Compile PowerShell scripts
3754
run: |
3855
echo "Compile version ${{ env.version }}"
3956
Get-ChildItem -Path . -Filter '*.ps1' -Recurse -Exclude build-wslinternals.ps1,sched-wsl-dist-update.ps1 | ForEach-Object {

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ On first run, wsl-perf will download and build the perf tool from source and sav
6868

6969
wsl-perf will pass any command line arguments to perf.elf, which is run as root in the WSL2 System Distro.
7070

71+
Unlike the other applications here, wsl-perf is built with [Nim](https://nim-lang.org/) due to limitations in argument parsing in PS2EXE.
72+
7173
## wsl-reset
7274

7375
A troubleshooting utility that resets the WSL 2 stack to various degrees.

build-wslinternals.ps1

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,30 @@
11
# Install ps2exe module if not already installed
22
if (-not (Get-Module -Name ps2exe -ListAvailable)) {
3+
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
34
Install-Module -Name ps2exe -Scope CurrentUser -Force
45
}
56

7+
# Install Scoop and Nim if not already installed
8+
if (-not (Get-Command nim -ErrorAction SilentlyContinue)) {
9+
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process -Force
10+
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
11+
scoop install nim
12+
nimble update -y
13+
nimble install puppy -y
14+
}
15+
16+
# Check if cl.exe is available
17+
if (-not (Get-Command cl -ErrorAction SilentlyContinue)) {
18+
Write-Host "cl.exe not found. Please install Visual Studio Build Tools 2019 or Visual Studio 2019 and try again."
19+
exit 1
20+
}
21+
22+
# Check if Windows SDK is available
23+
if (-not (Get-Command rc.exe -ErrorAction SilentlyContinue)) {
24+
Write-Host "rc.exe not found. Please install Windows SDK and try again."
25+
exit 1
26+
}
27+
628
# Create /bin/ subdirectory if it does not exist
729
if (-not (Test-Path -Path ".\bin\" -PathType Container)) {
830
New-Item -ItemType Directory -Path ".\bin\"
@@ -19,4 +41,7 @@ foreach ($ps1File in $ps1Files) {
1941
}
2042
$exeFile = ".\bin\" + $ps1File.Name.Replace(".ps1", ".exe")
2143
ps2exe -inputFile $ps1File.FullName -outputFile $exeFile
22-
}
44+
}
45+
46+
# Compile wslperf.nim to wsl-perf.exe
47+
nim c -d:release -d:static -o:bin\wsl-perf.exe wslperf.nim

wsl-perf.ps1

Lines changed: 0 additions & 101 deletions
This file was deleted.

wslperf.nim

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import os, osproc, strutils, json, puppy
2+
3+
let tempDir = getEnv("TEMP")
4+
let wslTempDir = "/mnt/" & tempDir[0].toLowerAscii() & tempDir[2..^1].replace("\\", "/")
5+
6+
proc runCommand(cmd: string): (int, string, string) =
7+
let result = execCmdEx(cmd, options = {poUsePath, poStdErrToStdOut})
8+
echo result.output
9+
return (result.exitCode, result.output, result.output)
10+
11+
proc downloadKernel() =
12+
13+
# Get latest kernel version of Microsoft/WSL2-Linux-Kernel from GitHub API
14+
let response = get("https://api.github.com/repos/microsoft/WSL2-Linux-Kernel/releases/latest")
15+
let json = parseJson(response.body)
16+
let kernelVersion = json["tag_name"].str
17+
# Get download url for kernel tar.gz
18+
let downloadUrl = "https://github.com/microsoft/WSL2-Linux-Kernel/archive/refs/tags/" & kernelVersion & ".tar.gz"
19+
# Use puppy library to download kernel tar.gz
20+
let download = get(downloadUrl)
21+
let kernelTar = open(tempDir & "/kernel.tar.gz", fmWrite)
22+
kernelTar.write(download.body)
23+
kernelTar.close()
24+
25+
let perfElfExists = fileExists("perf.elf")
26+
27+
if perfElfExists:
28+
let (output, exitCode) = execCmdEx("wsl.exe --system --user root ./perf.elf " & commandLineParams().join(" "))
29+
echo output
30+
if exitCode != 0:
31+
quit(exitCode)
32+
else:
33+
echo "perf does not exist. Do you want to build and install perf? [Y/n]"
34+
let response = readLine(stdin)
35+
if response in ["", "Y", "y"]:
36+
echo "Installing perf"
37+
discard runCommand("wsl.exe --system --user root sh -c \"while true; do sleep 1000; done\"&")
38+
echo "Installing dependencies"
39+
discard runCommand("wsl.exe --system --user root tdnf install -y gcc glibc-devel make gawk tar kernel-headers binutils flex bison glibc-static diffutils elfutils-libelf-devel libnuma-devel libbabeltrace2-devel python3")
40+
echo "Downloading perf sources"
41+
downloadKernel()
42+
echo "Copying perf sources to WSL System Distro"
43+
discard runCommand("wsl --system --user root cp " & wslTempDir & "/kernel.tar.gz ~/kernel.tar.gz")
44+
echo "Extracting perf sources"
45+
discard runCommand("wsl --system --user root tar -xzf ~/kernel.tar.gz -C ~")
46+
echo "Building perf"
47+
discard runCommand("wsl --system --user root sh -c \"cd ~/WSL2-Linux-Kernel-* && make -C tools/perf LDFLAGS='-static'\"")
48+
echo "Copying perf to local directory"
49+
discard runCommand("wsl --system --user root cp ~/WSL2-Linux-Kernel-*/tools/perf/perf ./perf.elf")
50+
echo "Cleaning up"
51+
discard runCommand("wsl --system --user root pkill sleep")
52+
removeFile(getEnv("TEMP") & "/kernel.tar.gz")
53+
echo "perf installed: ", fileExists("perf.elf")
54+
let (output, exitCode) = execCmdEx("wsl.exe --system --user root ./perf.elf " & commandLineParams().join(" "))
55+
echo output
56+
if exitCode != 0:
57+
quit(exitCode)
58+
else:
59+
echo "Exiting..."

0 commit comments

Comments
 (0)