0

I'm trying to accomplish a CodeWars challenge for the lulz, but I can't seem to get it performant enough to pass submission. The solution is correct and passes all the tests, but it fails the performance test, taking > 120000 ms

MY 2 QUESTIONS FOR YOU

  1. How does someone debug performance issues? I don't know how to begin to debug performance and identify nonperformant code, or how to optimize code intentionally

  2. What is the issue with this specific code? Is there a pattern that I'm executing incorrectly? Are there some parts of the code that are happening too many times?

detailed requirements can be found here: https://www.codewars.com/kata/integers-recreation-one ```

//generate an array of range, containing every number M to N
//map1: for each  number find all divisors
//map2: for each array of divisors, format answer for tests
//filter out undefined results
let listSquared = (m, n) => range(m,n)
    .map(nextNumberInRange => findDivisors(nextNumberInRange))
    .map(arrayOfDivisors => formatAnswer(
            arrayOfDivisors[arrayOfDivisors.length - 1],
            squareAndSumAll(arrayOfDivisors)))
    .filter(x => x !== undefined)


//if the square root of y (the sum of squared divisors) is WHOLE, return [x,y]
let formatAnswer = (x,y) => Math.sqrt(y) % 1 === 0 ? [x,y] : undefined
//find all divisors of any integer
let findDivisors = (x) => range(1,x).filter(y => x%y === 0 || y===x)
//generate an array containing values from start to end.
//e.g. 100-500, 351-293487 etc. 
let range = (start,end) => [...Array((end-start)+1)].map((x,i)=> start+i)


let squareAndSumAll = (x) => x.map(square).reduce(add)
let add = (x,y) => x + y
let square = (x) => x * x

detailed requirements can be found here: https://www.codewars.com/kata/integers-recreation-one

You should be able to slap the code into the window on their website and recreate the passing input and failing timer tests.

nathan rogers
  • 189
  • 5
  • 19

2 Answers2

0
  1. To debug performance issues, you use a profiler. It will help you identify the parts of the code that are taking the most time, so you can try to improve them. Most browsers have a built-in profiler in the Developer Tools.

  2. You have lots of loops in your code, try to find a way to avoid them. In particular, you're calling findDivisors() frequently, and it has to loop over a large range. If you're calling it repeatedly for the same numbers, memoization can avoid much of that.

Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Fastest way of looping is old ugly for loop. Actually it's seams that while loop can be even faster then for loop. you can check more about loop performance on this discussion What's the fastest way to loop through an array in JavaScript?

The trick to make it even faster is to reduce number of loops. every call to map, reduce, filter and there is lot of those calls in your code is just nicer slower version of for loop.

  • 4 maps calls, 1 reduce, 2 filter (total 7 looping) my first bet would be to reduce number of looping. Perform multiple operations on 1 loop cycle.

You should see lot of benefit just by removing range call and .filter from findDivisor and update find divisor to use for (let i = 1; i <= x; i++)

snovakovic
  • 314
  • 1
  • 8