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

CLI: parallelize mfkey32v2 processes #187

Merged
merged 2 commits into from
Dec 20, 2023

Conversation

p-l-
Copy link
Contributor

@p-l- p-l- commented Dec 9, 2023

This PR will run as many mfkey32v2 processes in parallel than the host CPUs count. It makes the hf mf elog --decrypt command much faster.

Copy link

github-actions bot commented Dec 9, 2023

You are welcome to add an entry to the CHANGELOG.md as well

Copy link

github-actions bot commented Dec 9, 2023

Built artifacts for commit cc674f1

Firmware

Client

@p-l- p-l- force-pushed the enh-hf-mf-elog-parallel branch 2 times, most recently from 09d0174 to 02165a0 Compare December 9, 2023 19:21
@p-l- p-l- marked this pull request as ready for review December 9, 2023 19:25
items[1]["nt"],
items[1]["nr"],
items[1]["ar"],
],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally needed to add shell=True in the subprocess.run() args
Running this one a windows machine, not sure how this will affect a different OS

Suggested change
],
],
shell=True,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Can you confirm that with this patch you needed to add shell=True? With the exact same command, without changing anything else?
That's very surprising to me! Could you share the output without adding shell=True?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! Here it is without shell=True

multiprocessing.pool.RemoteTraceback:
"""
Traceback (most recent call last):
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/mingw64/lib/python3.11/multiprocessing/pool.py", line 125, in worker
    result = (True, func(*args, **kwds))
                    ^^^^^^^^^^^^^^^^^^^
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/home/USER/ChameleonUltra/software/script/chameleon_cli_unit.py", line 1030, in _run_mfkey32v2
    output_str = subprocess.run(
                 ^^^^^^^^^^^^^^^
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/mingw64/lib/python3.11/subprocess.py", line 548, in run
    with Popen(*popenargs, **kwargs) as process:
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/mingw64/lib/python3.11/subprocess.py", line 1026, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/mingw64/lib/python3.11/subprocess.py", line 1538, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [WinError 2] The system cannot find the file specified
"""

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/home/USER/ChameleonUltra/software/script/chameleon_cli_main.py", line 144, in exec_cmd
    raise error
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/home/USER/ChameleonUltra/software/script/chameleon_cli_main.py", line 139, in exec_cmd
    unit.on_exec(args_parse_result)
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/home/USER/ChameleonUltra/software/script/chameleon_cli_unit.py", line 1137, in on_exec
    result_maps[uid][block]['A'] = self.decrypt_by_list(records)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/home/USER/ChameleonUltra/software/script/chameleon_cli_unit.py", line 1076, in decrypt_by_list
    for key in pool.imap(
  File "C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/mingw64/lib/python3.11/multiprocessing/pool.py", line 873, in next
    raise value
FileNotFoundError: [WinError 2] The system cannot find the file specified

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh OK, I'm having a look. Thanks for your answer!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try if it if fixed @MrFlou?

@@ -1029,7 +1029,7 @@ def res_value(self, src_blk, src_type, src_key, dst_blk, dst_type, dst_key):
def _run_mfkey32v2(items):
output_str = subprocess.run(
[
"mfkey32v2.exe" if sys.platform == "win32" else "./mfkey32v2",
".\\mfkey32v2.exe" if sys.platform == "win32" else "./mfkey32v2",
Copy link

@MrFlou MrFlou Dec 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tried following the changes you did and got this working.

Suggested change
".\\mfkey32v2.exe" if sys.platform == "win32" else "./mfkey32v2",
"./bin/mfkey32v2.exe" if sys.platform == "win32" else "./mfkey32v2",

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is really weird, I don't understand...
Can you add a print(default_cwd) just after the default_cwd = definition (line 41), then run the CLI and report the path displayed? On Linux I get /home/user/Github/RfidResearchGroup/ChameleonUltra/software/script/bin. I expect you'd get something similar under Windows, but based on your suggestion it seems you won't have the bin final directory?

Copy link

@MrFlou MrFlou Dec 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C:/Users/USER/Desktop/Chamilion Ultra/CLI/ProxSpace/msys2/home/USER/ChameleonUltra/software/script/bin
I do have the bin. Could it be I'm running it with the ProxySpace guide?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK thanks a lot! I've tried something else, that should work in any environment. Can you check again?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@p-l- This works!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, appreciate your help! Did you notice a performance improvement?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, running much faster!

@p-l- p-l- force-pushed the enh-hf-mf-elog-parallel branch from 426dd30 to 9174b02 Compare December 18, 2023 08:26
@p-l-
Copy link
Contributor Author

p-l- commented Dec 19, 2023

Hello @xianglin1998 @doegox sorry for the ping. This PR has now been tested on both Windows (thanks @MrFlou) and Linux. Could you have a look? It really speeds up running hf mf elog --decrypt.

CHANGELOG.md Outdated
@@ -26,6 +26,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added support for timestamped comments in CLI via `rem`, `;`, `%` or `#` (@doegox)
- Fixed watchdog trigger during `hw factory_reset` (@doegox)
- Added PyInstaller support for CLI client (@augustozanellato)
- Parallelize mfkey32v2 processes called from CLI (@p-l-)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new changelog entries should be moved to the top of the list

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, makes sense, sorry. That's done!

@p-l- p-l- force-pushed the enh-hf-mf-elog-parallel branch from 9174b02 to cc674f1 Compare December 20, 2023 15:20
@doegox
Copy link
Contributor

doegox commented Dec 20, 2023

Thanks! you know you don't need to rewrite and force-push commits, you can just add a commit in your branch and it'll be added to the existing PR.

@doegox doegox merged commit 0124709 into RfidResearchGroup:main Dec 20, 2023
8 checks passed
@p-l- p-l- deleted the enh-hf-mf-elog-parallel branch December 20, 2023 15:30
p-l- added a commit to p-l-/ChameleonUltra that referenced this pull request Dec 20, 2023
This (often largely) improves the speed of the decrypt process. On my
laptop, with the same logs (37 records for one block and 37 records
for another block), here are the performances, as measuerd using a
simple command:

```bash
time echo -e "hw connect\nhf mf elog --decrypt\nhw disconnect" | ./chameleon_cli_main.py
```

- Before parallelisation (RfidResearchGroup#187): 14m59,277s
- With parallelisation (current main): 6m13,513s
- With item skipping (this PR): 2m42,491s
@p-l-
Copy link
Contributor Author

p-l- commented Dec 21, 2023

Thanks @doegox. Actually I just amended the commit (hence the push force), I did not rewrite the PR!

@doegox
Copy link
Contributor

doegox commented Dec 21, 2023

You don't need to rewrite a PR.
You don't need to amend a commit and force-push it.
You can just push a new commit in your existing branch and it will automatically appear in the existing PR.
That way, it's easier for reviewers to know what you changed after the reviewers comments. But if you amend the commit, then we've to read it all again and try to spot what you changed.

Not an issue here as it was just the changelog but this workflow may help in future commits.
Thanks!

@p-l-
Copy link
Contributor Author

p-l- commented Dec 21, 2023

OK noted.

As a maintainer I use the link "force-pushed" in the message (@p-l- force-pushed the enh-hf-mf-elog-parallel branch from 9174b02 to cc674f1), but that's totally OK for me to add new commits, I'll do that for my future PRs to this project.

Thanks for the work & the super cool project BTW!

@doegox
Copy link
Contributor

doegox commented Dec 21, 2023

oh I didn't know that force-pushed link, thanks !

p-l- added a commit to p-l-/ChameleonUltra that referenced this pull request Dec 21, 2023
It is done by adding a "server" mode (on STDIN/STDOUT) to `mfkey32v2`
using `--server`.

This improves the speed of the decrypt process, as it prevents a lot
of Python calls to `subprocess.Popen()` (and of course, a lot of
fork/execve syscalls).

On my laptop, with the same logs (37 records for one block and 37
records for another block), here are the performances, as measuerd
using a simple command:

```bash
time echo -e "hw connect\nhf mf elog --decrypt\nhw disconnect" | ./chameleon_cli_main.py
```

|                           |         | real       | user       | sys       |
|---------------------------|---------|------------|------------|-----------|
| Before parallelisation    | 05ea03d | 14m59,277s | 14m47,995s | 0m8,490s  |
| With parallelisation      | RfidResearchGroup#187    | 6m13,513s  | 35m2,926s  | 0m22,038s |
| With item skipping        | RfidResearchGroup#189    | 2m42,491s  | 15m43,425s | 0m9,881s  |
| With `mfkey32v2 --server` | this PR | 1m55,160s  | 0m1,315s   | 0m0,250s  |
p-l- added a commit to p-l-/ChameleonUltra that referenced this pull request Dec 31, 2023
It is done by adding a "server" mode (on STDIN/STDOUT) to `mfkey32v2`
using `--server`.

This improves the speed of the decrypt process, as it prevents a lot
of Python calls to `subprocess.Popen()` (and of course, a lot of
fork/execve syscalls).

On my laptop, with the same logs (37 records for one block and 37
records for another block), here are the performances, as measuerd
using a simple command:

```bash
time echo -e "hw connect\nhf mf elog --decrypt\nhw disconnect" | ./chameleon_cli_main.py
```

|                           |         | real       | user       | sys       |
|---------------------------|---------|------------|------------|-----------|
| Before parallelisation    | 05ea03d | 14m59,277s | 14m47,995s | 0m8,490s  |
| With parallelisation      | RfidResearchGroup#187    | 6m13,513s  | 35m2,926s  | 0m22,038s |
| With item skipping        | RfidResearchGroup#189    | 2m42,491s  | 15m43,425s | 0m9,881s  |
| With `mfkey32v2 --server` | this PR | 1m55,160s  | 0m1,315s   | 0m0,250s  |
p-l- added a commit to p-l-/ChameleonUltra that referenced this pull request Aug 20, 2024
It is done by adding a "server" mode (on STDIN/STDOUT) to `mfkey32v2`
using `--server`.

This improves the speed of the decrypt process, as it prevents a lot
of Python calls to `subprocess.Popen()` (and of course, a lot of
fork/execve syscalls).

On my laptop, with the same logs (37 records for one block and 37
records for another block), here are the performances, as measuerd
using a simple command:

```bash
time echo -e "hw connect\nhf mf elog --decrypt\nhw disconnect" | ./chameleon_cli_main.py
```

|                           |         | real       | user       | sys       |
|---------------------------|---------|------------|------------|-----------|
| Before parallelisation    | 05ea03d | 14m59,277s | 14m47,995s | 0m8,490s  |
| With parallelisation      | RfidResearchGroup#187    | 6m13,513s  | 35m2,926s  | 0m22,038s |
| With item skipping        | RfidResearchGroup#189    | 2m42,491s  | 15m43,425s | 0m9,881s  |
| With `mfkey32v2 --server` | this PR | 1m55,160s  | 0m1,315s   | 0m0,250s  |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants