Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

அனைத்து பயனர்களும் மொபைல் பயன்பாடுகளில் விரைவான துவக்கம் மற்றும் பதிலளிக்கக்கூடிய UI ஐ சாதாரணமாக எடுத்துக்கொள்கிறார்கள். பயன்பாடு தொடங்குவதற்கு நீண்ட நேரம் எடுத்தால், பயனர் சோகமாகவும் கோபமாகவும் உணரத் தொடங்குகிறார். பயன்பாட்டைப் பயன்படுத்தத் தொடங்குவதற்கு முன்பே நீங்கள் வாடிக்கையாளர் அனுபவத்தை எளிதில் கெடுக்கலாம் அல்லது பயனரை முற்றிலும் இழக்கலாம்.

Dodo Pizza ஆப்ஸ் தொடங்குவதற்கு சராசரியாக 3 வினாடிகள் ஆகும் என்பதையும், சில "அதிர்ஷ்டசாலிகளுக்கு" 15-20 வினாடிகள் ஆகும் என்பதையும் ஒருமுறை கண்டுபிடித்தோம்.

வெட்டுக்குக் கீழே ஒரு மகிழ்ச்சியான முடிவுடன் ஒரு கதை உள்ளது: Realm தரவுத்தளத்தின் வளர்ச்சி, நினைவக கசிவு, உள்ளமைக்கப்பட்ட பொருட்களை எவ்வாறு குவித்தோம், பின்னர் நம்மை ஒன்றாக இழுத்து எல்லாவற்றையும் சரிசெய்தோம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை
கட்டுரை ஆசிரியர்: மாக்சிம் கச்சிங்கின் - டோடோ பிட்சாவில் ஆண்ட்ராய்டு டெவலப்பர்.

பயன்பாட்டு ஐகானைக் கிளிக் செய்வதிலிருந்து முதல் செயல்பாட்டின் onResume() வரையிலான மூன்று வினாடிகள் முடிவிலி ஆகும். சில பயனர்களுக்கு, தொடக்க நேரம் 15-20 வினாடிகளை எட்டியது. இது கூட எப்படி சாத்தியம்?

படிக்க நேரமில்லாதவர்களுக்காக மிகச்சிறிய சுருக்கம்
எங்கள் Realm தரவுத்தளம் முடிவில்லாமல் வளர்ந்தது. சில உள்ளமை பொருள்கள் நீக்கப்படவில்லை, ஆனால் தொடர்ந்து குவிந்தன. பயன்பாடு தொடங்கும் நேரம் படிப்படியாக அதிகரித்தது. பின்னர் நாங்கள் அதை சரிசெய்தோம், தொடக்க நேரம் இலக்கை அடைந்தது - இது 1 வினாடிக்கும் குறைவாக ஆனது மற்றும் இனி அதிகரிக்கவில்லை. கட்டுரையில் நிலைமையின் பகுப்பாய்வு மற்றும் இரண்டு தீர்வுகள் உள்ளன - விரைவான ஒன்று மற்றும் சாதாரணமானது.

சிக்கலின் தேடல் மற்றும் பகுப்பாய்வு

இன்று, எந்த மொபைல் பயன்பாடும் விரைவாக தொடங்க வேண்டும் மற்றும் பதிலளிக்க வேண்டும். ஆனால் இது மொபைல் பயன்பாட்டைப் பற்றியது அல்ல. ஒரு சேவை மற்றும் நிறுவனத்துடன் தொடர்பு கொள்ளும் பயனர் அனுபவம் ஒரு சிக்கலான விஷயம். எடுத்துக்காட்டாக, எங்கள் விஷயத்தில், விநியோக வேகம் பீட்சா சேவைக்கான முக்கிய குறிகாட்டிகளில் ஒன்றாகும். டெலிவரி வேகமாக இருந்தால், பீட்சா சூடாக இருக்கும், இப்போது சாப்பிட விரும்பும் வாடிக்கையாளர் நீண்ட நேரம் காத்திருக்க வேண்டியதில்லை. பயன்பாட்டிற்கு, வேகமான சேவையின் உணர்வை உருவாக்குவது முக்கியம், ஏனென்றால் பயன்பாடு தொடங்குவதற்கு 20 வினாடிகள் மட்டுமே எடுத்தால், பீட்சாவிற்கு எவ்வளவு நேரம் காத்திருக்க வேண்டும்?

முதலில், சில நேரங்களில் பயன்பாடு தொடங்க இரண்டு வினாடிகள் ஆகும் என்ற உண்மையை நாமே எதிர்கொண்டோம், பின்னர் அது எவ்வளவு நேரம் ஆனது என்பது குறித்து மற்ற சக ஊழியர்களிடமிருந்து புகார்களைக் கேட்க ஆரம்பித்தோம். ஆனால் இந்த நிலைமையை எங்களால் தொடர்ந்து செய்ய முடியவில்லை.

எவ்வளவு நேரம் ஆகும்? படி Google ஆவணங்கள், ஒரு பயன்பாட்டின் குளிர் தொடக்கமானது 5 வினாடிகளுக்கு குறைவாக எடுத்தால், இது "இயல்பானது போல்" கருதப்படுகிறது. டோடோ பிஸ்ஸா ஆண்ட்ராய்டு பயன்பாடு தொடங்கப்பட்டது (ஃபயர்பேஸ் அளவீடுகளின்படி _app_start) மணிக்கு குளிர் ஆரம்பம் சராசரியாக 3 வினாடிகளில் - அவர்கள் சொல்வது போல் "பெரியது அல்ல, பயங்கரமானது அல்ல".

ஆனால், அப்ளிகேஷன் தொடங்குவதற்கு மிக மிக மிக நீண்ட நேரம் எடுத்ததாக புகார்கள் தோன்ற ஆரம்பித்தன! தொடங்குவதற்கு, "மிக, மிக, மிக நீண்ட" என்பதை அளவிட முடிவு செய்தோம். இதற்கு Firebase ட்ரேஸைப் பயன்படுத்தினோம் ஆப் தொடக்கத் தடம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

இந்த நிலையான சுவடு பயனர் பயன்பாட்டைத் திறக்கும் தருணத்திற்கும் முதல் செயல்பாட்டின் onResume() செயல்படுத்தப்படும் தருணத்திற்கும் இடையிலான நேரத்தை அளவிடும். ஃபயர்பேஸ் கன்சோலில் இந்த மெட்ரிக் _app_start என்று அழைக்கப்படுகிறது. அது மாறியது:

  • சராசரி குளிர் தொடக்க நேரம் 95 வினாடிகளுக்கு குறைவாக இருந்தாலும், 20வது சதவீதத்திற்கு மேல் உள்ள பயனர்களின் தொடக்க நேரங்கள் கிட்டத்தட்ட 5 வினாடிகள் (சில இன்னும் நீண்டது).
  • தொடக்க நேரம் நிலையான மதிப்பு அல்ல, ஆனால் காலப்போக்கில் வளரும். ஆனால் சில நேரங்களில் சொட்டுகள் உள்ளன. பகுப்பாய்வின் அளவை 90 நாட்களுக்கு அதிகரித்தபோது இந்த முறையைக் கண்டறிந்தோம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

இரண்டு எண்ணங்கள் மனதில் தோன்றின:

  1. ஏதோ கசிகிறது.
  2. இந்த "ஏதாவது" வெளியான பிறகு மீட்டமைக்கப்பட்டு, மீண்டும் கசியும்.

"அநேகமாக ஏதாவது தரவுத்தளத்தில் இருக்கலாம்," நாங்கள் நினைத்தோம், நாங்கள் சரிதான். முதலாவதாக, தரவுத்தளத்தை தற்காலிக சேமிப்பாகப் பயன்படுத்துகிறோம்; இடம்பெயர்வின் போது அதை அழிக்கிறோம். இரண்டாவதாக, பயன்பாடு தொடங்கும் போது தரவுத்தளம் ஏற்றப்படும். எல்லாம் ஒன்றாக பொருந்துகிறது.

Realm தரவுத்தளத்தில் என்ன தவறு

பயன்பாட்டின் வாழ்நாள் முழுவதும் தரவுத்தளத்தின் உள்ளடக்கங்கள் எவ்வாறு மாறுகின்றன என்பதை நாங்கள் சரிபார்க்கத் தொடங்கினோம், முதல் நிறுவலில் இருந்து மேலும் செயலில் பயன்படுத்தும்போது. நீங்கள் Realm தரவுத்தளத்தின் உள்ளடக்கங்களை இதன் மூலம் பார்க்கலாம் ஸ்டெத்தோ அல்லது இன்னும் விரிவாகவும் தெளிவாகவும் கோப்பைத் திறப்பதன் மூலம் ரியல்ம் ஸ்டுடியோ. ADB வழியாக தரவுத்தளத்தின் உள்ளடக்கங்களைப் பார்க்க, Realm தரவுத்தளக் கோப்பை நகலெடுக்கவும்:

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

வெவ்வேறு நேரங்களில் தரவுத்தளத்தின் உள்ளடக்கங்களைப் பார்த்த பிறகு, ஒரு குறிப்பிட்ட வகை பொருள்களின் எண்ணிக்கை தொடர்ந்து அதிகரித்து வருவதைக் கண்டறிந்தோம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை
படம் இரண்டு கோப்புகளுக்கான ரியல்ம் ஸ்டுடியோவின் ஒரு பகுதியைக் காட்டுகிறது: இடதுபுறத்தில் - நிறுவலுக்குப் பிறகு சிறிது நேரம் பயன்பாட்டுத் தளம், வலதுபுறம் - செயலில் பயன்பாட்டிற்குப் பிறகு. பொருள்களின் எண்ணிக்கையைக் காணலாம் ImageEntity и MoneyType கணிசமாக வளர்ந்துள்ளது (ஸ்கிரீன்ஷாட் ஒவ்வொரு வகை பொருட்களின் எண்ணிக்கையைக் காட்டுகிறது).

தரவுத்தள வளர்ச்சிக்கும் தொடக்க நேரத்திற்கும் இடையிலான உறவு

கட்டுப்பாடற்ற தரவுத்தள வளர்ச்சி மிகவும் மோசமாக உள்ளது. ஆனால் இது பயன்பாட்டு தொடக்க நேரத்தை எவ்வாறு பாதிக்கிறது? ActivityManager மூலம் இதை அளவிடுவது மிகவும் எளிது. ஆண்ட்ராய்டு 4.4 முதல், லாக்கேட் லாக் காட்டப்படும் சரம் மற்றும் நேரத்துடன் பதிவைக் காட்டுகிறது. இந்த நேரம் பயன்பாடு தொடங்கப்பட்ட தருணத்திலிருந்து செயல்பாட்டு ரெண்டரிங் முடியும் வரையிலான இடைவெளிக்கு சமம். இந்த நேரத்தில், பின்வரும் நிகழ்வுகள் நிகழ்கின்றன:

  • செயல்முறையைத் தொடங்கவும்.
  • பொருள்களின் துவக்கம்.
  • செயல்பாடுகளின் உருவாக்கம் மற்றும் துவக்கம்.
  • அமைப்பை உருவாக்குதல்.
  • விண்ணப்ப ரெண்டரிங்.

நமக்கு பொருந்தும். -S மற்றும் -W கொடிகளுடன் ADBஐ இயக்கினால், தொடக்க நேரத்துடன் நீட்டிக்கப்பட்ட வெளியீட்டைப் பெறலாம்:

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

அங்கிருந்து பிடுங்கினால் grep -i WaitTime நேரம், நீங்கள் இந்த அளவீட்டின் சேகரிப்பை தானியங்குபடுத்தலாம் மற்றும் முடிவுகளை பார்வைக்கு பார்க்கலாம். கீழேயுள்ள வரைபடம், பயன்பாட்டின் தொடக்க நேரத்தின் எண்ணிக்கையில் பயன்பாட்டின் தொடக்க நேரத்தின் சார்புநிலையைக் காட்டுகிறது.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

அதே நேரத்தில், தரவுத்தளத்தின் அளவு மற்றும் வளர்ச்சிக்கு இடையிலான உறவின் அதே தன்மை இருந்தது, இது 4 MB இலிருந்து 15 MB வரை வளர்ந்தது. மொத்தத்தில், காலப்போக்கில் (குளிர் தொடக்கத்தின் வளர்ச்சியுடன்), பயன்பாட்டு வெளியீட்டு நேரம் மற்றும் தரவுத்தளத்தின் அளவு இரண்டும் அதிகரித்தன. எங்கள் கைகளில் ஒரு கருதுகோள் உள்ளது. இப்போது எஞ்சியிருப்பது சார்புநிலையை உறுதிப்படுத்துவதுதான். எனவே, "கசிவுகளை" அகற்ற முடிவு செய்தோம், மேலும் இது வெளியீட்டை விரைவுபடுத்துமா என்று பார்க்கவும்.

முடிவற்ற தரவுத்தள வளர்ச்சிக்கான காரணங்கள்

"கசிவுகளை" அகற்றுவதற்கு முன், அவை ஏன் முதலில் தோன்றின என்பதைப் புரிந்துகொள்வது மதிப்பு. இதை செய்ய, Realm என்றால் என்ன என்பதை நினைவில் கொள்வோம்.

Realm என்பது தொடர்பில்லாத தரவுத்தளமாகும். ஆண்ட்ராய்டில் எத்தனை ORM தொடர்புடைய தரவுத்தளங்கள் விவரிக்கப்பட்டுள்ளன என்பதைப் போலவே பொருள்களுக்கு இடையிலான உறவுகளை விவரிக்க இது உங்களை அனுமதிக்கிறது. அதே நேரத்தில், Realm பொருட்களை நேரடியாக நினைவகத்தில் குறைந்த அளவு மாற்றங்கள் மற்றும் வரைபடங்களுடன் சேமிக்கிறது. இது வட்டில் இருந்து தரவை மிக விரைவாகப் படிக்க உங்களை அனுமதிக்கிறது, இது Realm இன் வலிமை மற்றும் அது ஏன் விரும்பப்படுகிறது.

(இந்த கட்டுரையின் நோக்கங்களுக்காக, இந்த விளக்கம் எங்களுக்கு போதுமானதாக இருக்கும். நீங்கள் Realm பற்றி மேலும் படிக்கலாம் ஆவணங்கள் அல்லது அவர்களின் கலைக்கூடம்).

பல டெவலப்பர்கள் தொடர்புடைய தரவுத்தளங்களுடன் (உதாரணமாக, ஹூட்டின் கீழ் SQL உடன் ORM தரவுத்தளங்கள்) அதிகமாக வேலை செய்யப் பழகிவிட்டனர். தரவு நீக்கம் போன்ற விஷயங்கள் பெரும்பாலும் கொடுக்கப்பட்டதாகத் தெரிகிறது. ஆனால் சாம்ராஜ்யத்தில் இல்லை.

மூலம், அடுக்கை நீக்கும் அம்சம் நீண்ட காலமாக கேட்கப்பட்டது. இது திருத்தம் и மற்றொன்று, அதனுடன் தொடர்புடையது, தீவிரமாக விவாதிக்கப்பட்டது. அது விரைவில் நிறைவேறும் என்ற எண்ணம் ஏற்பட்டது. ஆனால் பின்னர் எல்லாம் வலுவான மற்றும் பலவீனமான இணைப்புகளை அறிமுகப்படுத்தியது, இது தானாகவே இந்த சிக்கலை தீர்க்கும். இந்தப் பணியில் மிகவும் சுறுசுறுப்பாகவும் சுறுசுறுப்பாகவும் இருந்தார் கோரிக்கையை இழுக்கவும், உள் பிரச்சனைகளால் தற்போது இடைநிறுத்தப்பட்டுள்ளது.

கேஸ்கேடிங் நீக்கம் இல்லாமல் தரவு கசிவு

இல்லாத கேஸ்கேடிங் நீக்கத்தை நீங்கள் நம்பினால், தரவு சரியாக எப்படி கசியும்? நீங்கள் Realm பொருட்களை உள்ளமைத்திருந்தால், அவை நீக்கப்பட வேண்டும்.
ஒரு (கிட்டத்தட்ட) உண்மையான உதாரணத்தைப் பார்ப்போம். நம்மிடம் ஒரு பொருள் இருக்கிறது 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()

வண்டியில் உள்ள தயாரிப்பு ஒரு படம் உட்பட பல்வேறு துறைகளைக் கொண்டுள்ளது ImageEntity, தனிப்பயனாக்கப்பட்ட பொருட்கள் CustomizationEntity. மேலும், வண்டியில் உள்ள தயாரிப்பு அதன் சொந்த தயாரிப்புகளுடன் ஒரு கலவையாக இருக்கலாம் RealmList (CartProductEntity). பட்டியலிடப்பட்ட புலங்கள் அனைத்தும் Realm ஆப்ஜெக்ட்கள். அதே ஐடியுடன் ஒரு புதிய பொருளை (copyToRealm() / copyToRealmOrUpdate()) செருகினால், இந்த பொருள் முழுமையாக மேலெழுதப்படும். ஆனால் அனைத்து உள் பொருள்களும் (படம், தனிப்பயனாக்கம் மற்றும் கார்ட்காம்போ தயாரிப்புகள்) பெற்றோருடனான தொடர்பை இழந்து தரவுத்தளத்தில் இருக்கும்.

அவர்களுடனான இணைப்பு துண்டிக்கப்பட்டதால், நாங்கள் அவற்றைப் படிக்கவோ அல்லது நீக்கவோ மாட்டோம் (நாங்கள் அவற்றை வெளிப்படையாக அணுகும் வரை அல்லது முழு "அட்டவணை" அழிக்கும் வரை). இதை "நினைவக கசிவுகள்" என்று அழைத்தோம்.

நாம் Realm உடன் பணிபுரியும் போது, ​​எல்லா உறுப்புகளையும் வெளிப்படையாகச் சென்று, அத்தகைய செயல்பாடுகளுக்கு முன் அனைத்தையும் வெளிப்படையாக நீக்க வேண்டும். இதை செய்ய முடியும், எடுத்துக்காட்டாக, இது போன்றது:

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()
}
// и потом уже сохраняем

நீங்கள் இதைச் செய்தால், எல்லாம் சரியாக வேலை செய்யும். இந்த எடுத்துக்காட்டில், படம், customizationEntity மற்றும் cartComboProducts ஆகியவற்றிற்குள் வேறு உள்ளமைக்கப்பட்ட Realm ஆப்ஜெக்ட்கள் இல்லை என்று கருதுகிறோம், எனவே வேறு உள்ளமைக்கப்பட்ட சுழல்கள் மற்றும் நீக்கல்கள் எதுவும் இல்லை.

விரைவான தீர்வு

நாங்கள் செய்ய முடிவு செய்த முதல் விஷயம், வேகமாக வளர்ந்து வரும் பொருட்களை சுத்தம் செய்து, இது எங்களின் அசல் பிரச்சனையை தீர்க்குமா என்று பார்க்க முடிவுகளை சரிபார்க்கவும். முதலில், எளிமையான மற்றும் மிகவும் உள்ளுணர்வு தீர்வு செய்யப்பட்டது, அதாவது: ஒவ்வொரு பொருளும் அதன் குழந்தைகளை அகற்றுவதற்கு பொறுப்பாக இருக்க வேண்டும். இதைச் செய்ய, அதன் உள்ளமைக்கப்பட்ட Realm பொருட்களின் பட்டியலை வழங்கும் ஒரு இடைமுகத்தை நாங்கள் அறிமுகப்படுத்தினோம்:

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

நாங்கள் அதை எங்கள் சாம்ராஜ்யப் பொருட்களில் செயல்படுத்தினோம்:

@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 நாங்கள் எல்லா குழந்தைகளையும் ஒரு தட்டையான பட்டியலாகத் தருகிறோம். ஒவ்வொரு குழந்தைப் பொருளும் NestedEntityAware இடைமுகத்தை செயல்படுத்தலாம், எடுத்துக்காட்டாக, நீக்குவதற்கு உள் Realm ஆப்ஜெக்ட்கள் உள்ளன என்பதைக் குறிக்கிறது. 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
   )
 }
}

மேலும், பொருட்களின் கூடு மீண்டும் மீண்டும் செய்யப்படலாம்.

அனைத்து உள்ளமை பொருட்களையும் மீண்டும் மீண்டும் நீக்கும் முறையை எழுதுகிறோம். முறை (நீட்டிப்பாக செய்யப்பட்டது) deleteAllNestedEntities அனைத்து உயர்மட்ட பொருள்களையும் முறைகளையும் பெறுகிறது deleteNestedRecursively NestedEntityAware இடைமுகத்தைப் பயன்படுத்தி அனைத்து உள்ளமை பொருட்களையும் மீண்டும் மீண்டும் நீக்குகிறது:

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()
   }
 }
}

வேகமாக வளரும் பொருட்களைக் கொண்டு இதைச் செய்து என்ன நடந்தது என்பதைச் சரிபார்த்தோம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

இதன் விளைவாக, இந்த தீர்வுடன் நாங்கள் மூடிய அந்த பொருள்கள் வளர்வதை நிறுத்திவிட்டன. மேலும் அடித்தளத்தின் ஒட்டுமொத்த வளர்ச்சி குறைந்தது, ஆனால் நிற்கவில்லை.

"சாதாரண" தீர்வு

அடித்தளம் மெதுவாக வளர ஆரம்பித்தாலும், அது இன்னும் வளர்ந்தது. எனவே நாங்கள் மேலும் பார்க்க ஆரம்பித்தோம். எங்கள் திட்டம் Realm இல் தரவு கேச்சிங்கை மிகவும் செயலில் பயன்படுத்துகிறது. எனவே, ஒவ்வொரு பொருளுக்கும் உள்ளமைக்கப்பட்ட அனைத்து பொருட்களையும் எழுதுவது உழைப்பு-தீவிரமானது, மேலும் பிழைகளின் ஆபத்து அதிகரிக்கிறது, ஏனெனில் குறியீட்டை மாற்றும் போது பொருட்களைக் குறிப்பிட மறந்துவிடலாம்.

நான் இடைமுகங்களைப் பயன்படுத்தவில்லை என்பதை உறுதிப்படுத்த விரும்பினேன், ஆனால் எல்லாமே சொந்தமாக வேலை செய்தன.

நாம் ஏதாவது சொந்தமாக வேலை செய்ய விரும்பினால், நாம் பிரதிபலிப்பைப் பயன்படுத்த வேண்டும். இதைச் செய்ய, ஒவ்வொரு வகுப்பு புலத்திலும் சென்று அது ஒரு Realm பொருளா அல்லது பொருட்களின் பட்டியலா என்பதைச் சரிபார்க்கலாம்:

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

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

புலம் RealmModel அல்லது RealmList ஆக இருந்தால், இந்த புலத்தின் பொருளை உள்ளமைக்கப்பட்ட பொருட்களின் பட்டியலில் சேர்க்கவும். எல்லாம் நாம் மேலே செய்ததைப் போலவே உள்ளது, இங்கே மட்டுமே அது தானாகவே செய்யப்படும். அடுக்கை நீக்கும் முறை மிகவும் எளிமையானது மற்றும் இது போல் தெரிகிறது:

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()
         }
       }
 }
}

நீட்டிப்பு filterRealmObject Realm பொருட்களை மட்டும் வடிகட்டி அனுப்புகிறது. முறை getNestedRealmObjects பிரதிபலிப்பு மூலம், அது அனைத்து உள்ளமை Realm பொருட்களை கண்டுபிடித்து அவற்றை ஒரு நேரியல் பட்டியலில் வைக்கிறது. பிறகு அதையே மீண்டும் மீண்டும் செய்கிறோம். நீக்கும் போது, ​​பொருளின் செல்லுபடியை சரிபார்க்க வேண்டும் isValid, ஏனென்றால் வெவ்வேறு பெற்றோர் பொருள்கள் ஒரே மாதிரியானவற்றைக் கொண்டிருக்கலாம். இதைத் தவிர்த்து, புதிய பொருட்களை உருவாக்கும் போது, ​​ஐடியின் தானாக உருவாக்குவதைப் பயன்படுத்துவது நல்லது.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

getNestedRealmObjects முறையின் முழு செயலாக்கம்

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)
}

இதன் விளைவாக, எங்கள் கிளையன்ட் குறியீட்டில் ஒவ்வொரு தரவு மாற்றியமைக்கும் செயல்பாட்டிற்கும் “கேஸ்கேடிங் டெலிட்” ஐப் பயன்படுத்துகிறோம். எடுத்துக்காட்டாக, செருகும் செயல்பாட்டிற்கு இது போல் தெரிகிறது:

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 }
 ))
}

முதலில் முறை getManagedEntities அனைத்து சேர்க்கப்பட்ட பொருள்களையும் பெறுகிறது, பின்னர் முறை cascadeDelete புதிதாக எழுதும் முன் சேகரிக்கப்பட்ட அனைத்து பொருட்களையும் மீண்டும் மீண்டும் நீக்குகிறது. பயன்பாடு முழுவதும் இந்த அணுகுமுறையைப் பயன்படுத்துகிறோம். Realm இல் நினைவக கசிவுகள் முற்றிலும் போய்விட்டன. பயன்பாட்டின் குளிர் தொடக்கங்களின் எண்ணிக்கையில் தொடக்க நேரத்தைச் சார்ந்திருப்பதற்கான அதே அளவீட்டை மேற்கொண்ட பிறகு, முடிவைக் காண்கிறோம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

பச்சைக் கோடு, உள்ளமைக்கப்பட்ட பொருள்களின் தானாக அடுக்கை நீக்கும் போது குளிர் தொடக்கங்களின் எண்ணிக்கையில் பயன்பாட்டு தொடக்க நேரத்தைச் சார்ந்திருப்பதைக் காட்டுகிறது.

முடிவுகள் மற்றும் முடிவுகள்

தொடர்ந்து வளர்ந்து வரும் Realm தரவுத்தளமானது பயன்பாடு மிகவும் மெதுவாக தொடங்குவதற்கு காரணமாக இருந்தது. உள்ளமைக்கப்பட்ட பொருட்களின் எங்களின் சொந்த "கேஸ்கேடிங் டெலிட்" மூலம் புதுப்பிப்பை வெளியிட்டோம். இப்போது _app_start மெட்ரிக் மூலம் எங்களின் முடிவு பயன்பாட்டு வெளியீட்டு நேரத்தை எவ்வாறு பாதித்தது என்பதை நாங்கள் கண்காணித்து மதிப்பீடு செய்கிறோம்.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

பகுப்பாய்விற்கு, நாங்கள் 90 நாட்களை எடுத்துக்கொள்கிறோம் மற்றும் பார்க்கவும்: பயன்பாட்டின் தொடக்க நேரம், சராசரி மற்றும் 95 வது சதவீத பயனர்களின் மீது விழும், குறையத் தொடங்கியது மற்றும் இனி உயராது.

Realm இல் கேஸ்கேட் நீக்கம் எப்படி நீண்ட வெளியீட்டில் வெற்றி பெற்றது என்பது பற்றிய கதை

நீங்கள் ஏழு நாள் அட்டவணையைப் பார்த்தால், _app_start மெட்ரிக் முற்றிலும் போதுமானதாகத் தெரிகிறது மற்றும் 1 வினாடிக்கும் குறைவாக உள்ளது.

_app_start இன் சராசரி மதிப்பு 5 வினாடிகளுக்கு மேல் இருந்தால், முன்னிருப்பாக, Firebase அறிவிப்புகளை அனுப்பும் என்பதையும் சேர்த்துக் கொள்வது மதிப்பு. இருப்பினும், நாங்கள் பார்க்கிறபடி, நீங்கள் இதை நம்பக்கூடாது, மாறாக உள்ளே சென்று வெளிப்படையாக சரிபார்க்கவும்.

Realm தரவுத்தளத்தின் சிறப்பு என்னவென்றால், இது ஒரு தொடர்பு இல்லாத தரவுத்தளமாகும். அதன் பயன்பாட்டின் எளிமை, ORM தீர்வுகள் மற்றும் பொருள் இணைப்பு ஆகியவற்றுடன் ஒற்றுமை இருந்தபோதிலும், இது அடுக்கை நீக்குதல் இல்லை.

இது கணக்கில் எடுத்துக்கொள்ளப்படாவிட்டால், உள்ளமைக்கப்பட்ட பொருள்கள் குவிந்து "கசிந்துவிடும்." தரவுத்தளம் தொடர்ந்து வளரும், இது பயன்பாட்டின் மந்தநிலை அல்லது தொடக்கத்தை பாதிக்கும்.

Realm இல் உள்ள பொருட்களை எவ்வாறு விரைவாக நீக்குவது என்பது பற்றிய எங்கள் அனுபவத்தைப் பகிர்ந்து கொண்டேன், இது இன்னும் பெட்டியில் இல்லை, ஆனால் நீண்ட காலமாகப் பேசப்படுகிறது அவர்கள் சொல்கிறார்கள் и அவர்கள் சொல்கிறார்கள். எங்கள் விஷயத்தில், இது பயன்பாட்டின் தொடக்க நேரத்தை பெரிதும் துரிதப்படுத்தியது.

இந்த அம்சத்தின் உடனடி தோற்றம் பற்றிய விவாதம் இருந்தபோதிலும், Realm இல் அடுக்கு நீக்கம் இல்லாதது வடிவமைப்பால் செய்யப்படுகிறது. நீங்கள் ஒரு புதிய பயன்பாட்டை வடிவமைக்கிறீர்கள் என்றால், இதை கணக்கில் எடுத்துக்கொள்ளவும். நீங்கள் ஏற்கனவே Realm ஐப் பயன்படுத்துகிறீர்கள் என்றால், உங்களுக்கு இதுபோன்ற சிக்கல்கள் உள்ளதா எனச் சரிபார்க்கவும்.

ஆதாரம்: www.habr.com

கருத்தைச் சேர்