Skip to content
Documentation · all sections

Performance

panchang-ts · v5.0.0 · MIT

Measured costs, the sections and computeEndTimes levers, process-wide caches, and the React Native / Hermes rendering pattern.

Measured at Pune on an Apple M-series laptop under Node, median of 11 processes per configuration. Treat them as relative guidance, not a spec — they move with hardware, latitude and date. Distinct days is the calendar-scan cost (every call misses the solar rise/set cache); same day repeated is what a UI that re-renders one date sees. The last column is the published 4.3.1 package, installed from npm and benchmarked beside v5.

getDailyPanchangDistinct daysSame day repeated4.3.1 (distinct)
Default (all sections + end-times)~0.41 ms~0.17 ms~6.06 ms
computeEndTimes: false~0.39 ms~0.15 ms~5.63 ms
Without 'festivals'~0.39 msn/a
sections: ['festivals', 'eclipse']~0.40 msn/a
sections: []~0.27 msn/a
sections: [] + computeEndTimes: false~0.25 ms~0.14 msn/a
getInstantPanchang~0.21 ms~0.10 ms~0.43 ms

A default day is ~15× cheaper than in 4.3.1, and a repeated day ~37×. Most of that is not tuning: 4.3.1 ran a full lunar theory inside the eclipse search on every day containing a syzygy, and had no cache that survived a call.

The two levers

Cost is dominated by ephemeris evaluations, so the lever that matters is the one that avoids them:

LeverWhat it doesWorth
sectionsskip the optional ephemeris-backed blocks you do not need~0.41 → ~0.27 ms when everything optional is off
computeEndTimes: falseskip transition searches — drops endTime fields, saves arithmetic, not ephemeris~5% cold, ~10% warm — use it to drop fields you do not want, not to go faster

Narrowing the work

PanchangSection lists the four optional blocks. Everything else a daily panchang returns — the five elements, slot systems, muhurtas, inauspicious periods, masa / samvat / rashi — is arithmetic over the sunrise / sunset / next-sunrise triplet and is always computed, because skipping it would save nothing.

SectionCoversFields when omitted
'festivals'festival detection — needs the prior day, canonical-time anchors, next-day transitfestivals: [] — but an eclipse entry is still prepended when 'eclipse' is on
'eclipse'eclipse overlapping the Hindu dayeclipse: null
'moonTimes'moon.rise / moon.setnull
'lunarWindows'Bhadra, Varjyam, Panchaka-Rahita — each binary-searches lunar longitude across the daynull / []
// Everything (default).
getDailyPanchang(date, loc, { timezone: 330 });

// Festivals only — no moon times, no Bhadra/Varjyam windows.
getDailyPanchang(date, loc, {
  timezone: 330,
  sections: ['festivals', 'eclipse'],
});

// Cheapest useful call: elements, slots, muhurtas and inauspicious periods
// only. Those are arithmetic on the sunrise triplet and are always computed.
getDailyPanchang(date, loc, {
  timezone: 330,
  sections: [],
  computeEndTimes: false,
});

Caches and the range helpers

Repeated calls for the same location-day are cheaper because solar rise/set events are cached process-wide, keyed on (direction, lat, lon, elevation, UTC day) and bounded at 20,000 entries. The cache also makes sunrise single-valued — two calls for the same day agree exactly.

Range helpers apply the same narrowing internally: computeEkadashiDatesForYear reads only the tithi at sunrise (~18 ms for a full year, against ~2,360 ms in 4.3.1); computeFestivalsInRange keeps only 'festivals' and 'eclipse' (~131 ms/year, against ~2,180); computeSankrantisForYear scans one solar longitude per day and bisects the 12 transits (~3.3 ms/year, against ~154).

Where v5 is slower — and why

The own-ephemeris series keep roughly three times the old accuracy against JPL DE441, and evaluation is sine-bound, so more terms cost proportionally more:

Surfacev5 vs 4.3.1Context
getSiderealSunLongitude / getSiderealMoonLongitude~2× per raw callevery documented workflow amortizes these through caches and is faster overall; visible only in tight loops over distinct instants — prefer the range APIs there
computeRashiChart / computeNavamsa~0.32 ms vs ~0.10 msa chart is fifteen full-accuracy planet evaluations; the price of Mercury 6.50″ → 0.30″ against DE441
computeShadbala / computeBhavaBala~2× fasterv5 computes the positions once and reuses them (~0.33 ms vs ~0.72)

React Native / Hermes

Works with Expo and bare React Native (Hermes engine). Pass timezone as a number — IANA strings need Intl, which older Hermes versions lack. Two-pass rendering pattern for a smooth UI:

import { getDailyPanchang } from 'panchang-ts';
import { InteractionManager } from 'react-native';

// Pass 1 — cheapest useful result: elements, slots, muhurtas.
const fast = getDailyPanchang(date, location, {
  timezone: 330,
  sections: [],
  computeEndTimes: false,
});
setState(fast);

// Pass 2 — background, everything.
InteractionManager.runAfterInteractions(() => {
  setState(getDailyPanchang(date, location, { timezone: 330 }));
});

The published numbers above are Node measurements; Hermes figures will be published once measured on device. What carries over is the shape of the cost — it is dominated by ephemeris math, so the sections and computeEndTimes levers have the same proportional effect on any runtime. Built tables are dictionary-encoded specifically because parse time and resident memory are the constraints that bite on Hermes — see the table pattern.