FPS (Frames Per Second) — ay isang metrik na nagpapakita kung gaano karaming indibidwal na mga frame ang irerender ng graphic system sa isang segundo. Sa mobile development, ang FPS ay isang karaniwang tagapagpahiwatig ng pagganap ng UI: kung mas mataas ang FPS, mas makinis ang mga animation at mas responsive ang interface. Ayon sa datos ng Google Android Performance, 2025, ang target na halaga ng FPS para sa mga mobile application ay 60 frame bawat segundo — ito ang threshold kung saan nakikita ng mata ng tao ang paggalaw bilang tuloy-tuloy at makinis.
Mga Pangunahing Punto
FPS (Frames Per Second) — ay isang yunit ng pagsukat ng frame rate na ginagamit sa computer graphics, video, at mga mobile interface. Ang bawat frame ay isang static na imahe na ipinapakita sa screen sa loob ng maikling panahon. Sa mabilis na pagbabago ng mga frame, nakikita ng utak ang mga ito bilang tuloy-tuloy na paggalaw — ang epektong ito ay tinatawag na persistence of vision. Para sa mga mobile application, ang FPS ay isang kritikal na metrik, dahil ang anumang nalaglag na frame (drop) ay ginagawang kapansin-pansing pagkautal ang makinis na animation. Dapat magtagumpay ang app na irecter ang bawat frame nang mahigpit sa loob ng badyet ng oras: 16.6 ms para sa 60 FPS, 11.1 ms para sa 90 FPS, 8.3 ms para sa 120 FPS.
Ang FPS ay sinusukat hindi lamang para sa UI, kundi para din sa mga laro, video, at camera. Sa mga laro, ang FPS ay nakadepende sa pagiging kumplikado ng eksena, kalidad ng mga texture, at lakas ng GPU. Sa video, ang FPS ay nakapirmi (24, 30, 60 frame/s) at tinutukoy ng nilalaman. Sa mga mobile application, ang FPS ay nakadepende sa kahusayan ng UI code: pagiging kumplikado ng Layout, bilang ng mga View, dalas ng pag-redraw, at trabaho ng GC (Garbage Collection). Ayon sa Apple WWDC 2022, ang average na FPS sa isang app ay maaaring bumaba ng 10–15% dahil sa hindi mahusay na pag-update ng mga koleksyon (reloadData sa halip na insert/delete/dequeueReusableCell). Ang pagsukat ng FPS sa real-time ay isang karaniwang kasanayan para sa mga QA engineer at developer na nagtatrabaho sa pagganap.
Ang pagkalkula ng FPS sa isang mobile app ay batay sa pagsukat ng oras sa pagitan ng magkakasunod na mga frame. Ang pinakasimpleng formula: FPS = 1000 / deltaTimeMs, kung saan ang deltaTimeMs ay ang pagitan sa pagitan ng pagkumpleto ng nakaraang frame at pagkumpleto ng kasalukuyang frame. Kung ang kasalukuyang frame ay na-render sa 20 ms, FPS = 1000 / 20 = 50. Gayunpaman sa pagsasanay, ang FPS ay bihirang maging matatag kahit sa loob ng isang segundo: ang tipikal na profile ay may kasamang mga frame na 12–16 ms na may kasamang mga nalaglag (jank) o mabagal na frame (40–60 ms). Samakatuwid, ang FPS ay sinusukat bilang isang moving average sa loob ng 1–5 segundo o bilang mga percentile ng pamamahagi ng oras ng frame.
Sa Android, ang FPS ay kinakalkula sa pamamagitan ng Choreographer, na tumatanggap ng callback mula sa VSync (synchronization impulse ng display). Ang bawat callback ay tumutugma sa isang frame. Kung ang callback ay hindi dumating — ang frame ay nalaglag. Pinapayagan ng Choreographer ang pagsukat ng eksaktong bilang ng mga frame bawat segundo at ang bilang ng mga nalaglag (skipped frames). Sa iOS, ang CADisplayLink ay gumagana nang katulad — ito ay tinatawag sa bawat oras na ang display ay handa na upang irecter ang isang bagong frame. Ang property na timestamp ay naglalaman ng eksaktong oras ng huling frame, at ang targetTimestamp — ang inaasahang oras ng susunod. Ang pagkakaiba sa pagitan ng mga ito ay ang badyet ng oras para sa kasalukuyang frame.
Ang code sa Swift ay nagpapakita ng simpleng pagsubaybay sa FPS sa pamamagitan ng CADisplayLink. Ang counter na frameCount ay tumataas sa bawat tawag at isang beses bawat segundo ang aktwal na FPS ay kinakalkula.
class FpsCounter {
private var displayLink: CADisplayLink?
private var frameCount = 0
private var lastTime = TimeInterval(0)
func start() {
displayLink = CADisplayLink(
target: self,
selector: #selector(countFrame)
)
displayLink?.add(to: .current,
forMode: .common)
}
@objc
private func countFrame() {
frameCount += 1
let now = Date().timeIntervalSince1970
if now - lastTime >= 1.0 {
print("FPS: \(frameCount)")
frameCount = 0
lastTime = now
}
}
}
Ang pamantayang 60 FPS (60 Hz) ay nag-ugat sa industriya dahil sa ilang mga kadahilanan. Una — pisyolohikal: ang mata ng tao ay hindi nakikilala ang mga indibidwal na frame sa dalas na higit sa 50–60 Hz, na nakikita ang mga ito bilang makinis na paggalaw. Ang threshold na ito ay tinatawag na Critical Flicker Fusion (CFF). Pangalawa — pangkasaysayan: ang mga unang cathode-ray tube (CRT) ay gumana sa 60 Hz sa USA (NTSC) at 50 Hz sa Europe (PAL). Ang mga modernong LCD display ay nagmana ng dalas na ito. Pangatlo — pang-inhinyero: para sa mga UI animation, ang 60 FPS ay nagbibigay ng sub-millisecond latency ng pagtugon sa pagpindot, na kritikal para sa pag-input ng teksto, pag-scroll, at pag-drag.
Para sa mga mobile developer, ang 60 FPS ay hindi lamang isang rekomendasyon, kundi isang mahigpit na badyet na 16.6 ms bawat frame. Ang badyet na ito ay hinati sa pagitan ng lahat ng mga yugto ng rendering: Input (1–2 ms), Animation (2–3 ms), Layout (3–5 ms), Draw (3–5 ms), at Swap (1–2 ms). Kung ang anumang yugto ay lumampas sa sub-badyet nito, ang frame ay maaaring hindi magkasya sa 16.6 ms. Inirerekomenda ng Google Android Performance na gumamit ng 12–14 ms para sa paghahanda ng frame, na nag-iiwan ng 2–4 ms na reserba para sa mga system interruption (GC, background thread). Ayon sa Firebase Performance, ang mga app na may average na FPS na mas mababa sa 52 at P99 FPS na mas mababa sa 30 ay tumatanggap ng 35% na mas maraming reklamo sa pagganap sa mga review ng Google Play.
FPS at Frame Time (oras ng frame) — ay dalawang panig ng parehong metrik at mahalagang huwag silang malito. Ang FPS ay bilis, ang Frame Time ay latency. Sa 60 FPS, ang bawat frame ay tumatagal ng 16.6 ms. Sa 30 FPS — 33.3 ms. Ngunit ang FPS ay isang di-linear na metrik: ang pagbaba mula 60 hanggang 30 FPS ay nangangahulugan na ang oras ng frame ay tumaas ng 2 beses, at ang pagbaba mula 30 hanggang 20 — 1.5 beses. Samakatuwid, ang mga profiler ay nagpapakita hindi ng FPS, kundi ng Frame Time — ito ay nagbibigay-daan upang makita ang mga problemang frame, hindi ang average frequency. Halimbawa, ang average na 55 FPS ay maaaring itago na 5% ng mga frame ay may Frame Time na 50–100 ms — ang mga frame na ito ay nagdudulot ng Jank, ngunit hindi gaanong nakakaapekto sa average na FPS.
Sa pagsusuri ng pagganap, inirerekomenda na tumingin hindi sa average na FPS, kundi sa histogram ng Frame Time. Sa Android Studio Profiler at iOS Instruments, ang Frame Time ay ipinapakita bilang isang iskala, kung saan ang berdeng sona — hanggang 16.6 ms (60 FPS), dilaw — 16.6–33.3 ms (30–60 FPS), pula — higit sa 33.3 ms (mas mababa sa 30 FPS). Ang bawat pulang kolum ay isang kapansin-pansing latency para sa user. Praktikal na patakaran: P95 Frame Time (95% ng mga frame ay kasya sa X ms) — ay isang mas maaasahang metrik kaysa sa average na FPS. Kung ang P95 Frame Time ay lumampas sa 32 ms (30 FPS), ang app ay itinuturing na mabagal kahit na may average na FPS na 50.
Function sa Kotlin para sa pag-convert ng array ng mga oras ng frame sa FPS na may mga percentile. Ibinabalik hindi lamang ang average na FPS, kundi pati na rin ang P50, P90, at P99 para sa detalyadong pagsusuri.
data class FpsReport(
val average: Float,
val p50: Float,
val p90: Float,
val p99: Float
)
fun List<Long>.toFpsReport(): FpsReport {
val fpsValues = this.map { ms ->
if (ms > 0) 1000f / ms else 0f
}.sorted()
return FpsReport(
average = fpsValues.average().toFloat(),
p50 = fpsValues[fpsValues.size / 2],
p90 = fpsValues[(fpsValues.size * 90 / 100)],
p99 = fpsValues[(fpsValues.size * 99 / 100)]
)
}
Ang mga modernong mobile device na may mga display na 90, 120, at 144 Hz ay naglalagay ng mga bagong kinakailangan para sa FPS. Kung ang isang app ay naghahatid ng 60 FPS sa isang 120 Hz na display, ang user ay nakakakita ng mga micro-utterance, dahil ang bawat ikalawang cycle ng pag-refresh ng screen ay tumatanggap ng parehong frame. Upang mapanatili ang 120 FPS, ang badyet bawat frame ay nababawasan mula 16.6 hanggang 8.3 ms — ito ay nangangailangan ng dalawang beses na mas mahusay na rendering code. Ayon sa mga developer ng Android (Google I/O 2023), upang makamit ang matatag na 120 FPS, kinakailangan: iwasan ang mga alokasyon sa Draw cycle, bawasan ang bilang ng mga View sa hierarchy (mas mababa sa 80), iwanan ang mabibigat na drawable pabor sa VectorDrawable, at gumamit ng surfaceView para sa kumplikadong graphics.
Sa iOS, ang sitwasyon ay katulad: iPhone Pro na may ProMotion (120 Hz) ay nangangailangan ng dalawang beses na mas maraming frame, ngunit ang oras bawat frame ay kalahati. Pansinin ng Apple na hindi lahat ng animation ay dapat gumana sa 120 FPS — awtomatikong binabawasan ng Core Animation ang dalas para sa mga static o mabagal na nagbabagong elemento. Gayunpaman, ang pag-scroll, mga animation ng kilos, at mga transition ay dapat maghatid ng 120 FPS para sa pakiramdam ng "parang sutla". Ang mga pangunahing problema sa paglipat mula 60 tungo sa 120 FPS: pagtaas ng konsumo ng kuryente (25–40% para sa GPU), pag-init ng device, at throttling — kapag ang dalas ay bumababa dahil sa sobrang init. Inirerekomenda na magpatupad ng fallback mechanism: kung ang Frame Time ay patuloy na lumalampas sa 8.3 ms, bawasan ang target frequency sa 60 FPS nang programmatically, sa halip na maghintay ng system throttling.
Code sa Java para sa Android na tumutukoy kung ang device ay maaaring sumuporta sa 120 FPS at lumipat ng rendering mode. Ginagamit ang Display.getMode upang matukoy ang mga sinusuportahang frequency.
class FpsModeSwitcher {
static boolean canDo120Fps(Activity activity) {
Display display = activity.getWindowManager()
.getDefaultDisplay();
for (Display.Mode mode : display.getSupportedModes()) {
if (mode.getRefreshRate() >= 120f) {
return true;
}
}
return false;
}
}
Ang pag-optimize ng FPS ay nangangailangan ng sistematikong approach, simula sa profiling at nagtatapos sa refactoring ng mga problemang lugar. Unang yugto — sukatin ang kasalukuyang FPS gamit ang isang profiler (. Ikalawang yugto — hanapin ang mga frame na lumalampas sa badyet. Para sa Android, ito ay maaaring gawin sa pamamagitan ng GPU Profiling o Perfetto. Para sa iOS — Instruments na may template na Core Animation. Ikatlong yugto — alisin ang mga sanhi: bawasan ang overdraw, bawasan ang lalim ng View nesting, palitan ang Layout phase ng ConstraintLayout, magdagdag ng ViewHolder Recycling, ilipat ang mabibigat na kalkulasyon sa background thread.
Ang mga partikular na pag-optimize ng FPS ay kinabibilangan ng: Frame Pacing — isang mekanismo na pantay na namamahagi ng oras sa pagitan ng mga frame upang maiwasan ang "mga pakete" ng mabilis at mabagal na frame. Sa Android, ang Choreographer.FrameCallback na may fixed interval ay nagbibigay-daan sa pagpapatupad ng Frame Pacing. Sa iOS, ang CADisplayLink.preferredFrameRateRange ay gumagawa ng pareho. Ikalawang mekanismo — Triple Buffering: ang system ay gumagamit ng tatlong buffer sa halip na dalawa, na nagpapahintulot sa GPU na simulan ang pag-drawing ng susunod na frame nang hindi naghihintay na malaya ang nakaraang buffer. Android ay awtomatikong nag-a-activate ng Triple Buffering kapag kinakailangan, ngunit sa iOS, ang developer ay maaaring humingi nito nang tahasan sa pamamagitan ng CAMetalLayer. Ikatlo — Texture Caching: pag-cache ng mga bitmap sa GPU memory upang hindi muling i-load ang mga ito sa bawat frame.
Ang halimbawa sa Kotlin ay nagpapakita ng pagpapatupad ng Frame Pacing na may fixed interval na 16.6 ms. Lahat ng callback ay dumarating na may pantay na interval, kahit na ang system ay naantala.
class PacedFrameRenderer {
private val targetDelta = 16_666_666L // 16.6 ms (60 FPS)
private var lastFrameTime = 0L
private val frameCallback =
Choreographer.FrameCallback { frameTimeNanos ->
val delta = frameTimeNanos - lastFrameTime
if (delta >= targetDelta) {
onFrame(delta)
lastFrameTime = frameTimeNanos
}
Choreographer.getInstance()
.postFrameCallback(this)
}
private fun onFrame(delta: Long) {
// pag-render ng frame
}
}
Mga Madalas Itanong
60 FPS — komportableng antas para sa mga mobile app. Ang pagkakaiba sa pagitan ng 60 at 120 FPS ay kapansin-pansin lamang sa mga display na may mataas na refresh rate sa mabilis na animation (pag-scroll, pag-drag). Sa ibaba ng 30 FPS — discomfort.
FPS = 1000 / FrameTime (ms). Kung Frame Time = 16.6 ms, FPS = 60. Kung Frame Time = 33.3 ms, FPS = 30. Inirerekomenda na subaybayan ang Frame Time, hindi ang FPS, dahil ipinapakita nito ang mga problemang frame.
Kapag nag-scroll, tinatawagan ng system ang Layout at Draw para sa bawat bagong elemento ng listahan. Kung kumplikado ang mga View, hindi na-cache ang Layout, o gumagamit ng mabibigat na drawable — tumataas ang Frame Time at bumababa ang FPS. Solusyon — ViewHolder recycling at flat hierarchy.
Gamitin ang Instruments na may template na Core Animation (nagpapakita ng FPS sa real-time). Para sa programmatic na pagsukat — CADisplayLink na may pagbibilang ng mga frame bawat segundo. Para sa produksyon — MetricKit na may metrik na MXAnimatoryMetric.
Triple Buffering ay gumagamit ng tatlong buffer sa halip na dalawa, na nagpapahintulot sa GPU na simulan ang rendering ng susunod na frame bago matapos ang VSync ng kasalukuyang frame. Ito ay nagpapakinis ng peak load at nagpapataas ng stability ng FPS, ngunit nagdaragdag ng 1 frame latency.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din