Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Visi lietotāji mobilo lietojumprogrammu ātru palaiÅ”anu un atsaucÄ«gu lietotāja interfeisu uzskata par paÅ”saprotamu. Ja lietojumprogrammas palaiÅ”ana prasa ilgu laiku, lietotājs sāk justies bēdÄ«gs un dusmÄ«gs. JÅ«s varat viegli sabojāt klienta pieredzi vai pilnÄ«bā zaudēt lietotāju pat pirms viņŔ sāk lietot lietojumprogrammu.

Reiz mēs atklājām, ka lietotnes Dodo Pizza palaiÅ”ana aizņem vidēji 3 sekundes, bet dažiem ā€œlaimÄ«gajiemā€ ā€” 15ā€“20 sekundes.

Zem griezuma ir stāsts ar laimīgām beigām: par Realm datu bāzes pieaugumu, atmiņas noplūdi, kā mēs uzkrājām ligzdotos objektus, pēc tam savedāmies kopā un visu salabojām.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu
Raksta autors: Maksims Kačinkins ā€” Android izstrādātājs Dodo Pizza.

TrÄ«s sekundes no noklikŔķināŔanas uz lietojumprogrammas ikonas lÄ«dz pirmās darbÄ«bas resume() ir bezgalÄ«ba. Un dažiem lietotājiem palaiÅ”anas laiks sasniedza 15-20 sekundes. Kā tas vispār ir iespējams?

Ļoti īss kopsavilkums tiem, kam nav laika lasīt
MÅ«su Realm datubāze pieauga bezgalÄ«gi. Daži ligzdoti objekti netika izdzēsti, bet tika pastāvÄ«gi uzkrāti. Lietojumprogrammas palaiÅ”anas laiks pakāpeniski palielinājās. Tad mēs to labojām, un palaiÅ”anas laiks sasniedza mērÄ·i - tas kļuva mazāks par 1 sekundi un vairs nepalielinājās. Rakstā ir situācijas analÄ«ze un divi risinājumi - ātrais un parastais.

Problēmas meklÄ“Å”ana un analÄ«ze

MÅ«sdienās jebkurai mobilajai lietojumprogrammai ir ātri jāpalaižas un jābÅ«t atsaucÄ«gai. Bet tas attiecas ne tikai uz mobilo lietotni. Lietotāja pieredze mijiedarbÄ«bā ar pakalpojumu un uzņēmumu ir sarežģīta lieta. Piemēram, mÅ«su gadÄ«jumā piegādes ātrums ir viens no galvenajiem picu apkalpoÅ”anas rādÄ«tājiem. Ja piegāde ir ātra, pica bÅ«s karsta, un klientam, kurÅ” vēlas ēst tagad, nebÅ«s ilgi jāgaida. Savukārt aplikācijai ir svarÄ«gi radÄ«t ātras apkalpoÅ”anas sajÅ«tu, jo, ja aplikācijas palaiÅ”ana aizņem tikai 20 sekundes, tad cik ilgi bÅ«s jāgaida pica?

Sākumā mēs paÅ”i saskārāmies ar faktu, ka dažreiz lietojumprogrammas palaiÅ”ana prasÄ«ja pāris sekundes, un tad mēs sākām dzirdēt citu kolēģu sÅ«dzÄ«bas par to, cik ilgi tas prasÄ«ja. Taču mēs nevarējām konsekventi atkārtot Å”o situāciju.

Cik ilgi tas ir? Saskaņā ar Google dokumentācija, ja lietojumprogrammas aukstā palaiÅ”ana aizņem mazāk nekā 5 sekundes, tas tiek uzskatÄ«ts par ā€œit kā normāliā€. Palaista Android lietotne Dodo Pizza (saskaņā ar Firebase metriku _app_start) plkst aukstais starts vidēji 3 sekundēs - ā€œNav lieliski, nav briesmÄ«giā€, kā saka.

Bet tad sāka parādÄ«ties sÅ«dzÄ«bas, ka lietojumprogrammas palaiÅ”ana prasÄ«ja ļoti, ļoti, ļoti ilgu laiku! Sākumā mēs nolēmām izmērÄ«t, kas ir ā€œÄ¼oti, ļoti, ļoti garÅ”ā€. Å im nolÅ«kam mēs izmantojām Firebase izsekoÅ”anu Lietotnes sākuma izsekoÅ”ana.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Å Ä« standarta izsekoÅ”ana mēra laiku no brīža, kad lietotājs atver lietojumprogrammu, un brÄ«di, kad tiek izpildÄ«ts pirmās darbÄ«bas onResume(). Firebase konsolē Ŕī metrika tiek saukta par _app_start. IzrādÄ«jās, ka:

  • StartÄ“Å”anas laiks lietotājiem virs 95. procentiles ir gandrÄ«z 20 sekundes (daži pat ilgāk), lai gan vidējais aukstās palaiÅ”anas laiks ir mazāks par 5 sekundēm.
  • StartÄ“Å”anas laiks nav nemainÄ«ga vērtÄ«ba, bet laika gaitā pieaug. Bet dažreiz ir pilieni. Mēs atklājām Å”o modeli, kad palielinājām analÄ«zes skalu lÄ«dz 90 dienām.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Ienāca prātā divas domas:

  1. Kaut kas noplūst.
  2. Å is ā€œkaut kasā€ tiek atiestatÄ«ts pēc atbrÄ«voÅ”anas un pēc tam atkal noplÅ«st.

"DroÅ”i vien kaut kas ar datu bāzi," mēs domājām, un mums bija taisnÄ«ba. Pirmkārt, mēs izmantojam datu bāzi kā keÅ”atmiņu; migrācijas laikā mēs to notÄ«rām. Otrkārt, datu bāze tiek ielādēta, kad programma tiek startēta. Viss sader kopā.

Kas vainas Realm datu bāzei

Mēs sākām pārbaudÄ«t, kā datu bāzes saturs mainās lietojumprogrammas darbÄ«bas laikā, sākot no pirmās instalÄ“Å”anas un turpmāk aktÄ«vās lietoÅ”anas laikā. Realm datu bāzes saturu varat apskatÄ«t, izmantojot Steto vai detalizētāk un skaidrāk, atverot failu caur Realm studija. Lai skatÄ«tu datu bāzes saturu, izmantojot ADB, kopējiet Realm datu bāzes failu:

adb exec-out run-as ${PACKAGE_NAME} cat files/${DB_NAME}

Apskatot datubāzes saturu dažādos laikos, noskaidrojām, ka noteikta veida objektu skaits nepārtraukti pieaug.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu
Attēlā redzams Realm Studio fragments diviem failiem: pa kreisi - aplikācijas bāze kādu laiku pēc instalÄ“Å”anas, labajā - pēc aktÄ«vas lietoÅ”anas. Var redzēt, ka objektu skaits ImageEntity Šø MoneyType ir ievērojami pieaudzis (ekrānuzņēmums parāda katra veida objektu skaitu).

Saistība starp datu bāzes pieaugumu un palaiŔanas laiku

Nekontrolēta datu bāzes izaugsme ir ļoti slikta. Bet kā tas ietekmē lietojumprogrammas palaiÅ”anas laiku? To ir diezgan viegli izmērÄ«t, izmantojot ActivityManager. KopÅ” operētājsistēmas Android 4.4 logcat parāda žurnālu ar virkni ParādÄ«to un laiku. Å is laiks ir vienāds ar intervālu no lietojumprogrammas palaiÅ”anas brīža lÄ«dz aktivitātes renderÄ“Å”anas beigām. Å ajā laikā notiek Ŕādi notikumi:

  • Sāciet procesu.
  • Objektu inicializācija.
  • AktivitāŔu izveide un inicializācija.
  • Izkārtojuma izveide.
  • Lietojumprogrammu renderÄ“Å”ana.

Mums piestāv. Ja palaižat ADB ar karodziņiem -S un -W, varat iegÅ«t pagarinātu izvadi ar startÄ“Å”anas laiku:

adb shell am start -S -W ru.dodopizza.app/.MainActivity -c android.intent.category.LAUNCHER -a android.intent.action.MAIN

Ja jÅ«s to paņemat no turienes grep -i WaitTime laikā, varat automatizēt Ŕīs metrikas apkopoÅ”anu un vizuāli aplÅ«kot rezultātus. Zemāk esoÅ”ajā grafikā parādÄ«ta lietojumprogrammas palaiÅ”anas laika atkarÄ«ba no lietojumprogrammas aukstās palaiÅ”anas reižu skaita.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Tajā paŔā laikā pastāvēja tāda pati saistÄ«ba starp datu bāzes lielumu un pieaugumu, kas pieauga no 4 MB lÄ«dz 15 MB. Kopumā izrādās, ka laika gaitā (ar auksto startu pieaugumu) palielinājās gan aplikācijas palaiÅ”anas laiks, gan datu bāzes apjoms. MÅ«su rokās ir hipotēze. Tagad atlika tikai apstiprināt atkarÄ«bu. Tāpēc mēs nolēmām novērst ā€œnoplÅ«desā€ un noskaidrot, vai tas paātrinās palaiÅ”anu.

Bezgalīgas datu bāzes izaugsmes iemesli

Pirms ā€œnoplūžuā€ noņemÅ”anas ir vērts saprast, kāpēc tās vispār parādÄ«jās. Lai to izdarÄ«tu, atcerēsimies, kas ir Realm.

Realm ir nerelāciju datubāze. Tas ļauj aprakstÄ«t attiecÄ«bas starp objektiem lÄ«dzÄ«gi tam, cik daudz ORM relāciju datu bāzu operētājsistēmā Android ir aprakstÄ«tas. Tajā paŔā laikā Realm saglabā objektus tieÅ”i atmiņā ar vismazāko transformāciju un kartējumu skaitu. Tas ļauj ļoti ātri nolasÄ«t datus no diska, kas ir Realm stiprā puse un kāpēc tā tiek mÄ«lēta.

(Å Ä« raksta vajadzÄ«bām mums pietiks ar Å”o aprakstu. Vairāk par Realm varat izlasÄ«t vēsumā dokumentācija vai viņu akadēmija).

Daudzi izstrādātāji ir pieraduÅ”i vairāk strādāt ar relāciju datu bāzēm (piemēram, ORM datubāzēm ar SQL zem pārsega). Un tādas lietas kā kaskādes datu dzÄ“Å”ana bieži Ŕķiet paÅ”saprotama. Bet ne valstÄ«bā.

Starp citu, kaskādes dzÄ“Å”anas funkcija ir lÅ«gta jau ilgu laiku. Å is pārskatÄ«Å”ana Šø cits, kas saistÄ«ts ar to, tika aktÄ«vi apspriests. Bija sajÅ«ta, ka drÄ«z tas bÅ«s izdarÄ«ts. Bet pēc tam viss pārvērtās stipro un vājo saiÅ”u ievieÅ”anā, kas arÄ« automātiski atrisinātu Å”o problēmu. Bija diezgan dzÄ«vs un aktÄ«vs Å”ajā uzdevumā izvilkt pieprasÄ«jumu, kas pagaidām ir apturēta iekŔējo grÅ«tÄ«bu dēļ.

Datu noplÅ«de bez kaskādes dzÄ“Å”anas

Kā tieÅ”i notiek datu noplÅ«de, ja paļaujaties uz neesoÅ”u kaskādes dzÄ“Å”anu? Ja jums ir ligzdoti Realm objekti, tie ir jāizdzÄ“Å”.
Apskatīsim (gandrīz) reālu piemēru. Mums ir objekts CartItemEntity:

@RealmClass
class CartItemEntity(
 @PrimaryKey
 override var id: String? = null,
 ...
 var name: String = "",
 var description: String = "",
 var image: ImageEntity? = null,
 var category: String = MENU_CATEGORY_UNKNOWN_ID,
 var customizationEntity: CustomizationEntity? = null,
 var cartComboProducts: RealmList<CartProductEntity> = RealmList(),
 ...
) : RealmObject()

Precei grozā ir dažādi lauki, ieskaitot attēlu ImageEntity, pielāgotas sastāvdaļas CustomizationEntity. ArÄ« prece grozā var bÅ«t kombinēta ar savu produktu komplektu RealmList (CartProductEntity). Visi uzskaitÄ«tie lauki ir Realm objekti. Ja ievietosim jaunu objektu (copyToRealm() / copyToRealmOrUpdate()) ar tādu paÅ”u id, tad Å”is objekts tiks pilnÄ«bā pārrakstÄ«ts. Bet visi iekŔējie objekti (attēls, customizationEntity un cartComboProducts) zaudēs savienojumu ar vecāku un paliks datu bāzē.

Tā kā savienojums ar tiem tiek zaudēts, mēs tos vairs nelasām un neizdzÄ“Å”am (ja vien mēs tiem nepārprotami piekļūstam vai notÄ«rām visu ā€œtabuluā€). Mēs to saucām par "atmiņas noplÅ«dēm".

Strādājot ar Realm, mums ir skaidri jāiet cauri visiem elementiem un skaidri jāizdzÄ“Å” viss pirms Ŕādu darbÄ«bu veikÅ”anas. To var izdarÄ«t, piemēram, Ŕādi:

val entity = realm.where(CartItemEntity::class.java).equalTo("id", id).findFirst()
if (first != null) {
 deleteFromRealm(first.image)
 deleteFromRealm(first.customizationEntity)
 for(cartProductEntity in first.cartComboProducts) {
   deleteFromRealm(cartProductEntity)
 }
 first.deleteFromRealm()
}
// Šø ŠæŠ¾Ń‚Š¾Š¼ уŠ¶Šµ сŠ¾Ń…Ń€Š°Š½ŃŠµŠ¼

Ja jÅ«s to darÄ«sit, viss darbosies tā, kā vajadzētu. Å ajā piemērā mēs pieņemam, ka attēlā, customizationEntity un cartComboProducts nav citu ligzdotu Realm objektu, tāpēc nav citu ligzdotu cilpu un dzÄ“Å”anu.

Ātrs risinājums

Pirmā lieta, ko mēs nolēmām darÄ«t, bija sakopt visstraujāk augoÅ”os objektus un pārbaudÄ«t rezultātus, lai redzētu, vai tas atrisinās mÅ«su sākotnējo problēmu. Pirmkārt, tika izveidots vienkārŔākais un intuitÄ«vākais risinājums, proti: katram objektam ir jāatbild par savu bērnu izņemÅ”anu. Lai to izdarÄ«tu, mēs ieviesām saskarni, kas atgrieza ligzdoto Realm objektu sarakstu:

interface NestedEntityAware {
 fun getNestedEntities(): Collection<RealmObject?>
}

Un mēs to ieviesām savos Realm objektos:

@RealmClass
class DataPizzeriaEntity(
 @PrimaryKey
 var id: String? = null,
 var name: String? = null,
 var coordinates: CoordinatesEntity? = null,
 var deliverySchedule: ScheduleEntity? = null,
 var restaurantSchedule: ScheduleEntity? = null,
 ...
) : RealmObject(), NestedEntityAware {

 override fun getNestedEntities(): Collection<RealmObject?> {
   return listOf(
       coordinates,
       deliverySchedule,
       restaurantSchedule
   )
 }
}

Š’ getNestedEntities mēs atdodam visus bērnus kā vienotu sarakstu. Katrs pakārtotais objekts var arÄ« ieviest NestedEntityAware saskarni, norādot, ka tam ir iekŔējie Realm objekti, ko dzēst, piemēram, ScheduleEntity:

@RealmClass
class ScheduleEntity(
 var monday: DayOfWeekEntity? = null,
 var tuesday: DayOfWeekEntity? = null,
 var wednesday: DayOfWeekEntity? = null,
 var thursday: DayOfWeekEntity? = null,
 var friday: DayOfWeekEntity? = null,
 var saturday: DayOfWeekEntity? = null,
 var sunday: DayOfWeekEntity? = null
) : RealmObject(), NestedEntityAware {

 override fun getNestedEntities(): Collection<RealmObject?> {
   return listOf(
       monday, tuesday, wednesday, thursday, friday, saturday, sunday
   )
 }
}

Un tā tālāk, objektu ligzdoŔanu var atkārtot.

Pēc tam mēs rakstām metodi, kas rekursÄ«vi dzÄ“Å” visus ligzdotos objektus. Metode (izgatavota kā paplaÅ”inājums) deleteAllNestedEntities iegÅ«st visus augstākā lÄ«meņa objektus un metodi deleteNestedRecursively RekursÄ«vi noņem visus ligzdotos objektus, izmantojot NestedEntityAware saskarni:

fun <T> Realm.deleteAllNestedEntities(entities: Collection<T>,
 entityClass: Class<out RealmObject>,
 idMapper: (T) -> String,
 idFieldName : String = "id"
 ) {

 val existedObjects = where(entityClass)
     .`in`(idFieldName, entities.map(idMapper).toTypedArray())
     .findAll()

 deleteNestedRecursively(existedObjects)
}

private fun Realm.deleteNestedRecursively(entities: Collection<RealmObject?>) {
 for(entity in entities) {
   entity?.let { realmObject ->
     if (realmObject is NestedEntityAware) {
       deleteNestedRecursively((realmObject as NestedEntityAware).getNestedEntities())
     }
     realmObject.deleteFromRealm()
   }
 }
}

Mēs to darÄ«jām ar visstraujāk augoÅ”ajiem objektiem un pārbaudÄ«jām, kas noticis.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Rezultātā tie objekti, kurus mēs pārklājām ar Å”o risinājumu, pārstāja augt. Un kopējā bāzes izaugsme palēninājās, bet neapstājās.

"Normāls" risinājums

Lai gan bāze sāka augt lēnāk, tā tomēr auga. Tāpēc sākām meklēt tālāk. MÅ«su projekts ļoti aktÄ«vi izmanto datu keÅ”atmiņu Realm. LÄ«dz ar to visu ligzdoto objektu rakstÄ«Å”ana katram objektam ir darbietilpÄ«ga, turklāt palielinās kļūdu risks, jo, mainot kodu, var aizmirst norādÄ«t objektus.

Es gribēju pārliecināties, ka neizmantoju saskarnes, bet vai viss darbojas pats par sevi.

Kad mēs vēlamies, lai kaut kas darbotos pats no sevis, mums ir jāizmanto refleksija. Lai to izdarītu, mēs varam iziet cauri katram klases laukam un pārbaudīt, vai tas ir Realm objekts vai objektu saraksts:

RealmModel::class.java.isAssignableFrom(field.type)

RealmList::class.java.isAssignableFrom(field.type)

Ja lauks ir RealmModel vai RealmList, pievienojiet Ŕī lauka objektu ligzdoto objektu sarakstam. Viss ir tieÅ”i tāpat kā iepriekÅ”, tikai Å”eit tas tiks darÄ«ts pats. Pati kaskādes dzÄ“Å”anas metode ir ļoti vienkārÅ”a un izskatās Ŕādi:

fun <T : Any> Realm.cascadeDelete(entities: Collection<T?>) {
 if(entities.isEmpty()) {
   return
 }

 entities.filterNotNull().let { notNullEntities ->
   notNullEntities
       .filterRealmObject()
       .flatMap { realmObject -> getNestedRealmObjects(realmObject) }
       .also { realmObjects -> cascadeDelete(realmObjects) }

   notNullEntities
       .forEach { entity ->
         if((entity is RealmObject) && entity.isValid) {
           entity.deleteFromRealm()
         }
       }
 }
}

Pagarinājums filterRealmObject filtrē un nodod tikai Realm objektus. Metode getNestedRealmObjects izmantojot atspoguļojumu, tas atrod visus ligzdotos Realm objektus un ievieto tos lineārā sarakstā. Tad mēs darām to paÅ”u rekursÄ«vi. DzÄ“Å”ot, jums jāpārbauda objekta derÄ«gums isValid, jo var bÅ«t, ka dažādiem vecākobjektiem var bÅ«t ligzdoti identiski objekti. Labāk no tā izvairÄ«ties un, veidojot jaunus objektus, vienkārÅ”i izmantojiet automātisko ID Ä£enerÄ“Å”anu.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

GetNestedRealmObjects metodes pilnīga ievieŔana

private fun getNestedRealmObjects(realmObject: RealmObject) : List<RealmObject> {
 val nestedObjects = mutableListOf<RealmObject>()
 val fields = realmObject.javaClass.superclass.declaredFields

// ŠŸŃ€Š¾Š²ŠµŃ€ŃŠµŠ¼ ŠŗŠ°Š¶Š“Š¾Šµ ŠæŠ¾Š»Šµ, Š½Šµ яŠ²Š»ŃŠµŃ‚ся Š»Šø Š¾Š½Š¾ RealmModel ŠøŠ»Šø сŠæŠøсŠŗŠ¾Š¼ RealmList
 fields.forEach { field ->
   when {
     RealmModel::class.java.isAssignableFrom(field.type) -> {
       try {
         val child = getChildObjectByField(realmObject, field)
         child?.let {
           if (isInstanceOfRealmObject(it)) {
             nestedObjects.add(child as RealmObject)
           }
         }
       } catch (e: Exception) { ... }
     }

     RealmList::class.java.isAssignableFrom(field.type) -> {
       try {
         val childList = getChildObjectByField(realmObject, field)
         childList?.let { list ->
           (list as RealmList<*>).forEach {
             if (isInstanceOfRealmObject(it)) {
               nestedObjects.add(it as RealmObject)
             }
           }
         }
       } catch (e: Exception) { ... }
     }
   }
 }

 return nestedObjects
}

private fun getChildObjectByField(realmObject: RealmObject, field: Field): Any? {
 val methodName = "get${field.name.capitalize()}"
 val method = realmObject.javaClass.getMethod(methodName)
 return method.invoke(realmObject)
}

Rezultātā mÅ«su klienta kodā mēs izmantojam ā€œkaskādes dzÄ“Å”anuā€ katrai datu modificÄ“Å”anas darbÄ«bai. Piemēram, ievietoÅ”anas darbÄ«bai tas izskatās Ŕādi:

override fun <T : Entity> insert(
 entityInformation: EntityInformation,
 entities: Collection<T>): Collection<T> = entities.apply {
 realmInstance.cascadeDelete(getManagedEntities(entityInformation, this))
 realmInstance.copyFromRealm(
     realmInstance
         .copyToRealmOrUpdate(this.map { entity -> entity as RealmModel }
 ))
}

Vispirms metode getManagedEntities saņem visus pievienotos objektus un pēc tam metodi cascadeDelete RekursÄ«vi dzÄ“Å” visus savāktos objektus pirms jaunu rakstÄ«Å”anas. Mēs galu galā izmantojam Å”o pieeju visā lietojumprogrammā. Atmiņas noplÅ«de Realm ir pilnÄ«bā pazudusi. Veicot tādu paÅ”u starta laika atkarÄ«bas mērÄ«jumu no lietojumprogrammas auksto palaiÅ”anas reižu skaita, mēs redzam rezultātu.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Zaļā lÄ«nija parāda lietojumprogrammas palaiÅ”anas laika atkarÄ«bu no aukstās palaiÅ”anas reižu skaita ligzdoto objektu automātiskās kaskādes dzÄ“Å”anas laikā.

Rezultāti un secinājumi

Arvien augoŔā Realm datubāze izraisÄ«ja lietojumprogrammas palaiÅ”anu ļoti lēni. Mēs izlaidām atjauninājumu ar mÅ«su paÅ”u ligzdoto objektu "kaskādes dzÄ“Å”anu". Tagad mēs pārraugām un novērtējam, kā mÅ«su lēmums ietekmēja lietojumprogrammas palaiÅ”anas laiku, izmantojot metriku _app_start.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

AnalÄ«zei mēs ņemam 90 dienu periodu un redzam: lietojumprogrammas palaiÅ”anas laiks, gan vidējais, gan lietotāju 95. procentiles laiks, sāka samazināties un vairs nepalielinās.

Stāsts par to, kā kaskādes dzÄ“Å”ana programmā Realm uzvarēja ilgu palaiÅ”anu

Ja skatāties uz septiņu dienu diagrammu, metrika _app_start izskatās pilnÄ«gi atbilstoÅ”a un ir mazāka par 1 sekundi.

Ir arÄ« vērts piebilst, ka pēc noklusējuma Firebase sÅ«ta paziņojumus, ja _app_start vidējā vērtÄ«ba pārsniedz 5 sekundes. Tomēr, kā mēs redzam, jums nevajadzētu uz to paļauties, bet gan tieÅ”i to pārbaudÄ«t.

Realm datubāzes Ä«paŔā iezÄ«me ir tā, ka tā ir nerelāciju datu bāze. Neskatoties uz lietoÅ”anas vienkārŔību, lÄ«dzÄ«bu ar ORM risinājumiem un objektu saistÄ«Å”anu, tai nav kaskādes dzÄ“Å”anas.

Ja tas netiek ņemts vērā, ligzdotie objekti uzkrāsies un ā€œizplÅ«dÄ«sā€. Datubāze pastāvÄ«gi pieaugs, kas savukārt ietekmēs lietojumprogrammas palēnināŔanos vai palaiÅ”anu.

Es dalÄ«jos pieredzē, kā ātri veikt kaskādes objektu dzÄ“Å”anu Realm, kas vēl nav izņemts no kastes, bet par to tiek runāts jau ilgu laiku viņi saka Šø viņi saka. MÅ«su gadÄ«jumā tas ievērojami paātrināja lietojumprogrammas palaiÅ”anas laiku.

Neskatoties uz diskusiju par Ŕīs funkcijas nenovērÅ”amo parādÄ«Å”anos, kaskādes dzÄ“Å”anas neesamÄ«ba programmā Realm tiek veikta pēc dizaina. Ja veidojat jaunu lietojumprogrammu, ņemiet to vērā. Un, ja jau izmantojat Realm, pārbaudiet, vai jums nav Ŕādas problēmas.

Avots: www.habr.com

Pievieno komentāru