Realm හි කඳුරැල්ල මකා දැමීම දිගු දියත් කිරීමකින් ජයග්‍රහණය කළ ආකාරය පිළිබඳ කතාව

සියලුම පරිශීලකයින් ජංගම යෙදුම්වල වේගවත් දියත් කිරීම සහ ප්‍රතිචාරාත්මක UI ලබා ගනී. යෙදුම දියත් කිරීමට බොහෝ කාලයක් ගත වුවහොත්, පරිශීලකයාට දුක සහ කෝපය දැනෙන්නට පටන් ගනී. ඔබට පහසුවෙන් පාරිභෝගික අත්දැකීම නරක් කළ හැකිය, නැතහොත් පරිශීලකයා යෙදුම භාවිතා කිරීමට පෙර පවා ඔහු සම්පූර්ණයෙන්ම අහිමි කළ හැකිය.

Dodo Pizza යෙදුම සාමාන්‍යයෙන් දියත් කිරීමට තත්පර 3ක් ගත වන බවත්, සමහර "වාසනාවන්තයින්" සඳහා තත්පර 15-20ක් ගත වන බවත් අපි වරක් සොයා ගත්තෙමු.

කප්පාදුවට පහළින් සතුටුදායක අවසානයක් සහිත කතාවකි: Realm දත්ත සමුදායේ වර්ධනය, මතක කාන්දුවක්, අපි කැදලි වස්තු රැස් කර ගත් ආකාරය සහ පසුව අපවම එකට ඇදගෙන සියල්ල නිවැරදි කළ ආකාරය ගැන.

Realm හි කඳුරැල්ල මකා දැමීම දිගු දියත් කිරීමකින් ජයග්‍රහණය කළ ආකාරය පිළිබඳ කතාව

Realm හි කඳුරැල්ල මකා දැමීම දිගු දියත් කිරීමකින් ජයග්‍රහණය කළ ආකාරය පිළිබඳ කතාව
ලිපි කර්තෘ: මැක්සිම් කචින්කින් - Dodo Pizza හි Android සංවර්ධක.

යෙදුම් නිරූපකය මත ක්ලික් කිරීමෙන් පළමු ක්‍රියාකාරකමේ onResume() දක්වා තත්පර තුනක් අනන්තය වේ. සමහර පරිශීලකයින් සඳහා, ආරම්භක කාලය තත්පර 15-20 දක්වා ළඟා විය. මෙය පවා හැකි වන්නේ කෙසේද?

කියවීමට කාලය නොමැති අය සඳහා ඉතා කෙටි සාරාංශයක්
අපගේ Realm දත්ත සමුදාය නිමක් නැතිව වර්ධනය විය. සමහර කැදලි වස්තු මකා නොදැමූ නමුත් නිරන්තරයෙන් එකතු විය. යෙදුම් ආරම්භක කාලය ක්රමයෙන් වැඩි විය. ඉන්පසුව අපි එය සවි කළ අතර, ආරම්භක කාලය ඉලක්කය වෙත පැමිණියේය - එය තත්පර 1 ට වඩා අඩු වූ අතර තවදුරටත් වැඩි නොවීය. ලිපියේ තත්වය පිළිබඳ විශ්ලේෂණයක් සහ විසඳුම් දෙකක් අඩංගු වේ - ඉක්මන් එකක් සහ සාමාන්‍ය එකක්.

ගැටලුව සෙවීම සහ විශ්ලේෂණය

අද, ඕනෑම ජංගම යෙදුමක් ඉක්මනින් දියත් කළ යුතු අතර ප්‍රතිචාර දැක්විය යුතුය. නමුත් එය ජංගම යෙදුම ගැන පමණක් නොවේ. සේවාවක් සහ සමාගමක් සමඟ අන්තර්ක්‍රියා කිරීමේ පරිශීලක අත්දැකීම සංකීර්ණ දෙයකි. උදාහරණයක් ලෙස, අපගේ නඩුවේදී, බෙදාහැරීමේ වේගය පීසා සේවාව සඳහා ප්රධාන දර්ශකයන්ගෙන් එකකි. බෙදා හැරීම වේගවත් නම්, පීසා උණුසුම් වනු ඇත, දැන් කන්න කැමති පාරිභෝගිකයාට වැඩි වේලාවක් බලා සිටීමට සිදු නොවේ. යෙදුම සඳහා, වේගවත් සේවාවක් පිළිබඳ හැඟීමක් ඇති කිරීම වැදගත් වේ, මන්ද යෙදුම දියත් කිරීමට තත්පර 20 ක් ගතවේ නම්, ඔබට පීසා සඳහා කොපමණ කාලයක් බලා සිටීමට සිදුවේද?

මුලදී, සමහර විට යෙදුම දියත් කිරීමට තත්පර කිහිපයක් ගත වූ බවට අපටම මුහුණ දීමට සිදු වූ අතර, පසුව එය කොපමණ කාලයක් ගතවේද යන්න පිළිබඳව අනෙකුත් සගයන්ගෙන් පැමිණිලි ඇසීමට පටන් ගත්තේය. නමුත් මේ තත්ත්වය දිගින් දිගටම නැවත ඇති කිරීමට අපට නොහැකි විය.

එය කොපමණ කාලයක්ද? අනුව Google ලේඛන, යෙදුමක සීතල ආරම්භයක් තත්පර 5 කට වඩා අඩු කාලයක් ගතවේ නම්, මෙය "සාමාන්‍ය ලෙස" සලකනු ලැබේ. Dodo Pizza Android යෙදුම දියත් කරන ලදී (ෆයර්බේස් ප්‍රමිතික අනුව _app_start) හිදී සීතල ආරම්භය සාමාන්‍යයෙන් තත්පර 3 කින් - ඔවුන් පවසන පරිදි “විශිෂ්ට නොවේ, භයානක නොවේ”.

නමුත් පසුව පැමිණිලි පෙනෙන්නට පටන් ගත්තේ යෙදුම දියත් කිරීමට ඉතා, ඉතා, ඉතා දිගු කාලයක් ගත වූ බවයි! ආරම්භ කිරීම සඳහා, "ඉතා, ඉතා, ඉතා දිගු" යනු කුමක්දැයි මැනීමට අපි තීරණය කළෙමු. ඒ වගේම අපි මේ සඳහා Firebase trace භාවිතා කළා යෙදුම ආරම්භයේ ලුහුබැඳීම.

Realm හි කඳුරැල්ල මකා දැමීම දිගු දියත් කිරීමකින් ජයග්‍රහණය කළ ආකාරය පිළිබඳ කතාව

මෙම සම්මත හෝඩුවාව මඟින් පරිශීලකයා යෙදුම විවෘත කරන මොහොත සහ පළමු ක්‍රියාකාරකමේ onResume() ක්‍රියාත්මක වන මොහොත අතර කාලය මනිනු ලබයි. Firebase Console හි මෙම මෙට්‍රික් _app_start ලෙස හැඳින්වේ. එය සිදු වූයේ:

  • මධ්‍ය සීතල ආරම්භක කාලය තත්පර 95කට වඩා අඩු වුවද, 20 වැනි ප්‍රතිශතයට වඩා වැඩි පරිශීලකයින් සඳහා ආරම්භක වේලාවන් තත්පර 5කට ආසන්න වේ (සමහර ඊටත් වඩා දිගු).
  • ආරම්භක කාලය නියත අගයක් නොවේ, නමුත් කාලයත් සමඟ වර්ධනය වේ. නමුත් සමහර විට බිංදු ඇත. අපි විශ්ලේෂණයේ පරිමාණය දින 90 දක්වා වැඩි කළ විට මෙම රටාව අපට හමු විය.

Realm හි කඳුරැල්ල මකා දැමීම දිගු දියත් කිරීමකින් ජයග්‍රහණය කළ ආකාරය පිළිබඳ කතාව

සිතිවිලි දෙකක් හිතට ආවා:

  1. යමක් කාන්දු වේ.
  2. මෙම "යමක්" මුදා හැරීමෙන් පසු නැවත සකස් කර නැවත කාන්දු වේ.

"සමහරවිට දත්ත සමුදාය සමඟ ඇති දෙයක්," අපි සිතුවා, අපි හරි. පළමුව, අපි දත්ත සමුදාය හැඹිලියක් ලෙස භාවිතා කරමු; සංක්‍රමණයේදී අපි එය ඉවත් කරමු. දෙවනුව, යෙදුම ආරම්භ වන විට දත්ත සමුදාය පටවනු ලැබේ. සෑම දෙයක්ම එකට ගැලපේ.

Realm දත්ත ගබඩාවේ ඇති වැරැද්ද කුමක්ද

පළමු ස්ථාපනයේ සිට සහ තවදුරටත් සක්‍රිය භාවිතයේදී යෙදුමේ ආයු කාලය පුරාවට දත්ත සමුදායේ අන්තර්ගතය වෙනස් වන ආකාරය අපි පරීක්ෂා කිරීමට පටන් ගත්තෙමු. ඔබට Realm දත්ත ගබඩාවේ අන්තර්ගතය මේ හරහා බැලිය හැක ස්ටෙතෝ හෝ හරහා ගොනුව විවෘත කිරීමෙන් වඩාත් විස්තරාත්මකව සහ පැහැදිලිව Realm Studio. ADB හරහා දත්ත සමුදායේ අන්තර්ගතය බැලීමට, Realm දත්ත සමුදා ගොනුව පිටපත් කරන්න:

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

විවිධ කාලවලදී දත්ත සමුදායේ අන්තර්ගතය දෙස බැලීමෙන්, යම් ආකාරයක වස්තූන් සංඛ්යාව නිරන්තරයෙන් වැඩි වන බව අපට පෙනී ගියේය.

Realm හි කඳුරැල්ල මකා දැමීම දිගු දියත් කිරීමකින් ජයග්‍රහණය කළ ආකාරය පිළිබඳ කතාව
පින්තූරයේ ගොනු දෙකක් සඳහා Realm Studio හි කොටසක් පෙන්වයි: වම් පසින් - යෙදුම් පදනම ස්ථාපනය කිරීමෙන් ටික වේලාවකට පසුව, දකුණු පසින් - සක්‍රිය භාවිතයෙන් පසු. වස්තු සංඛ්යාව බව දැක ගත හැකිය ImageEntity и MoneyType සැලකිය යුතු ලෙස වර්ධනය වී ඇත (තිර රුව එක් එක් වර්ගයේ වස්තූන් ගණන පෙන්වයි).

දත්ත සමුදා වර්ධනය සහ ආරම්භක කාලය අතර සම්බන්ධතාවය

පාලනයකින් තොරව දත්ත සමුදා වර්ධනය ඉතා නරක ය. නමුත් මෙය යෙදුම් ආරම්භක වේලාවට බලපාන්නේ කෙසේද? ActivityManager හරහා මෙය මැනීම තරමක් පහසුය. Android 4.4 සිට, logcat දර්ශණය වන තන්තුව සහ වේලාව සමඟ ලොගය පෙන්වයි. මෙම කාලය යෙදුම දියත් කළ මොහොතේ සිට ක්‍රියාකාරකම් විදැහුම්කරණය අවසන් වන තෙක් පරතරයට සමාන වේ. මෙම කාලය තුළ පහත සිදුවීම් සිදු වේ:

  • ක්රියාවලිය ආරම්භ කරන්න.
  • වස්තූන් ආරම්භ කිරීම.
  • ක්රියාකාරකම් නිර්මාණය කිරීම සහ ආරම්භ කිරීම.
  • පිරිසැලසුමක් නිර්මාණය කිරීම.
  • යෙදුම් විදැහුම්කරණය.

අපිට ගැලපෙනවා. ඔබ -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 ගැන වැඩිදුර කියවන්න පුළුවන් ලියකියවිලි හෝ ඔවුන්ගේ ඇකඩමිය).

බොහෝ සංවර්ධකයින් සම්බන්ධිත දත්ත සමුදායන් සමඟ වැඩිපුර වැඩ කිරීමට පුරුදු වී ඇත (උදාහරණයක් ලෙස, HOOD යටතේ SQL සහිත ORM දත්ත සමුදායන්). තවද දත්ත මකාදැමීම වැනි දේ බොහෝ විට ලබා දී ඇති බව පෙනේ. නමුත් Realm හි නොවේ.

මාර්ගය වන විට, කැස්කැඩ් මකාදැමීමේ විශේෂාංගය දිගු කාලයක් තිස්සේ ඉල්ලා ඇත. මෙය සංශෝධනය и තවත්, ඒ හා සම්බන්ධ, ක්රියාකාරීව සාකච්ඡා කරන ලදී. එය ඉක්මනින් ඉටු වේ යැයි හැඟීමක් ඇති විය. නමුත් පසුව සෑම දෙයක්ම ශක්තිමත් සහ දුර්වල සබැඳි හඳුන්වාදීමට පරිවර්තනය කර ඇති අතර එමඟින් මෙම ගැටළුව ස්වයංක්‍රීයව විසඳනු ඇත. මෙම කාර්යයේදී තරමක් සජීවී හා ක්‍රියාශීලී විය අදින්න ඉල්ලීම, අභ්‍යන්තර අපහසුතා හේතුවෙන් දැනට නවතා දමා ඇත.

මකාදැමීමකින් තොරව දත්ත කාන්දු වීම

ඔබ නොපවතින කැස්කැඩින් මකාදැමීම මත රඳා පවතින්නේ නම් හරියටම දත්ත කාන්දු වන්නේ කෙසේද? ඔබ 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 objects වේ. අපි එකම හැඳුනුම්පත සමඟ නව වස්තුවක් (copyToRealm() / copyToRealmOrUpdate()) ඇතුළු කළහොත්, මෙම වස්තුව සම්පූර්ණයෙන්ම උඩින් ලියැවෙනු ඇත. නමුත් සියලුම අභ්‍යන්තර වස්තූන් (රූපය, අභිරුචිකරණEntity සහ cartComboProducts) මාපියන් සමඟ සම්බන්ධතාව නැති වී දත්ත ගබඩාවේ පවතිනු ඇත.

ඔවුන් සමඟ සම්බන්ධතාවය නැති වී ඇති බැවින්, අපි ඒවා තවදුරටත් කියවන්නේ හෝ මකා දමන්නේ නැත (අපි ඒවාට පැහැදිලිව ප්‍රවේශ වන්නේ නම් හෝ සම්පූර්ණ "වගුව" ඉවත් නොකරන්නේ නම්). අපි මෙය හැඳින්වූයේ "මතකය කාන්දු වීම" යනුවෙනි.

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

ඔබ මෙය කරන්නේ නම්, සියල්ල කළ යුතු පරිදි ක්‍රියාත්මක වනු ඇත. මෙම උදාහරණයේදී, රූපය, අභිරුචිකරණEntity, සහ cartComboProducts තුළ වෙනත් කැදලි Realm වස්තු නොමැති බව අපි උපකල්පනය කරමු, එබැවින් වෙනත් කැදැලි ලූප සහ මකාදැමීම් නොමැත.

"ඉක්මන්" විසඳුම

අපි මුලින්ම තීරණය කළේ වේගයෙන්ම වර්ධනය වන වස්තූන් පිරිසිදු කිරීම සහ අපගේ මුල් ගැටලුව විසඳන්නේ දැයි බැලීමට ප්රතිඵල පරීක්ෂා කිරීමයි. පළමුව, සරලම හා වඩාත්ම අවබෝධාත්මක විසඳුම සාදන ලදී, එනම්: සෑම වස්තුවක්ම එහි දරුවන් ඉවත් කිරීම සඳහා වගකිව යුතුය. මෙය සිදු කිරීම සඳහා, අපි එහි කැදලි Realm වස්තු ලැයිස්තුවක් ආපසු ලබා දෙන අතුරු මුහුණතක් හඳුන්වා දුන්නෙමු:

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

තවද අපි එය අපගේ Realm objects තුළ ක්‍රියාත්මක කළෙමු:

@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 objects පමණක් ෆිල්ටර් කර සම්මත කරයි. ක්රමය 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

අදහස් එක් කරන්න