I tried solving Maximum Subarray using both Javascript(Node.js) and Python, with brute force algorithm. Here's my code:
Using python:
from datetime import datetime
from random import randint
arr = [randint(-1000,1000) for i in range(1000)]
def bruteForce(a):
l = len(a)
max = 0
for i in range(l):
sum = 0
for j in range(i, l):
sum += a[j]
if(sum > max):
max = sum
return max
start = datetime.now()
bruteForce(arr)
end = datetime.now()
print(format(end-start))
And Javascript:
function randInt(start, end) {
return Math.floor(Math.random() * (end - start + 1))
}
var arr = Array(1000).fill(randInt(-1000, 1000))
function bruteForce(arr) {
var max = 0
for (let i = 0; i < arr.length; i++) {
var sum = 0
for (let j = i; j < arr.length; j++) {
sum += arr[j]
max = Math.max(max, sum)
}
}
return max
}
var start = performance.now()
bruteForce(arr)
var end = performance.now()
console.log(end - start)
Javascript got a result of about 0.187 seconds, while python got 4.75s - about 25 times slower. Does my code not optimized or python is really that slower than javascript?
I tried solving Maximum Subarray using both Javascript(Node.js) and Python, with brute force algorithm. Here's my code:
Using python:
from datetime import datetime
from random import randint
arr = [randint(-1000,1000) for i in range(1000)]
def bruteForce(a):
l = len(a)
max = 0
for i in range(l):
sum = 0
for j in range(i, l):
sum += a[j]
if(sum > max):
max = sum
return max
start = datetime.now()
bruteForce(arr)
end = datetime.now()
print(format(end-start))
And Javascript:
function randInt(start, end) {
return Math.floor(Math.random() * (end - start + 1))
}
var arr = Array(1000).fill(randInt(-1000, 1000))
function bruteForce(arr) {
var max = 0
for (let i = 0; i < arr.length; i++) {
var sum = 0
for (let j = i; j < arr.length; j++) {
sum += arr[j]
max = Math.max(max, sum)
}
}
return max
}
var start = performance.now()
bruteForce(arr)
var end = performance.now()
console.log(end - start)
Javascript got a result of about 0.187 seconds, while python got 4.75s - about 25 times slower. Does my code not optimized or python is really that slower than javascript?
Share Improve this question asked Mar 30, 2022 at 14:26 Trung KiênTrung Kiên 1851 gold badge2 silver badges10 bronze badges 6- 3 properly structured JS is blisteringly fast when run in modern browsers. Perhaps one day just-in-time bytecode compilation by browsers will be efficiently applied to Python but it will have a lot of catching up to do. I once re-worked million-loop JS functions in C and the run times were very close - browsers are particularly efficient for processing repetitions such as loops where only one or two variable change. There's interesting background material here: hacks.mozilla.org/2017/02/… – Dave Pritlove Commented Mar 30, 2022 at 14:33
- 1 @general-grievance, what was the time for the JS? of course different user systems will vary, it's the comparison that matters. Would be interesting to see how different set ups compare. – Dave Pritlove Commented Mar 30, 2022 at 14:35
- 1 On my computer they both take approximately 0.3s – Achille G Commented Mar 30, 2022 at 14:41
- 2 @DavePritlove True. Testing on TIO: Python: ~0.1s, and JS 0.07-0.08 s after removing all the output code. So, slower, just not by a factor of 25. – General Grievance Commented Mar 30, 2022 at 14:42
- @general-grievance, yes, that's pretty close. Thanks. – Dave Pritlove Commented Mar 30, 2022 at 14:55
2 Answers
Reset to default 19Python is not per se slower than Javascript, it depends on the implementation. Here the results comparing node and PyPy which also uses JIT:
> /pypy39/python brute.py
109.8594 ms N= 10000 result= 73682
> node brute.js
167.4442000091076 ms N= 10000 result= 67495
So we could even say "python is somewhat faster" ... And if we use Cython, with a few type-hints, it will be again a lot faster - actual full C speed:
> cythonize -a -i brutec.pyx
> python -c "import brutec"
69.28919999999998 ms N= 10000 result= 52040
To make the comparison reasonable, I fixed a few issues in your scripts:
- Fix: the js script filled an array with all the same values from a single random
- Does the same basic kind of looping in Python - instead of using the range iterator (otherwise its a little slower)
- Use the same time format and increase the array length to 10000 - otherwise the times are too small regarding resolution and thread switching jitter
Python code:
from time import perf_counter as clock
from random import randint
N = 10000
arr = [randint(-1000,1000) for i in range(N)]
def bruteForce(a):
l = len(a)
max = 0
i = 0
while i < l:
sum = 0
j = i
while j < l:
sum += a[j]
if sum > max:
max = sum
j += 1
i += 1
return max
start = clock()
r = bruteForce(arr)
end = clock()
print((end - start) * 1000, 'ms', 'N=', N, 'result=', r)
##print(arr[:10])
JS code:
var start = -1000, end = 1000, N=10000
var arr = Array.from({length: N},
() => Math.floor(Math.random() * (end - start + 1) + start))
function bruteForce(arr) {
var max = 0
for (let i = 0; i < arr.length; i++) {
var sum = 0
for (let j = i; j < arr.length; j++) {
sum += arr[j];
max = Math.max(max, sum)
//~ if (sum > max) max = sum;
}
}
return max
}
var start = performance.now()
r = bruteForce(arr)
var end = performance.now()
console.log(end - start, 'ms', 'N=', N, 'result=', r)
//~ console.log(arr.slice(0, 10))
Code for Cython (or Python), enriched with a few type-hints:
import cython
from time import perf_counter as clock
from random import randint
N = 10000
arr = [randint(-1000,1000) for i in range(N)]
def bruteForce(arr):
l: cython.int = len(arr)
assert l <= 10000
a: cython.int[10000] = arr # copies mem from Python array
max: cython.int = 0
i: cython.int = 0
while i < l:
sum: cython.int = 0
j: cython.int = i
while j < l:
sum += a[j]
if sum > max:
max = sum
j += 1
i += 1
return max
start = clock()
r = bruteForce(arr)
end = clock()
print((end - start) * 1000, 'ms', 'N=', N, 'result=', r)
##print(arr[:10])
(Done on a slow notebook)
I also examined this, with JS and Python loop and pandas, JS is far better than Python looping and pandas.
My code:
JS:
// Create a large dataset
const NUM_RECORDS = 1000*10000
const people = Array.from({ length: NUM_RECORDS }, (_, i) => ({ name: `Person ${i}`, age: i % 100, gender: i % 2 === 0 ? 'male' : 'female' }));
// Define filter parameters
const ageThreshold = 35;
const gender = 'male';
// JavaScript filter method
const jsStartTime = Date.now();
const filteredPeopleJS = people.filter(person => person.age > ageThreshold && person.gender === gender);
const jsEndTime = Date.now();
const jsTimeTaken = (jsEndTime - jsStartTime) / 1000; // Convert milliseconds to seconds
console.log("JavaScript filter method time:", jsTimeTaken, "seconds");
Python code is:
import pandas as pd
import numpy as np
import time
NUM_RECORDS = 1000 * 10000
people = [{'name': f'Person {i}', 'age': i % 100, 'gender': 'male' if i % 2 == 0 else 'female'} for i in range(NUM_RECORDS)]
df = pd.DataFrame(people)
age_threshold = 35
gender = 'male'
python_start_time = time.time()
filtered_people_python = list(filter(lambda person: person['age'] > age_threshold and person['gender'] == gender, people))
python_end_time = time.time()
python_time_taken = python_end_time - python_start_time
pandas_start_time = time.time()
filtered_people_pandas = df[(df['age'] > age_threshold) & (df['gender'] == gender)]
pandas_end_time = time.time()
pandas_time_taken = pandas_end_time - pandas_start_time
print("Python filter time:", python_time_taken)
print("Pandas time:", pandas_time_taken)
RESULTS:
JavaScript filter method time: 0.121 seconds,
Python filter time: 0.7254292964935303,
Pandas time: 0.4761631488800049