Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code-PS #39262

Closed
dbaeumer opened this issue Nov 28, 2017 · 28 comments
Closed

Code-PS #39262

dbaeumer opened this issue Nov 28, 2017 · 28 comments
Assignees
Labels
feature-request Request for new features or functionality on-testplan workbench-diagnostics General VS Code built-in diagnostic issues
Milestone

Comments

@dbaeumer
Copy link
Member

Issue is used to collect ideas around a code-ps tools to collect process information about running code processes:

  • output should be JSON
  • contain machine information like:
    memory, cores, CPU and memory usage
  • contain information per code processes
    parent process, CPU, memory, kind, ...
@bpasero
Copy link
Member

bpasero commented Nov 28, 2017

@dbaeumer @weinand some first baby steps (tested on macOS only):

image

The JSON format I am using currently is pretty much left untouched from what @weinand had before:

export interface ProcessItem {
	name: string;
	cmd: string;
	pid: string;
	children?: ProcessItem[];
}

I am easy on having a different format. Of course it misses the yet to be added info around CPU and memory usage.

As for more info to provide, we could include the additional info we have when running "code --performance":

image

@bpasero bpasero added this to the November 2017 milestone Nov 28, 2017
@bpasero bpasero added the workbench-diagnostics General VS Code built-in diagnostic issues label Nov 28, 2017
@weinand
Copy link
Contributor

weinand commented Nov 28, 2017

The latest has support for Windows.

@weinand
Copy link
Contributor

weinand commented Nov 29, 2017

and there is now a "load" attribute (atm macOS and linux only)

@dbaeumer
Copy link
Member Author

I looked into how to get that information under Windows. Having a load percentage attribute for the whole machine is simple and I have it coded up. However having a CPU percentage value per process is quite complicated under Windows (I think under Mac / Linux as well). The reason is that you need to sample the processes over a period of time. Windows has the concept of performance counters and I found out how to query them. But there is some math involved (which I don't fully understand yet) to get to a percentage value. My approach is now that I query these counter over 10 seconds. This information will then be used to find the 5 highest CPU load processes. I will also use these counters to compute the load for all Code processes and their sub processes.

@weinand how would you do this under Mac ?

Regarding the format: I would prefer if the PowerShell script could include a flat structure with a parent process id and we do the inference if the tree in JS. I would also opt to only have the command line in it and do the process tagging (e.g terminal, renderer, ...) in JS code as well. Comments / Suggestions ?

@weinand
Copy link
Contributor

weinand commented Nov 29, 2017

@dbaeumer you can find ps.ts here: https://github.com/Microsoft/vscode/blob/master/src/vs/base/node/ps.ts

The easiest approach would be to just replace the command and the regexp by your command and regexp.

So there is no need to produce a JSON. Just a whitespace separated table is enough.
Every line of the table results in a call to addToTree that filters all items under a root pid and builds the tree. In addition it does the semantic tagging.

@bpasero
Copy link
Member

bpasero commented Nov 29, 2017

I pushed some changes:

  • show more meta information
  • show the window title for each window

I plan to include @egamma fingerprint for each window also to give a little bit more information about the workspace that is opened.

image

It works fine on mac and linux but still misses CPU/Memory information on Windows. The total memory information is printed via node.js methods (os.freemem, os.totalmem). The load average is only available on macOS and Linux via os.loadavg.

@egamma
Copy link
Member

egamma commented Nov 29, 2017

@bpasero #39326 this is the PR for the fingerprint (need to do another rebase).

@dbaeumer
Copy link
Member Author

I have the Windows PowerShell script running and it produces the following output:

[
    {
        "totalMemory":  16384,
        "logicalProcessors":  4,
        "processors":  1,
        "model":  "Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz",
        "type":  "machineInfo"
    },
    {
        "cpuLoad":  22,
        "memory":  {
                       "swapTotal":  22825740,
                       "free":  7277016,
                       "total":  16700508,
                       "swapFree":  4277948
                   },
        "type":  "machineState",
        "handles":  172378
    },
    {
        "type":  "topProcess",
        "processId":  14424,
        "parentProcessId":  24784,
        "commandLine":  "\\??\\C:\\windows\\system32\\conhost.exe 0x4",
        "cpuLoad":  [
                        4.6526165422131029,
                        3.8811108804937775,
                        1.5360306588770334
                    ]
    },
    {
        "type":  "topProcess",
        "processId":  21348,
        "parentProcessId":  21116,
        "commandLine":  "\"C:\\Program Files\\ConEmu\\ConEmu\\ConEmuC64.exe\"  /CINMODE=600020 /AID=19228 /GID=21116 /GHWND=000205AA /BW=87 /BH=55 /BZ=2048 \"/FN=Lucida Console\" /FW=3 /FH=5 /TA=10100007 /HIDE /ROOT powershell.exe",
        "cpuLoad":  [
                        5.0403345873975285,
                        2.7167776163456443,
                        2.3040459883155497
                    ]
    },
    {
        "type":  "topProcess",
        "processId":  24784,
        "parentProcessId":  23204,
        "commandLine":  "\"C:\\Program Files\\ConEmu\\ConEmu\\ConEmuC.exe\"  /CINMODE=600020 /AID=25888 /GID=23204 /GHWND=00461396 /BW=158 /BH=64 /BZ=2048 \"/FN=Lucida Console\" /FW=3 /FH=5 /TA=10100007 /HIDE /ROOT C:\\Windows\\sysnative\\bash.exe",
        "cpuLoad":  [
                        1.5508721807377011,
                        2.7167776163456443,
                        5.7601149707888748
                    ]
    },
    {
        "type":  "topProcess",
        "processId":  15544,
        "parentProcessId":  22016,
        "commandLine":  null,
        "cpuLoad":  [
                        3.4894624066598277,
                        3.4929997924443996,
                        2.688053653034808
                    ]
    },
    {
        "type":  "topProcess",
        "processId":  17780,
        "parentProcessId":  21348,
        "commandLine":  "\\??\\C:\\windows\\system32\\conhost.exe 0x4",
        "cpuLoad":  [
                        2.3263082711065515,
                        3.8811108804937775,
                        3.4560689824733251
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  16916,
        "parentProcessId":  23760,
        "commandLine":  "\\??\\C:\\windows\\system32\\conhost.exe 0x4",
        "cpuLoad":  [
                        0,
                        0,
                        0.38400766471925835
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  30344,
        "parentProcessId":  31932,
        "commandLine":  "C:\\windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  19636,
        "parentProcessId":  23760,
        "commandLine":  "C:\\windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -Command \"\u0026 \u0027C:\\Users\\dirkb\\.vscode-insiders\\extensions\\ms-vscode.powershell-1.5.1\\scripts\\Start-EditorServices.ps1\u0027 -EditorServicesVersion \u00271.5.1\u0027 -HostName \u0027Visual Studio Code Host\u0027 -HostProfileId \u0027Microsoft.VSCode\u0027 -HostVersion \u00271.5.1\u0027 -AdditionalModules @(\u0027PowerShellEditorServices.VSCode\u0027) -BundledModulesPath \u0027C:\\Users\\dirkb\\.vscode-insiders\\extensions\\ms-vscode.powershell-1.5.1\\modules\u0027 -EnableConsoleRepl -LogLevel \u0027Normal\u0027 -LogPath \u0027C:\\Users\\dirkb\\.vscode-insiders\\extensions\\ms-vscode.powershell-1.5.1\\logs\\1512032799-3d41ee8c-4d51-4c51-a1a6-66285d1f642c1512032796844\\EditorServices.log\u0027 -SessionDetailsPath \u0027C:\\Users\\dirkb\\.vscode-insiders\\extensions\\ms-vscode.powershell-1.5.1\\sessions\\PSES-VSCode-18960-552604\u0027 -FeatureFlags @()\"",
        "cpuLoad":  [
                        0.38771804518442526,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  16120,
        "parentProcessId":  13808,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" --type=gpu-process --no-sandbox --supports-dual-gpus=false --gpu-driver-bug-workarounds=7,10,19,23,41,61,74 --disable-gl-extensions=\"GL_KHR_blend_equation_advanced GL_KHR_blend_equation_advanced_coherent\" --gpu-vendor-id=0x8086 --gpu-device-id=0x1916 --gpu-driver-vendor=\"Intel Corporation\" --gpu-driver-version=20.19.15.4463 --gpu-driver-date=7-6-2016 --service-request-channel-token=C557DB99AC5BE5C1085B76A3932A1480 --mojo-platform-channel-handle=1520 /prefetch:2",
        "cpuLoad":  [
                        0.77543609036885053,
                        0,
                        0.38400766471925835
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  24660,
        "parentProcessId":  31932,
        "commandLine":  "\\??\\C:\\windows\\system32\\conhost.exe 0x4",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  18112,
        "parentProcessId":  13808,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" --type=renderer --js-flags=--nolazy --no-sandbox --primordial-pipe-token=08A7847B43D3E82D2A72C692B1715078 --lang=en-US --app-user-model-id=Microsoft.VisualStudioCodeInsiders --app-path=\"C:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\" --node-integration=true --webview-tag=true --no-sandbox --enable-pinch --device-scale-factor=1 --num-raster-threads=2 --enable-main-frame-before-activation --content-image-texture-target=0,0,3553;0,1,3553;0,2,3553;0,3,3553;0,4,3553;0,5,3553;0,6,3553;0,7,3553;0,8,3553;0,9,3553;0,10,3553;0,11,3553;0,12,3553;0,13,3553;0,14,3553;0,15,3553;1,0,3553;1,1,3553;1,2,3553;1,3,3553;1,4,3553;1,5,3553;1,6,3553;1,7,3553;1,8,3553;1,9,3553;1,10,3553;1,11,3553;1,12,3553;1,13,3553;1,14,3553;1,15,3553;2,0,3553;2,1,3553;2,2,3553;2,3,3553;2,4,3553;2,5,3553;2,6,3553;2,7,3553;2,8,3553;2,9,3553;2,10,3553;2,11,3553;2,12,3553;2,13,3553;2,14,3553;2,15,3553;3,0,3553;3,1,3553;3,2,3553;3,3,3553;3,4,3553;3,5,3553;3,6,3553;3,7,3553;3,8,3553;3,9,3553;3,10,3553;3,11,3553;3,12,3553;3,13,3553;3,14,3553;3,15,3553;4,0,3553;4,1,3553;4,2,3553;4,3,3553;4,4,3553;4,5,3553;4,6,3553;4,7,3553;4,8,3553;4,9,3553;4,10,3553;4,11,3553;4,12,3553;4,13,3553;4,14,3553;4,15,3553 --service-request-channel-token=08A7847B43D3E82D2A72C692B1715078 --renderer-client-id=6 --mojo-platform-channel-handle=2308 /prefetch:1",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  23624,
        "parentProcessId":  5932,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" \"c:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\\out\\bootstrap\" --type=terminal",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  5932,
        "parentProcessId":  13808,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" --type=renderer --js-flags=--nolazy --no-sandbox --primordial-pipe-token=B4159222B33A81E05FA8E5FCC0D55014 --lang=en-US --app-user-model-id=Microsoft.VisualStudioCodeInsiders --app-path=\"C:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\" --node-integration=true --webview-tag=true --no-sandbox --background-color=#1E1E1E --disable-blink-features=Auxclick --enable-pinch --device-scale-factor=1 --num-raster-threads=2 --enable-main-frame-before-activation --content-image-texture-target=0,0,3553;0,1,3553;0,2,3553;0,3,3553;0,4,3553;0,5,3553;0,6,3553;0,7,3553;0,8,3553;0,9,3553;0,10,3553;0,11,3553;0,12,3553;0,13,3553;0,14,3553;0,15,3553;1,0,3553;1,1,3553;1,2,3553;1,3,3553;1,4,3553;1,5,3553;1,6,3553;1,7,3553;1,8,3553;1,9,3553;1,10,3553;1,11,3553;1,12,3553;1,13,3553;1,14,3553;1,15,3553;2,0,3553;2,1,3553;2,2,3553;2,3,3553;2,4,3553;2,5,3553;2,6,3553;2,7,3553;2,8,3553;2,9,3553;2,10,3553;2,11,3553;2,12,3553;2,13,3553;2,14,3553;2,15,3553;3,0,3553;3,1,3553;3,2,3553;3,3,3553;3,4,3553;3,5,3553;3,6,3553;3,7,3553;3,8,3553;3,9,3553;3,10,3553;3,11,3553;3,12,3553;3,13,3553;3,14,3553;3,15,3553;4,0,3553;4,1,3553;4,2,3553;4,3,3553;4,4,3553;4,5,3553;4,6,3553;4,7,3553;4,8,3553;4,9,3553;4,10,3553;4,11,3553;4,12,3553;4,13,3553;4,14,3553;4,15,3553 --service-request-channel-token=B4159222B33A81E05FA8E5FCC0D55014 --renderer-client-id=206 --mojo-platform-channel-handle=15120 /prefetch:1",
        "cpuLoad":  [
                        0.77543609036885053,
                        0.77622217609875555,
                        1.5360306588770334
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  20092,
        "parentProcessId":  12808,
        "commandLine":  "\\??\\C:\\windows\\system32\\conhost.exe 0x4",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  30312,
        "parentProcessId":  5932,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" \"c:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\\out\\bootstrap\" --type=terminal",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  23760,
        "parentProcessId":  23624,
        "commandLine":  "\"\\\\?\\c:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\\node_modules\\node-pty\\build\\Release\\winpty-agent.exe\" \\\\.\\pipe\\winpty-control-23624-1-1d369ba889cc9a4-100dce0b6ae359464fd72fac265b7503 0 1 250 31",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  13808,
        "parentProcessId":  16992,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" ",
        "cpuLoad":  [
                        0,
                        0,
                        0.38400766471925835
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  12808,
        "parentProcessId":  5932,
        "commandLine":  "\"c:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\\out\\vs\\workbench\\services\\files\\node\\watcher\\win32\\CodeHelper.exe\" p:\\mseng\\VSCode\\code-ps",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  23536,
        "parentProcessId":  5932,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" \"c:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\\out\\bootstrap\" --type=extensionHost",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  31932,
        "parentProcessId":  30312,
        "commandLine":  "\"\\\\?\\c:\\Program Files\\Microsoft VS Code Insiders\\resources\\app\\node_modules\\node-pty\\build\\Release\\winpty-agent.exe\" \\\\.\\pipe\\winpty-control-30312-1-1d369ba86f8a7ae-88ffa892054faab1f29beaf0c0a5aaf8 0 1 250 31",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    },
    {
        "type":  "processInfo",
        "processId":  21756,
        "parentProcessId":  2028,
        "commandLine":  "\"C:\\Program Files\\Microsoft VS Code Insiders\\Code - Insiders.exe\" --reporter-url=https://rink.hockeyapp.net/api/2/apps/0ac07349c6e34e978fdfb42074932f22/crashes/upload --application-name=VSCode \"--crashes-directory=C:\\Users\\dirkb\\AppData\\Local\\Temp\\VSCode Crashes\" --v=1",
        "cpuLoad":  [
                        0,
                        0,
                        0
                    ]
    }
]

I created a flat array. I thought it is easier to extend, but I can change the format. Each top level entry has a type property, describing the info in the literal:

  • machineInfo: information about the machine
  • machineState: information about the current machine state (it contains a cpuLoad property which is the percentage load of the machine
  • topProcess: a top process in terms of CPU consumption. Must not necessarily be a code process or one of its sub processes.
  • processInfo: a code process or one of its sub processes.

Both topProcess and processInfo have a cpuLoad property. The property is an array. Each element is a % load value computed for 1 second. By default the script does 10 such samples. This gives an indication if the process is for example in an endless loop if these values are constant.

Let me know if you need more information. I can basically add whatever is necessary now that I understand how to do this in PowerShell. As said I can also change the format.

Side note: I fought quite some time with hashtables in PowerShell. The key is type and if for example the key value you use is a double and the you try hashtable[4] you get nothing. You need to do hashtable[[double]4] :-). Although PowerShell doesn't really type everything needs to have a type and there is no auto conversion

@weinand
Copy link
Contributor

weinand commented Nov 30, 2017

And this runs quickly and can be called every second without signification cpu load, correct?

If yes, could you try to integrate this into ps.ts and create a PR?
Alternatively if you are running out of time you can attach the PS script and a simple JS/TS snippet for how to run this on Windows here. I will integrate this into ps.ts.

@dbaeumer
Copy link
Member Author

Here is a doc page of the process attributes available in Windows: https://msdn.microsoft.com/en-us/library/aa394372(v=vs.85).aspx

@dbaeumer
Copy link
Member Author

I can check in the script. However running this every second might not work. The reason is that Get-Counter has a minimum sample length of 1 second. This is why the script basically does the sampling already. Why would we want to run this every second? To get the process tree. If this is what we need then I would factor that into another script since it is much easier to compute.

@weinand
Copy link
Contributor

weinand commented Nov 30, 2017

Yes, to get a "live" tree where new processes show up immediately we currently poll.
If your script can do better without polling (e.g. by sending deltas automatically), we could consider this too.

@dbaeumer
Copy link
Member Author

I have checked code-ps.ps1 into our git repository. It is alongside the cli.ts.

@bpasero
Copy link
Member

bpasero commented Dec 1, 2017

Based on feedback from @egamma I renamed the startup argument to "-s, --status" because it shows more than just process info now.

@weinand
Copy link
Contributor

weinand commented Dec 4, 2017

The "vscode-processes" extension (which uses a copy of https://github.com/Microsoft/vscode/blob/master/src/vs/base/node/ps.ts) lives here: https://github.com/weinand/vscode-processes

@bpasero
Copy link
Member

bpasero commented Dec 4, 2017

@dbaeumer are you planning to provide windows support for CPU/Memory? I think that would be the only thing left to do here.

@dbaeumer
Copy link
Member Author

dbaeumer commented Dec 4, 2017

@bpasero will see what I can do today / this week. Just for checking. Will it be called once or in an interval to feed @weinand process view ?

@bpasero
Copy link
Member

bpasero commented Dec 4, 2017

@dbaeumer just once from here

@dbaeumer
Copy link
Member Author

dbaeumer commented Dec 4, 2017

OK. Will have a look then.

@dbaeumer dbaeumer closed this as completed Dec 4, 2017
@dbaeumer dbaeumer reopened this Dec 4, 2017
@dbaeumer
Copy link
Member Author

dbaeumer commented Dec 4, 2017

@bpasero qq: you pass a root PID. This will not catch any orphaned or leaking code processes.

My current script takes whether we want to capture code or code-insiders. How would I get to that info in https://github.com/Microsoft/vscode/blob/master/src\vs\base\node\ps.ts#L21

@weinand weinand removed their assignment Dec 4, 2017
@dbaeumer
Copy link
Member Author

dbaeumer commented Dec 4, 2017

Windows output:

Version: code-oss-dev 1.19.0 (Commit unknown, Date unknown)
OS Version: Windows_NT x64 10.0.16299)
CPUs: Intel(R) Core(TM) i7-6600U CPU @ 2.60GHz (4 x 2808)
Memory (System): 15.93GB (6.84GB free)
VM: 0%
Screen Reader: no

CPU %   Mem MB  Process
    3       75  code-oss main
    4      134     window (Untitled-1 - Code - OSS Dev)
    0       27       extensionHost
    2       91     gpu-process
    0       51     shared-process

@dbaeumer
Copy link
Member Author

dbaeumer commented Dec 4, 2017

@weinand some notes:

My proposal would be to report mem usage in total byes from ps.ts and do the calculation for Linux / Mac there.

@dbaeumer
Copy link
Member Author

dbaeumer commented Dec 4, 2017

And would be cool if I could return more than the root process. I am for example collecting the 5 top processes as well in terms of CPU load. Might give an indication that something is busy outside VS Code. In additional I collect orphaned code processes. So if VS Code crashes and leaves an orphaned extension host behind you will see that.

dbaeumer added a commit that referenced this issue Dec 4, 2017
@bpasero
Copy link
Member

bpasero commented Dec 4, 2017

Thanks. I am not sure we can track the process usage on Linux/macOS using PS but I let @weinand comment on that.

I suggest we close this issue and continue in individual more fine grained issues.

@dbaeumer if you want to capture your suggestions into issues, there is a workbench-diagnostics label that I added that can be used.

@bpasero bpasero closed this as completed Dec 4, 2017
@bpasero bpasero added feature-request Request for new features or functionality on-testplan labels Dec 4, 2017
@weinand
Copy link
Contributor

weinand commented Dec 4, 2017

@bpasero what do you mean by "process usage"?

@bpasero
Copy link
Member

bpasero commented Dec 4, 2017

@weinand

the mem usage under Windows is reported in total bytes not as a percentage. I use the same mem slot for now and do the right thing in https://github.com/Microsoft/vscode/blob/master/src\vs\code\electron-main\diagnostics.ts#L147
My proposal would be to report mem usage in total byes from ps.ts and do the calculation for Linux / Mac there.

@weinand
Copy link
Contributor

weinand commented Dec 4, 2017

Aha, you meant "mem usage". I can look into this (but not for this milestone).

@bpasero
Copy link
Member

bpasero commented Dec 4, 2017

@weinand thanks!

@vscodebot vscodebot bot locked and limited conversation to collaborators Jan 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
feature-request Request for new features or functionality on-testplan workbench-diagnostics General VS Code built-in diagnostic issues
Projects
None yet
Development

No branches or pull requests

4 participants