1

does someone know why function 1 takes longer to finish than function 2 even though function 1 is multithreaded and should use the system resources better than function 2? I really have no idea if and where I made a mistake while implementing multiprocessing.

Function 1:

def encrypt(message, keyname="publicKey.rsa"):
"""
Encrypts or decrypts a hex message.
:param message: Must be a hexadecimal number. Example: 3e40f3ad, not: 0x3e40f3ad
:param keyname: Must be the name of the keyfile in the RSA-420 path.
:return: Returns encrypted or decrypted hexadecimal string (Example: "4723d8ea") with spaces as block splitters.
"""
crypted = ""
key = readkey(keyname)
exp, mod = format(int(key[0], 16), "x"), format(int(key[1], 16), "x")
blocklength = len(mod) - 1
blockcount = int(math.ceil(len(message)/blocklength))
results = []
pool = tp(processes=6)
for i in range(blockcount-1):
    results.append(None)
for i in range(blockcount-1):
    part = message[i*blocklength:((i+1)*blocklength)]
    res = pool.apply_async(crypt, args=(int(part, 16), int(exp, 16), int(mod, 16)))
    results[i] = res.get()
for i in range(len(results)):
    crypted += format(results[i], "x") + " "
i = blockcount-1
part = message[i*blocklength:((i+1)*blocklength)]
lastlen = len(part)
crypted += format(pow(int(part, 16), int(exp, 16), int(mod, 16)), "x") + " "
return crypted + str(blocklength) + " " + str(lastlen)

Function 2:

def encryptold(message, keyname="publicKey.rsa"):
"""
Encrypts or decrypts a hex message.
:param message: Must be a hexadecimal number. Example: 3e40f3ad, not: 0x3e40f3ad
:param keyname: Must be the name of the keyfile in the RSA-420 path.
:return: Returns encrypted or decrypted hexadecimal string (Example: "4723d8ea") with spaces as block splitters.
"""
crypted = ""
key = readkey(keyname)
exp, mod = format(int(key[0], 16), "x"), format(int(key[1], 16), "x")
blocklength = len(mod) - 1
blockcount = math.ceil(len(message)/blocklength)
for i in range(blockcount-1):
    part = message[i*blocklength:((i+1)*blocklength)]
    crypted += format(pow(int(part, 16), int(exp, 16), int(mod, 16)), "x") + " "
i = blockcount-1
part = message[i*blocklength:((i+1)*blocklength)]
lastlen = len(part)
crypted += format(pow(int(part, 16), int(exp, 16), int(mod, 16)), "x") + " "
return crypted + str(blocklength) + " " + str(lastlen)

I tested encrypting a 206kB file with both codes and the multithreaded one is always a good 3% slower even though it should be closer to 600% faster due to my system having 6 physical cores.

Thanks for helping in advance!

  • 1
    What Python interpreter are you using? With a CPython implementation, CPU-bound applications don't benefit from multiple threads because of the Global Interpreter Lock (GIL). – Daniel Pryden Dec 02 '18 at 12:49
  • 1
    Possible duplicate of [What is the global interpreter lock (GIL) in CPython?](https://stackoverflow.com/questions/1294382/what-is-the-global-interpreter-lock-gil-in-cpython) – Daniel Pryden Dec 02 '18 at 12:52
  • @DanielPryden Thank you! So this means that in order to take advantage of multiprocessing, I'll have to execute the code in a JPython interpreter? – halbGefressen Dec 02 '18 at 13:37
  • I would recommend trying [PyPy](https://pypy.org/) first. Alternatively, consider using the `multiprocessing` module instead of multiple threads. That would avoid the GIL by using multiple interpreter processes, each with their own "global" lock. – Daniel Pryden Dec 02 '18 at 22:00

0 Answers0