【问题标题】:Parse query stalls main thread for up to a minute解析查询使主线程停止长达一分钟
【发布时间】:2015-06-02 12:42:30
【问题描述】:

我正在使用资产商店中的 Parse 包来保存我的 Unity3D 手机游戏 (iOS/Android) 的用户数据。现在我遇到了一个问题,即我所做的解析查询使我的统一主线程停滞了很长时间。我的印象是 Parse 的“任务”概念是为了避免这种情况,但不知何故它似乎不起作用。停止也发生在编辑器中,只有几秒钟,而在移动设备上最多需要一分钟。 query.FindAsync().ContinueWith(t => {myContinuationBlock});方法立即返回并执行后续调用。 Unity3d 主线程在查询执行几秒钟后停止,并且在 {myContinuationBlock} 中的代码执行之前立即停止。

我制作了这个问题的视频。在视频中您还可以看到只有 Unity 被停止,底部的(原生)iAd 不受影响:

https://www.youtube.com/watch?v=XWaCGk9Hbus(摊位时间为0:07-1:07)

这是我的查询代码(注意,这段代码运行没有问题。停顿发生在稍后,就在 ContinueWith 代码执行之前):

public static void RetrieveHighScores()
{
    DebugLog.Log ("start of RetrieveHighScores() method");
    try
    {
        ParseQuery<ParseUser> query = ParseUser.Query
        .WhereGreaterThan (_highScoreKey, 1)
        .WhereGreaterThan("updatedAt", DateTime.Now - TimeSpan.FromDays(1))
        .OrderByDescending(_score24HoursKey)
        .Limit (1000);

        DebugLog.Log ("query.FindAsync()");
        query.FindAsync().ContinueWith(t =>
        {
            try
            {
                if (t.IsFaulted || t.IsCanceled)
                {
                    DebugLog.Log("Retrieving 24 Hours High Scores Failed");
                }
                else
                {
                    DebugLog.Log("Retrieving 24 Hours High Scores successful! ");
                    IEnumerable<ParseUser> results = t.Result;
                    foreach(ParseUser user in results)
                    {
                        //doing something with user..
                    }
                    DebugLog.Log ("24 Hours High Scores processed. "+_24HourHighScoreList.Count.ToString()+" entries.");
                }
            }
            catch(System.Exception e)
            {
                DebugLog.Log("Failed to retrieve 24 Hours High Scores. Reason: " + e.Message);
            }
        });
        DebugLog.Log ("FindAsync() returned");
    }
    catch (System.Exception e)
    {
        DebugLog.Log("Failed to retrieve 24 Hours High Scores. Reason: " + e.Message);
    }

    try
    {
        ParseQuery<ParseUser>query = ParseUser.Query
        .WhereGreaterThan (_highScoreKey, 1)
        .OrderByDescending(_highScoreKey)
        .Limit (1000);

        DebugLog.Log ("query.FindAsync()");
        query.FindAsync().ContinueWith(t =>
        {
        DebugLog.Log("Retrieving Alltime High Scores successful! ");
                    IEnumerable<ParseUser> results = t.Result;
                    foreach(ParseUser user in results)
                    {
                        //doing something with user...
                    }
                    DebugLog.Log ("Alltime High Scores processed. "+_allTimeHighScoreList.Count.ToString()+" entries.");
        });
        DebugLog.Log ("FindAsync() returned");
    }
    catch (System.Exception e)
    {
        DebugLog.Log("Failed to retrieve alltime Highscores. Reason: " + e.Message);
    }
    DebugLog.Log ("end of RetrieveHighScores() method");
}

所以,我在停止后在控制台输出中看到的下一件事是

“检索历史最高分成功!”

现在,我知道我在这里查询 1000 个对象,是的,可能有更好的方法来实现高分,但我不明白为什么这段代码会停止我的 Unity3D 主线程?为什么有时会停顿一分钟,有时根本不明显?

这是一个严重的问题,因为我的游戏已经发布。它只是在用户数据库变大后才开始出现,现在我需要快速修复它。

如果我不调用 RetrieveHighScores() 函数,则不会发生停滞,因此它一定是在解析代码从服务器接收数据并将其传递给 ContinueWith 代码之后发生的事情。

如果我在停顿期间单击 XCode 中的暂停,我会看到以下内容:

Thread 1, Queue : com.apple.main-thread

#0  0x017eaeb0 in GC_mark_from ()

#1  0x017eb520 in GC_mark_some ()

#2  0x017e5d1c in GC_stopped_mark ()

#3  0x017e6228 in GC_try_to_collect_inner ()

#4  0x017e64f0 in GC_collect_or_expand ()

#5  0x017e6a38 in GC_allocobj ()

#6  0x017e957c in GC_generic_malloc_inner ()

#7  0x017e965c in GC_generic_malloc ()

#8  0x017e9920 in GC_malloc_atomic ()

#9  0x01783814 in mono_array_new_specific ()

#10 0x00c5886c in m_wrapper_managed_to_native_object___icall_wrapper_mono_array_new_specific_intptr_int at /Users/me/myproj/build/device/Libraries/mscorlib.dll.s:187982

#11 0x009ee54c in m_System_Text_RegularExpressions_Interpreter_ResetGroups at /Users/me/myproj/build/device/Libraries/System.dll.s:6462

#12 0x009eb864 in m_System_Text_RegularExpressions_Interpreter_Reset at /Users/me/myproj/build/device/Libraries/System.dll.s:5761

#13 0x009edb6c in m_157 at /Users/me/myproj/build/device/Libraries/System.dll.s:6244

#14 0x009ebc54 in m_155 at /Users/me/myproj/build/device/Libraries/System.dll.s:5813

#15 0x009eb804 in m_System_Text_RegularExpressions_Interpreter_Scan_System_Text_RegularExpressions_Regex_string_int_int at /Users/me/myproj/build/device/Libraries/System.dll.s:5745

#16 0x009f3ce8 in m_System_Text_RegularExpressions_Regex_Match_string_int at /Users/me/myproj/build/device/Libraries/System.dll.s:9106

#17 0x00370204 in m_Parse_Internal_Json_Accept_string_int_System_Text_RegularExpressions_Regex_int__System_Text_RegularExpressions_Match_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3770

#18 0x0036fa80 in m_Parse_Internal_Json_ParseString_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3577

#19 0x0036f56c in m_Parse_Internal_Json_ParseMember_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3447

#20 0x0036f3b8 in m_Parse_Internal_Json_ParseObject_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3413

#21 0x0036f99c in m_Parse_Internal_Json_ParseValue_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3553

#22 0x0036f780 in m_Parse_Internal_Json_ParseArray_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3500

#23 0x0036f9b8 in m_Parse_Internal_Json_ParseValue_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3556

#24 0x0036f5ec in m_Parse_Internal_Json_ParseMember_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3457

#25 0x0036f3b8 in m_Parse_Internal_Json_ParseObject_string_int_int__object_ at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3413

#26 0x0036e920 in m_Parse_Internal_Json_Parse_string at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:3143

#27 0x00383168 in m_Parse_ParseClient_DeserializeJsonString_string at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:13121

#28 0x0038381c in m_Parse_ParseClient__c__DisplayClass8__RequestAsyncb__7_System_Threading_Tasks_Task_1_System_Tuple_2_System_Net_HttpStatusCode_string at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:13363

#29 0x0036de50 in m_Parse_Internal_InternalExtensions__c__DisplayClass1_2__OnSuccessb__0_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:2697

#30 0x0036e04c in m_Parse_Internal_InternalExtensions__c__DisplayClass7_1__OnSuccessb__6_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:2788

#31 0x003a3a4c in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5__ContinueWithb__2 ()

#32 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#33 0x003a39bc in m_System_Threading_Tasks_Task__c__DisplayClass3_1__ContinueWithb__1_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31474

#34 0x003a4140 in m_System_Threading_Tasks_Task_1_RunContinuations at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31766

#35 0x003a4278 in m_System_Threading_Tasks_Task_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31801

#36 0x003a4654 in m_System_Threading_Tasks_TaskCompletionSource_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31950

#37 0x003a4fa0 in m_3d9 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:32334

#38 0x003a44b0 in m_System_Threading_Tasks_Task_1__c__DisplayClass1__ContinueWithb__0_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31872

#39 0x003a3b3c in m_System_Threading_Tasks_Task__c__DisplayClass8__ContinueWithb__7_System_Threading_Tasks_Task ()

#40 0x00519a84 in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5_int__ContinueWithb__2 ()

#41 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#42 0x004a9548 in m_1ce9 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:165091

#43 0x003a8dcc in m_System_Threading_Tasks_Task_ContinueWith_int_System_Func_2_System_Threading_Tasks_Task_int_System_Threading_CancellationToken at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:34526

#44 0x003a321c in m_System_Threading_Tasks_Task_ContinueWith_System_Action_1_System_Threading_Tasks_Task_System_Threading_CancellationToken at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31155

#45 0x003a3168 in m_System_Threading_Tasks_Task_ContinueWith_System_Action_1_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31129

#46 0x003a3fdc in m_System_Threading_Tasks_Task_1_ContinueWith_System_Action_1_System_Threading_Tasks_Task_1_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31721

#47 0x003a4ed4 in m_3d8 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:32304

#48 0x003a44b0 in m_System_Threading_Tasks_Task_1__c__DisplayClass1__ContinueWithb__0_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31872

#49 0x003a3b3c in m_System_Threading_Tasks_Task__c__DisplayClass8__ContinueWithb__7_System_Threading_Tasks_Task ()

#50 0x00519a84 in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5_int__ContinueWithb__2 ()

#51 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#52 0x004a9548 in m_1ce9 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:165091

#53 0x003a4140 in m_System_Threading_Tasks_Task_1_RunContinuations at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31766

#54 0x003a4278 in m_System_Threading_Tasks_Task_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31801

#55 0x003a4654 in m_System_Threading_Tasks_TaskCompletionSource_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31950

#56 0x003a3a60 in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5__ContinueWithb__2 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31498

#57 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#58 0x003a39bc in m_System_Threading_Tasks_Task__c__DisplayClass3_1__ContinueWithb__1_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31474

#59 0x003a4140 in m_System_Threading_Tasks_Task_1_RunContinuations at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31766

#60 0x003a4278 in m_System_Threading_Tasks_Task_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31801

#61 0x003a4654 in m_System_Threading_Tasks_TaskCompletionSource_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31950

#62 0x003a4fa0 in m_3d9 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:32334

#63 0x003a44b0 in m_System_Threading_Tasks_Task_1__c__DisplayClass1__ContinueWithb__0_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31872

#64 0x003a3b3c in m_System_Threading_Tasks_Task__c__DisplayClass8__ContinueWithb__7_System_Threading_Tasks_Task ()

#65 0x00519a84 in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5_int__ContinueWithb__2 ()

#66 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#67 0x004a9548 in m_1ce9 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:165091

#68 0x003a8dcc in m_System_Threading_Tasks_Task_ContinueWith_int_System_Func_2_System_Threading_Tasks_Task_int_System_Threading_CancellationToken at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:34526

#69 0x003a321c in m_System_Threading_Tasks_Task_ContinueWith_System_Action_1_System_Threading_Tasks_Task_System_Threading_CancellationToken at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31155

#70 0x003a3168 in m_System_Threading_Tasks_Task_ContinueWith_System_Action_1_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31129

#71 0x003a3fdc in m_System_Threading_Tasks_Task_1_ContinueWith_System_Action_1_System_Threading_Tasks_Task_1_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31721

#72 0x003a4ed4 in m_3d8 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:32304

#73 0x003a44b0 in m_System_Threading_Tasks_Task_1__c__DisplayClass1__ContinueWithb__0_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31872

#74 0x003a3b3c in m_System_Threading_Tasks_Task__c__DisplayClass8__ContinueWithb__7_System_Threading_Tasks_Task ()

#75 0x00519a84 in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5_int__ContinueWithb__2 ()

#76 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#77 0x004a9548 in m_1ce9 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:165091

#78 0x003a4140 in m_System_Threading_Tasks_Task_1_RunContinuations at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31766

#79 0x003a4278 in m_System_Threading_Tasks_Task_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31801

#80 0x003a4654 in m_System_Threading_Tasks_TaskCompletionSource_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31950

#81 0x003a3a60 in m_System_Threading_Tasks_Task__c__DisplayClass3_1__c__DisplayClass5__ContinueWithb__2 at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31498

#82 0x003a36b8 in m_System_Threading_Tasks_Task___cctorb__23_System_Action at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31346

#83 0x003a39bc in m_System_Threading_Tasks_Task__c__DisplayClass3_1__ContinueWithb__1_System_Threading_Tasks_Task at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31474

#84 0x003a4140 in m_System_Threading_Tasks_Task_1_RunContinuations at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31766

#85 0x003a4278 in m_System_Threading_Tasks_Task_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31801

#86 0x003a4654 in m_System_Threading_Tasks_TaskCompletionSource_1_TrySetResult_T at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:31950

#87 0x003a0848 in m_Parse_PlatformHooks__c__DisplayClass2f__c__DisplayClass35__RequestAsyncb__2a_UnityEngine_WWW at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:29764

#88 0x003a0334 in m_Parse_PlatformHooks__c__DisplayClass20__RegisterNetworkRequestb__1f at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:29572

#89 0x003a0dbc in m_Parse_PlatformHooks__RunDispatcherd__39_MoveNext at /Users/me/myproj/build/device/Libraries/Parse.Unity.dll.s:29915

#90 0x0126ecec in scripting_method_invoke(ScriptingMethod*, MonoObject*, ScriptingArguments&, MonoException**) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Scripting/Backend/Mono/ScriptingBackendApi_Mono.cpp:196

#91 0x01309390 in ScriptingInvocation::Invoke(MonoException**, bool) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Scripting/Backend/ScriptingInvocation.cpp:128

#92 0x0130935c in ScriptingInvocation::Invoke(MonoException**) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Scripting/Backend/ScriptingInvocation.cpp:113

#93 0x01309308 in bool ScriptingInvocation::Invoke<bool>(MonoException**) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Scripting/Backend/ScriptingInvocation.cpp:80

#94 0x012df7e4 in Coroutine::InvokeMoveNext(MonoException**) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Mono/Coroutine.cpp:196

#95 0x012df57c in Coroutine::Run() at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Mono/Coroutine.cpp:221

#96 0x012df544 in Coroutine::ContinueCoroutine(Object*, void*) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Mono/Coroutine.cpp:78

#97 0x012593c4 in DelayedCallManager::Update(int) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/GameCode/CallDelayed.cpp:164

#98 0x012d0630 in PlayerLoop(bool, bool, IHookEvent*) at /Applications/buildAgent/work/d63dfc6385190b60/Runtime/Misc/Player.cpp:1880

#99 0x01117878 in UnityPlayerLoop at /Applications/buildAgent/work/d63dfc6385190b60/PlatformDependent/iPhonePlayer/LibEntryPoint.mm:241

#100    0x00d2ff34 in -[UnityAppController(Rendering) repaint] at /Users/me/myproj/build/device/Classes/UnityAppController+Rendering.mm:55

似乎 parse 的 JSON 解析运行在主线程上,但为什么呢? 这是怎么回事?如何避免主线程停止?

//注意:偶尔,不会发生停顿(尽管查询成功) - 好像 Parse 有时会在另一个线程上成功解析,但大多数时候在主线程上解析。

【问题讨论】:

  • 不会解决你的问题,但会产生数据提交以解析方差.....创建一个批处理作业,应该在最佳状态下运行得非常快(例如批量文件上传,比如上传100 个 img 文件在正常条件下解析并使用多线程 httpclient 将需要 5 秒才能完成)。将进程包装在 shell 中并以 'time' 作为前缀 cmd 以随机间隔执行...
  • 不确定您所说的“将进程包装在 shell 中”是什么意思以及发送的具体内容是什么?问题不在于时间长,问题在于主线程卡住了
  • 如果您没有怀疑某些服务器端问题导致您在客户端上出现间歇性线程等待,那么我的评论是 N/A。我是 android 本地人,所以不能真正帮助团结。但我会通过操纵超时来跟踪 Http vals 来消除服务器问题...baeldung.com/httpclient-timeout
  • 为您快速解决问题。您可以尝试在协程中等待任务而不是继续。只需在 while 循环中生成任务,直到完成,然后在任务完成后处理失败/结果。

标签: multithreading performance unity3d parse-platform


【解决方案1】:

我建议,如果您将 Unity 分析器连接到您的设备,您会发现您的 Linq 查询正在创建大量垃圾 - 并且是您设备上的垃圾收集使您的主线程停滞不前.

重新实现你的排行榜功能,不要使用 Linq。 Linq 节省了程序员的时间——不是机器,不要在你的游戏中使用它。

【讨论】:

  • 我没有在我的代码中使用 Linq。可能实现是使用Linq?如何在不使用 Linq 的情况下查询数据库?编辑:顺便说一句,我没有投反对票-我认为您对 GC 的看法是正确的
  • 哦,我明白了,ParseUser.Query 语法在我看来很像 Linq。你查询的是什么类型的数据库?
猜你喜欢
  • 2012-12-30
  • 2012-08-01
  • 1970-01-01
  • 2015-06-28
  • 2013-05-05
  • 1970-01-01
  • 2014-09-26
  • 1970-01-01
  • 2019-01-26
相关资源
最近更新 更多