Skip to content

Performance is ~2x slower than satellite.js #31

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

Open
1valdis opened this issue Aug 24, 2024 · 1 comment
Open

Performance is ~2x slower than satellite.js #31

1valdis opened this issue Aug 24, 2024 · 1 comment
Assignees
Labels
enhancement New feature or request

Comments

@1valdis
Copy link

1valdis commented Aug 24, 2024

Describe the bug
From my local comparison, equal calculations of position using ootk vs satellite.js are ~2x slower on ootk.

To Reproduce
Preparation code on ootk:

import * as ootk from 'ootk'
import * as satellite from 'satellite.js'
const { degreesToRadians } = satellite; // the only thing needed from satellite.js
const TLE: Array<[string, string, string]> = []; // here, each item is 3 strings of a three-line element set
const satellites = TLE
  .map((tle) => {
    const name = tle[0].slice(2)
    return new ootk.Satellite({ name, tle1: tle[1] as ootk.TleLine1, tle2: tle[2] as ootk.TleLine2 })
  })
  .filter(sat=> sat.satrec.error === 0)
// tried to get the least restrictive min/max values here to not filter satellites at all
const sensor = new ootk.Sensor({
  alt: location.altitude as ootk.Kilometers,
  lat: location.latitude as ootk.Degrees,
  lon: location.longitude as ootk.Degrees,
  maxAz: 360 as ootk.Degrees,
  maxEl: 180 as ootk.Degrees,
  maxRng: Infinity as ootk.Kilometers,
  minAz: 0 as ootk.Degrees,
  minEl: 0 as ootk.Degrees,
  minRng: 0 as ootk.Kilometers,
})

Code to measure using ootk:

const positions = satellites.map((satellite) => {
  const rae = sensor.rae(satellite, date)
  return {
    norad: satellite.satrec.satnum,
    azEl: [degreesToRadians(rae.az), degreesToRadians(rae.el)]
  }
})

Preparation code on satellite.js:

import * as satellite from 'satellite.js'
const TLE: Array<[string, string, string]> = []; // here, each item is 3 strings of a three-line element set as above
const satRecs = TLE
  .map(tle => satellite.twoline2satrec(tle[1], tle[2]))
  .filter(satRec => satRec.error === 0)
const gmst = satellite.gstime(date)
const locationForLib = {
  longitude: satellite.degreesToRadians(location.longitude),
  latitude: satellite.degreesToRadians(location.latitude),
  height: location.altitude / 1000
}

Code to measure using satellite.js

const positions = satRecs.
  map((satRec) => {
    const positionEci = satellite.propagate(satRec, date)
    if (typeof positionEci.position !== 'object') {
      return {
        azEl: null
        norad: satRec.satnum
      }
    }
    const positionEcf = satellite.eciToEcf(positionEci.position as satellite.EciVec3<number>, gmst)
    const lookAngles = satellite.ecfToLookAngles(locationForLib, positionEcf)
    return {
      norad: satRec.satnum,
      azEl: [lookAngles.azimuth, lookAngles.elevation]
    }
  })
  .filter(position => position.azEl)

With full space-track database, takes about 150-160 ms on ootk vs 80 ms on satellite.js on my machine.

Expected behavior
Performance is about the same or even better, considering less function calls from client code for ootk.

Desktop (please complete the following information):

  • OS: Windows 10
  • Browser: Chrome
  • Version: 127
@thkruz thkruz self-assigned this Sep 7, 2024
@thkruz thkruz added the enhancement New feature or request label Sep 7, 2024
@thkruz
Copy link
Owner

thkruz commented Mar 20, 2025

I finally had some time to work on this. There were a few causes of the difference:

A slow caching process that I removed (see thkruz/ootk-core@d147d0c). Once I removed this, I went from 185ms for my propagation loop to 120ms.

Pure JavaScript functions vs TypeScript classes. Depending on how you transpile the code into JavaScript might impact how well the JavaScript engine caches reused functions like dpper and dspace.

I tried converting everything into functions instead of classes and didn't see any noticeable change in performance, so I reverted back for now.

The other slow thing was the recalculation of date variables (like gmst) in the Satellite object's methods. You were calculating that once with satellite.js and then reusing it for every satellite. For ootk you were recalculating it for each satellite. I updated it so you can pass j and gmst into methods like eci and skip the calculations. For users working with one satellite it will still calculate those variables automatically, but for users working with the whole catalog you can focus on performance.

I don't think your premise that it should be faster because there is less function calls from client code really makes sense. You were definitely right that there were performance issues, but there are a huge number of calculations that must happen no matter how much the user actually types. My intent is to minimize how much the user has to type - its still almost the same math.

If you are still interested, take a look and see if this is closer to what you were expecting performance wise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants