Please help to optimize my python code, I wrote this JS code and tried to convert it to python that I need the execution time comparable to the original code.
The original code follows for-loop in JS, I transferred the code literally by using pure python and numpy but I didn’t optimize it well resulting in poor execution time and memory usage.
This code calculates a preset enemy vs player power with +-10% difference and do a random roll then get the player winrate. The target is to set the HERO_POWER or ENEMY_POWER atleast in 100000-300000 range.
JavaScript
x
83
83
1
'''
2
##winchance.js##
3
Original code
4
5
var h = 0
6
var g = 0
7
var i = char_power
8
var l = i*.9
9
var u = enemy_power * 1.1
10
var d = enemy_power * .9
11
for (let e = Math.floor(l); e <= i; e++)
12
for (let t = Math.floor(d); t <= u; t++) e >= t ? h++ : g++
13
var z = h / (h + g)*100;
14
return z
15
}
16
var out = combat_simulate(parseInt(arguments[2]),parseInt(arguments[3]))
17
console.log(out)
18
'''
19
20
import subprocess,itertools,math
21
import numpy as np
22
23
def calc_iter(array):
24
w=0
25
l=0
26
for x,y in array:
27
if x >= y:
28
w +=1
29
else:
30
l +=1
31
return w,l
32
33
###inputs###
34
HERO_POWER=120000
35
ENEMY_POWER=110000
36
37
w=0
38
l=0
39
h_l = HERO_POWER * .9
40
e_h = ENEMY_POWER * 1.1
41
e_l = ENEMY_POWER * .9
42
hp = np.arange(math.floor(h_l),math.floor(HERO_POWER))
43
ep = np.arange(math.floor(e_l),math.floor(e_h))
44
45
46
print('process using itertools')
47
start_time = time.time()
48
array = itertools.product(hp,ep)
49
w,l = calc_iter(array)
50
print('win rate:{}%'.format(round((w/(w+l))*100,2)))
51
end_time = time.time()
52
print('time elapsed',end_time-start_time)
53
54
print()
55
print('process using numpy')
56
start_time = time.time()
57
x,y = np.meshgrid(hp,ep)
58
n = x>y
59
w,l = (np.count_nonzero(n),np.count_nonzero(n==0))
60
print('win rate:{}%'.format(round((w/(w+l))*100,2)))
61
end_time = time.time()
62
print('time elapsed',end_time-start_time)
63
64
print()
65
print('process using nodejs')
66
start_time = time.time()
67
result = subprocess.run('node winchance.js {} {}'.format(HERO_POWER,ENEMY_POWER),capture_output=True,text=True)
68
print('win rate:{}%'.format(round(float(result.stdout),2)))
69
end_time = time.time()
70
print('time elapsed',end_time-start_time)
71
########################################
72
process using itertools
73
win rate:68.18%
74
time elapsed 30.484147787094116
75
76
process using numpy
77
win rate:68.18%
78
time elapsed 2.0294463634490967
79
80
process using nodejs
81
win rate:68.18%
82
time elapsed 0.799668550491333
83
Advertisement
Answer
upon searching the web, I tried to translate the python function code using ‘numba’ and it shows faster execution with no additional thing to do on my end in this context.
JavaScript
1
59
59
1
import math
2
import numpy as np
3
import time
4
import subprocess
5
import os
6
from numba import njit
7
8
hero_power_list = [120000,130000,140000]
9
enemy_power_list = [110000,121000,131000]
10
11
@njit
12
def calc_iter_1(array1,array2):
13
w=0
14
l=0
15
for x in array1:
16
for y in array2:
17
if x >= y:
18
w +=1
19
else:
20
l +=1
21
return w,l
22
23
24
print('process using numba')
25
for x in range(len(hero_power_list)):
26
h_l = hero_power_list[x] * .9
27
e_h = enemy_power_list[x] * 1.1
28
e_l = enemy_power_list[x] * .9
29
hp = np.arange(math.floor(h_l),math.floor(hero_power_list[x]))
30
ep = np.arange(math.floor(e_l),math.floor(e_h))
31
32
start_time = time.perf_counter()
33
w,l = calc_iter_1(hp,ep)
34
# print('win rate:{}%'.format(round((w/(w+l))*100,2)))
35
end_time = time.perf_counter()
36
print('time elapsed:',round(end_time-start_time,2),'sec(s)')
37
38
39
print()
40
print('process using nodejs')
41
for x in range(len(hero_power_list)):
42
HERO_POWER = hero_power_list[x]
43
ENEMY_POWER = enemy_power_list[x]
44
start_time = time.perf_counter()
45
result = subprocess.run('node winchance.js {} {}'.format(HERO_POWER,ENEMY_POWER),capture_output=True,text=True)
46
# print('win rate:{}%'.format(round(float(result.stdout),2)))
47
end_time = time.perf_counter()
48
print('time elapsed:',round(end_time-start_time,2),'sec(s)')
49
########################################
50
process using numba
51
time elapsed: 0.87 sec(s)
52
time elapsed: 0.43 sec(s)
53
time elapsed: 0.52 sec(s)
54
55
process using nodejs
56
time elapsed: 0.81 sec(s)
57
time elapsed: 1.07 sec(s)
58
time elapsed: 1.1 sec(s)
59