আইওএস 5 এ দ্রুত এবং দক্ষ কোর ডেটা আমদানি কার্যকর করা হচ্ছে


101

প্রশ্ন : আমি কীভাবে আমার সন্তানের প্রসঙ্গে পিতামৃত প্রসঙ্গে পরিবর্তনগুলি দেখতে দেখতে পাব যাতে তারা আমার এনএসফ্যাচড্রিজাল্টস কনট্রোলারটিকে ইউআই আপডেট করতে ট্রিগার করে?

এখানে সেটআপ দেওয়া আছে:

আপনার কাছে এমন একটি অ্যাপ্লিকেশন পেয়েছে যা প্রচুর এক্সএমএল ডেটা ডাউনলোড করে এবং যুক্ত করে (প্রায় 2 মিলিয়ন রেকর্ড, প্রতিটি পাঠ্যের একটি সাধারণ অনুচ্ছেদের আকার) প্রায় .sqlite ফাইলটি প্রায় 500 এমবি আকারের হয়ে যায়। কোর ডেটাতে এই বিষয়বস্তুটি যুক্ত করতে সময় লাগে, তবে আপনি চান যে ব্যবহারকারী ক্রমবর্ধমানভাবে ডেটা স্টোরে লোড হওয়ার সাথে সাথে অ্যাপটি ব্যবহার করতে সক্ষম হন। এটি ব্যবহারকারীর কাছে অদৃশ্য এবং দুর্ভেদ্য হতে পারে যে প্রচুর পরিমাণে ডেটা চারপাশে স্থানান্তরিত হচ্ছে, সুতরাং কোনও ঝুলন্ত নেই, কোনও জিটটার নেই: মাখনের মতো স্ক্রোল। তবুও, অ্যাপটি আরও কার্যকর, এতে আরও বেশি পরিমাণে ডেটা যুক্ত করা হয়, তাই কোরা ডেটা স্টোরটিতে ডেটা যুক্ত হওয়ার জন্য আমরা চিরকাল অপেক্ষা করতে পারি না। কোডে এর অর্থ আমি আমদানি কোডে এই জাতীয় কোড এড়াতে চাই:

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];

অ্যাপ্লিকেশনটি আইওএস 5 কেবলমাত্র তাই এটি সমর্থন করার জন্য ধীরতম ডিভাইসটি একটি আইফোন 3GS।

আমার বর্তমান সমাধানটি বিকাশের জন্য আমি এখন পর্যন্ত যে সংস্থানগুলি ব্যবহার করেছি:

অ্যাপলের কোর ডেটা প্রোগ্রামিং গাইড: দক্ষতার সাথে ডেটা আমদানি করা

  • স্মৃতিশক্তি কম রাখার জন্য অটোরিলিজ পুল ব্যবহার করুন
  • সম্পর্কের ব্যয়। ফ্ল্যাট আমদানি করুন, তারপরে সম্পর্কের শেষে প্যাচ আপ করুন
  • আপনি যদি এটি সহায়তা করতে পারেন তবে জিজ্ঞাসা করবেন না, এটি ও (N ^ 2) পদ্ধতিতে জিনিসগুলি ধীর করে দেয়
  • ব্যাচগুলিতে আমদানি করুন: সংরক্ষণ করুন, পুনরায় সেট করুন, নিকাশ এবং পুনরাবৃত্তি করুন
  • আমদানিতে আনডো ম্যানেজারটি বন্ধ করুন

iDeveloper TV - কোর ডেটা পারফরম্যান্স

  • ৩ টি প্রসঙ্গ ব্যবহার করুন: মাস্টার, মূল এবং সীমাবদ্ধ প্রসঙ্গের প্রকারগুলি

iDeveloper TV - ম্যাক, আইফোন এবং আইপ্যাড আপডেটের জন্য মূল ডেটা

  • পারফর্মব্লক দিয়ে অন্যান্য কাতারে সাশ্রয় চালানো জিনিসগুলিকে দ্রুত করে তোলে।
  • এনক্রিপশন জিনিসগুলিকে ধীর করে দেয়, আপনি যদি পারেন তবে এটি বন্ধ করুন।

মার্কাস জারার দ্বারা কোর ডেটাতে বড় ডেটা সেটগুলি আমদানি এবং প্রদর্শন করা হচ্ছে

  • আপনি বর্তমান রান লুপকে সময় দিয়ে আমদানিটি ধীর করতে পারেন, যাতে ব্যবহারকারীর পক্ষে জিনিসগুলি স্বাচ্ছন্দ্য বোধ করে।
  • নমুনা কোড প্রমাণ করে যে বড় আমদানি করা এবং ইউআইকে প্রতিক্রিয়াশীল রাখা সম্ভব, তবে 3 টি প্রসঙ্গ এবং ডিস্কে অ্যাসিঙ্ক সংরক্ষণের মতো দ্রুত নয়।

আমার বর্তমান সমাধান

আমি NSManagedObjectContext এর 3 টি উদাহরণ পেয়েছি:

মাস্টার ম্যানেজডঅবজেক্ট কনটেক্সট - এটি এমন প্রসঙ্গ যা NSPers ContinStoreCoordinator রয়েছে এবং ডিস্কে সংরক্ষণের জন্য দায়বদ্ধ। আমি এটি করি তাই আমার সঞ্চয়গুলি অ্যাসিক্রোনাস হতে পারে এবং তাই খুব দ্রুত। আমি এটিকে এটির মতো লঞ্চটিতে তৈরি করেছি:

masterManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[masterManagedObjectContext setPersistentStoreCoordinator:coordinator];

mainManagedObjectContext - এটি ইউআই সর্বত্র ব্যবহার করা প্রসঙ্গ। এটি মাস্টার ম্যানেজডঅবজেক্ট কনটেক্সটের একটি শিশু। আমি এটি এর মতো তৈরি করি:

mainManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[mainManagedObjectContext setUndoManager:nil];
[mainManagedObjectContext setParentContext:masterManagedObjectContext];

ব্যাকগ্রাউন্ডকন্টেক্সট - এই প্রসঙ্গটি আমার এনএসওপেশন সাবক্লাসে তৈরি করা হয়েছে যা XML ডেটা কোর ডেটা আমদানির জন্য দায়ী responsible আমি এটিকে অপারেশনের মূল পদ্ধতিতে তৈরি করেছি এবং এটিকে সেখানে মাস্টার প্রসঙ্গে যুক্ত করব।

backgroundContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSConfinementConcurrencyType];
[backgroundContext setUndoManager:nil];
[backgroundContext setParentContext:masterManagedObjectContext];

এটি আসলে খুব দ্রুত কাজ করে। কেবলমাত্র এই 3 প্রসঙ্গের সেটআপ করে আমি 10x এর বেশি দ্বারা আমার আমদানির গতি উন্নত করতে সক্ষম হয়েছি! সত্য, এটি বিশ্বাস করা কঠিন। (এই প্রাথমিক নকশাটি স্ট্যান্ডার্ড কোর ডেটা টেম্পলেটটির অংশ হওয়া উচিত ...)

আমদানি প্রক্রিয়া চলাকালীন আমি 2 বিভিন্ন উপায়ে সংরক্ষণ করি। প্রতি 1000 আইটেম আমি পটভূমি প্রসঙ্গে সংরক্ষণ করি:

BOOL saveSuccess = [backgroundContext save:&error];

তারপরে আমদানি প্রক্রিয়া শেষে, আমি প্রধান / পিতামাতার প্রসঙ্গে সংরক্ষণ করি যা সম্ভবত, মূল প্রসঙ্গে সহ অন্যান্য শিশু প্রসঙ্গে পরিবর্তনের দিকে ধাক্কা দেয়:

[masterManagedObjectContext performBlock:^{
   NSError *parentContextError = nil;
   BOOL parentContextSaveSuccess = [masterManagedObjectContext save:&parentContextError];
}];

সমস্যা : সমস্যাটি হ'ল আমি এই ভিউটি পুনরায় লোড না করা পর্যন্ত আমার ইউআই আপডেট হবে না।

আমার কাছে একটি ইউআইটিবেল ভিউ সহ একটি সাধারণ ইউআইভিউ কনট্রোলার রয়েছে যা একটি এনএসফ্যাচডরেসাল্টস কন্ট্রোলার ব্যবহার করে ডেটা খাওয়ানো হচ্ছে। যখন আমদানি প্রক্রিয়াটি সম্পূর্ণ হয়, এনএসফ্যাচডেরসাল্টস কন্ট্রোলার পিতামাতা / মাস্টার প্রসঙ্গে কোনও পরিবর্তন আসে না এবং তাই ইউআই স্বয়ংক্রিয়ভাবে আপডেট হয় না যেমন আমি দেখতে অভ্যস্ত। আমি যদি ইউআইভিউউকন্ট্রোলারটিকে স্ট্যাকটি থেকে সরিয়ে ফেলে আবার লোড করি তবে সমস্ত ডেটা আছে there

প্রশ্ন : আমি কীভাবে আমার সন্তানের প্রসঙ্গে পিতামৃত প্রসঙ্গে পরিবর্তনগুলি দেখতে দেখতে পাব যাতে তারা আমার এনএসফ্যাচড্রিজাল্টস কনট্রোলারটিকে ইউআই আপডেট করতে ট্রিগার করে?

আমি নিম্নলিখিতটি চেষ্টা করেছি যা কেবলমাত্র অ্যাপ্লিকেশনটিকে স্তব্ধ করে তুলেছে:

- (void)saveMasterContext {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];    
    [notificationCenter addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];

    NSError *error = nil;
    BOOL saveSuccess = [masterManagedObjectContext save:&error];

    [notificationCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];
}

- (void)contextChanged:(NSNotification*)notification
{
    if ([notification object] == mainManagedObjectContext) return;

    if (![NSThread isMainThread]) {
        [self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:YES];
        return;
    }

    [mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}

26
সেরা গঠনের জন্য +1000000, এখন পর্যন্ত সর্বাধিক প্রস্তুত প্রশ্ন। আমারও একটি উত্তর আছে ... এটি টাইপ করতে কয়েক মিনিট সময় লাগবে যদিও ...
জডি হ্যাগিনস 11:32 এ 11:32

1
আপনি যখন বলছেন অ্যাপটি হ্যাং হয়েছে, এটি কোথায়? এটা কি করছে?
জডি হ্যাগিনস 11:32

দীর্ঘ সময় পরে এটি আনার জন্য দুঃখিত। আপনি কি দয়া করে পরিষ্কার করতে পারেন যে "ফ্ল্যাট আমদানি করুন, তারপরে সম্পর্কগুলি প্যাচ আপ করুন" এর অর্থ কী? সম্পর্ক স্থাপনের জন্য আপনার এখনও সেই জিনিসগুলি স্মৃতিতে থাকতে হবে না? আমি আপনার মতো অনুরূপ একটি সমাধান বাস্তবায়নের চেষ্টা করছি এবং স্মৃতিচারণের চিহ্নটি হ্রাস করতে আমি কিছুটা সাহায্য ব্যবহার করতে পারি।
আন্দ্রে স্প্রেগা

এই নিবন্ধের প্রথমটির সাথে লিঙ্কযুক্ত অ্যাপল ডক্স দেখুন। এটি এটি ব্যাখ্যা করে। শুভকামনা!
ডেভিড ওয়েস

1
সত্যিই খুব ভাল প্রশ্ন এবং আপনি আপনার সেট আপের যে বিবরণটি দিয়েছিলেন তা থেকে কয়েকটি ঝরঝরে কৌশল বেছে
নিয়েছি

উত্তর:


47

আপনার সম্ভবত মাস্টার এমওসিও সাফল্যের সাথে চালাতে হবে। এমওসি থাকার কোনও অর্থ নেই যে সংরক্ষণের জন্য শেষ পর্যন্ত অপেক্ষা করুন। এটির নিজস্ব থ্রেড রয়েছে, এবং এটি স্মৃতিশক্তিও কম রাখতে সহায়তা করবে।

তুমি লিখেছিলে:

তারপরে আমদানি প্রক্রিয়া শেষে, আমি প্রধান / পিতামাতার প্রসঙ্গে সংরক্ষণ করি যা সম্ভবত, মূল প্রসঙ্গে সহ অন্যান্য শিশু প্রসঙ্গে পরিবর্তনের দিকে ধাক্কা দেয়:

আপনার কনফিগারেশনে আপনার দুটি সন্তান রয়েছে (মূল এমওসি এবং ব্যাকগ্রাউন্ড এমওসি), উভয়ই "মাস্টার" হিসাবে প্যারেন্টেড।

আপনি যখন কোনও সন্তানের উপর সঞ্চয় করেন, তখন এটি পিতামাতার মধ্যে পরিবর্তনগুলি ধাক্কা দেয়। সেই এমওসি-র অন্যান্য শিশুরা পরের বার যখন আনতে হবে তখন ডেটা দেখতে পাবে ... তাদের স্পষ্টভাবে অবহিত করা হয়নি।

সুতরাং, যখন বিজি সংরক্ষণ করে, তখন এর ডেটা মাস্টারকে ঠেলে দেওয়া হয়। নোট করুন, তবে, যে মাস্টার সংরক্ষণ না করা অবধি এই ডেটাগুলির কোনওটিই ডিস্কে নেই। তদুপরি, মাস্টার ডিস্কে সংরক্ষণ না করা পর্যন্ত কোনও নতুন আইটেম স্থায়ী আইডি পাবে না।

আপনার দৃশ্যে, আপনি ডিডসেভ বিজ্ঞপ্তির সময় মাস্টার সেভ থেকে মার্জ করে ডেটা মেইন এমওসি তে টানছেন।

এটি কাজ করা উচিত, সুতরাং এটি কোথায় আছে "আমি ঝুঁকছি" সে সম্পর্কে আমি আগ্রহী। আমি নোট করব, আপনি ক্যানোনিকাল উপায়ে মূল এমওসি থ্রেডে চলছেন না (অন্তত আইওএস 5 এর জন্য নয়)।

এছাড়াও, আপনি সম্ভবত কেবলমাত্র মাস্টার এমওসি থেকে পরিবর্তনগুলি মার্জ করতে আগ্রহী (যদিও আপনার নিবন্ধন দেখে মনে হচ্ছে এটি কেবল এটির জন্যই)। আমি যদি আপডেট-অন-ডু-সেভ-নোটিফিকেশনটি ব্যবহার করি তবে আমি এটি করতাম ...

- (void)contextChanged:(NSNotification*)notification {
    // Only interested in merging from master into main.
    if ([notification object] != masterManagedObjectContext) return;

    [mainManagedObjectContext performBlock:^{
        [mainManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];

        // NOTE: our MOC should not be updated, but we need to reload the data as well
    }];
}

এখন, হ্যাং সম্পর্কিত আপনার আসল সমস্যাটি কী হতে পারে ... আপনি মাস্টারকে বাঁচাতে দুটি আলাদা কল দেখান। প্রথমটি তার নিজস্ব পারফর্মব্লকটিতে সুরক্ষিত রয়েছে, তবে দ্বিতীয়টি নয় (যদিও আপনি একটি পারফর্মব্লকটিতে সেভমাস্টারকন্টেক্সট কল করতে পারেন ...

তবে আমি এই কোডটিও পরিবর্তন করতাম ...

- (void)saveMasterContext {
    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];    
    [notificationCenter addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];

    // Make sure the master runs in it's own thread...
    [masterManagedObjectContext performBlock:^{
        NSError *error = nil;
        BOOL saveSuccess = [masterManagedObjectContext save:&error];
        // Handle error...
        [notificationCenter removeObserver:self name:NSManagedObjectContextDidSaveNotification object:masterManagedObjectContext];
    }];
}

তবে নোট করুন যে মেইন হ'ল মাস্টার একটি শিশু। সুতরাং, পরিবর্তনগুলি মার্জ করা উচিত নয়। পরিবর্তে, কেবলমাত্র মাস্টারে ডিডস্যাভের জন্য নজর রাখুন, এবং কেবল পুনর্নির্মাণ করুন! ডেটাটি ইতিমধ্যে আপনার পিতামাতার কাছে বসে আছে, কেবল আপনি এটি চাওয়ার জন্য অপেক্ষা করছেন। প্রথম স্থানে পিতামাতার মধ্যে ডেটা রাখার একটি সুবিধা।

বিবেচনা করার জন্য আরেকটি বিকল্প (এবং আমি আপনার ফলাফলগুলি সম্পর্কে আগ্রহী হতে আগ্রহী - এটি প্রচুর ডেটা) ...

ব্যাকগ্রাউন্ডে এমওসিকে মাস্টারের সন্তান বানানোর পরিবর্তে এটিকে মেইন-এর সন্তান হিসাবে গড়ে তুলুন।

এটি পান বিজি যতবার সাশ্রয় করবে ততবার স্বয়ংক্রিয়ভাবে মেইন-এ মেলে। এখন, মেইনকে সেভ কল করতে হবে, এবং তারপরে মাস্টারকে সেভ কল করতে হবে, তবে যাঁরা করছেন তারা পয়েন্টারগুলি সরিয়ে নিয়ে যাচ্ছে ... যতক্ষণ না মাস্টার ডিস্কে সংরক্ষণ না করে।

এই পদ্ধতির সৌন্দর্য হ'ল ডেটা ব্যাকগ্রাউন্ড এমওসি থেকে সরাসরি আপনার অ্যাপ্লিকেশন এমওসি-তে যায় (তারপরে সেভ করার জন্য দিয়ে যায়)।

নেই কিছু পাস-থ্রু শাস্তি কিন্তু সব ভারী উত্তোলন কর্তা সম্পন্ন হলে তা ডিস্ক হিট। এবং যদি আপনি পারফর্মব্লক দিয়ে মাস্টারের উপর সেভ করে থাকেন তবে মূল থ্রেডটি কেবল অনুরোধটি প্রেরণ করে, এবং সঙ্গে সঙ্গে ফিরে আসে।

আমার এটা যায় কিভাবে জানাতে অনুগ্রহ করে!


দুর্দান্ত উত্তর। আমি আজ এই ধারণাগুলি চেষ্টা করব এবং আমি কী আবিষ্কার করেছি তা দেখতে পাবো। ধন্যবাদ!
ডেভিড ওয়েইস

অসাধারণ! পুরোপুরি কাজ! তবুও, আমি আপনার মাস্টার -> মেইন -> বিজি সম্পর্কে আপনার পরামর্শটি দেখতে যাচ্ছি এবং দেখুন যে অভিনয়টি কীভাবে কার্যকর হয়, এটি একটি খুব আকর্ষণীয় ধারণা বলে মনে হচ্ছে। দুর্দান্ত ধারণা জন্য আপনাকে ধন্যবাদ!
ডেভিড ওয়েইস

4
পারফর্মব্লকএন্ডওয়েটকে পারফর্মব্লকটিতে পরিবর্তন করতে আপডেট হয়েছে। কেন এটি আমার কাতারে আবার পপ আপ হয়েছে তা নিশ্চিত নয়, তবে আমি যখন এটি পড়লাম তখন তা স্পষ্ট ছিল ... আমি কেন আগে যেতে দিয়েছি তা নিশ্চিত নয়। হ্যাঁ, পারফর্মব্লকএন্ডওয়েট পুনরায় প্রবেশকারী। তবে, এর মতো নেস্টেড পরিবেশে, আপনি পিতামাতার প্রসঙ্গে কোনও সন্তানের প্রসঙ্গে সিঙ্ক্রোনাস সংস্করণটি কল করতে পারবেন না। বিজ্ঞপ্তিটি মূল প্রসঙ্গে পাঠানো হতে পারে (এই ক্ষেত্রে হয়), যা কোনও অচলাবস্থার কারণ হতে পারে। আমি আশা করি যে যারা পরে আসে এবং এটি পরে পড়েন তাদের কাছে এটি স্পষ্ট হবে। ধন্যবাদ, ডেভিড
জোডি হ্যাগিন্স

1
@ ডেভিডউইস আপনি কি মাস্টার -> মেইন -> বিজি চেষ্টা করেছেন? আমি এই নকশার ধরণটিতে আগ্রহী এবং এটি আপনার পক্ষে ভাল কাজ করে কিনা তা জানতে আশা করি। ধন্যবাদ.
ননামেলাইভ

2
মাস্টার -> মেইন -> বিজি প্যাটার্নের বিষয়টি হ'ল আপনি যখন বিজি প্রসঙ্গ থেকে আনবেন তখন এটি মেইন থেকেও নিয়ে আসবে এবং এটি ইউআইকে অবরুদ্ধ করবে এবং অ্যাপটিকে প্রতিক্রিয়াশীল করবে না
রোস্টিস্লাভ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.