Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gatsby/cache-dir/loader.js eval's JSON on main thread, doesn't use fetch() #18787

Closed
slightlyoff opened this issue Oct 18, 2019 · 8 comments
Closed
Labels
stale? Issue that may be closed soon due to the original author not responding any more.

Comments

@slightlyoff
Copy link

Description

In traces like this one:
https://www.webpagetest.org/result/191017_J5_d438a3f9ef614a319b46a66ae936fb5b/1/details/#waterfall_view_step1

The way that Gatsby's loader.js evaluates JSON leads to long main-thread tasks. At core, this is because of the use of JSON.parse(responseText) from an XHR.

Use of the fetch() method would allow asynchronous and off-thread JSON decoding that would not block user interaction.

Steps to reproduce

See trace linked above.

Expected result

Large JSON files should not block the main thread.

Actual result

Large JSON files block the main thread when loaded.

@jayphelps
Copy link

jayphelps commented Oct 18, 2019

(Note: I’m not a Gatsby maintainer, just saw this ticket and I’m curious)

My understanding has been that using Response's await json() doesn't actually parse JSON off the main thread. Few years ago folks pointed this out on twitter when someone suggested using it as a more performant json parsing solution.

Testing right now in latest Chrome seems to confirm this is still the case, though I don't have time to put together an example that is easy to understand, here is at least an example:

MEGA HUGE WARNING PLEASE READ THIS FIRST: THIS LOADS 135 MB OF JSON YOU HAVE BEEN WARNED: https://jsbin.com/fizokeq/1/edit?js,output

It's always possible what I'm seeing is not parse times, but something else though? I haven’t yet looked to see if the spec would allow off thread parsing, but seemingly wouldn’t be observable (ignoring that “it resolves faster”)

@pieh
Copy link
Contributor

pieh commented Oct 18, 2019

Reason for not using fetch (when this code was written) was related to chrome doing double fetches when using

<link rel="preload" href="/some-path" as="fetch" />

and later on doing fetch request. We initially were using fetch but it was resulting in double requests (regardless of various possible configurations) - but it wasn't the problem with xhr. So we were presented with 2 choices, both with its own drawbacks at a time - either not use link preload, and use fetch, or use link preload and use xhr. At a time it seemed more beneficial to go with second option, but really both options were bad.

Related links:

It seems like now the issue in chrome is fixed now - there are no more double requests when using <link> and fetch with proper cross origin, so we should move that request back from xhr to fetch so we could leverage off main-thread json parsing

Thanks for bringing this issue up!

@sidharthachatterjee
Copy link
Contributor

(new Response(...)).body.json() is an alternative that is async. Posted here so we don't forget. Thanks @slightlyoff 👍

@KyleAMathews
Copy link
Contributor

Maybe we should just switch to (new Response(...)).body.json()? There's still a non-trivial number of people on older Chrome versions and this would be a quick change.

@pieh
Copy link
Contributor

pieh commented Oct 19, 2019

I've been doing some research on that and seems like using fetch or just (new Response(...)).json() doesn't really offload parsing off main thread (which was raised by @jayphelps) and it still blocks event loop:

  • Using fetch + response.json():
    fetch("huge.json").then(function(response) {
      console.log("[fetch] start parsing");
      response.json().then(function(json) {
        console.log("[fetch] finish parsing");
      });
    });
    Screenshot 2019-10-19 at 12 24 49
  • Using XHR + (new Response(...)).json():
    var req = new XMLHttpRequest();
    req.open("GET", "huge.json", true);
    req.onreadystatechange = function(aEvt) {
      if (req.readyState == 4) {
        if (req.status == 200) {
          var syntheticResponse = new Response(req.responseText);
          console.log("[xhr] start parsing");
          syntheticResponse.json().then(json => {
             console.log("[xhr] finish parsing");
          });
        }
      }
    };
    req.send(null);
    Screenshot 2019-10-19 at 12 37 11
    • Current method XHR + JSON.parse:
    var req = new XMLHttpRequest();
    req.open("GET", "huge.json", true);
    req.onreadystatechange = function(aEvt) {
      if (req.readyState == 4) {
        if (req.status == 200) {
          console.log("[xhr-blocking] start parsing");
          var json = JSON.parse(req.responseText);
          console.log("[xhr-blocking] finish parsing");
        }
      }
    };
    req.send(null);
    Screenshot 2019-10-19 at 12 41 16

I wasn't really comparing performance of those methods (too few runs for that), but it seems that none of them is great. We could potentially look into solutions like https://www.npmjs.com/package/bfj that yields control periodically allowing event loop to be handled, but I think better approach would be to make sure that user don't end up with those huge json files instead, because that's bigger issue.

@pieh
Copy link
Contributor

pieh commented Oct 20, 2019

Debugging chromium itself seems to confirm that fetch + json() still actually parse on main thread:

(lldb) bt
* thread #1, name = 'CrRendererMain', queue = 'com.apple.main-thread', stop reason = breakpoint 6.1
  * frame #0: 0x000000010a621185 libv8.dylib`v8::internal::JsonParser<unsigned char>::Parse(v8::internal::Isolate*, v8::internal::Handle<v8::internal::String>, v8::internal::Handle<v8::internal::Object>) [inlined] v8::internal::JsonParser<unsigned char>::ParseJson(this=0x00007ffee5ef9c70) at json-parser.cc:310:32 [opt]
    frame #1: 0x000000010a621185 libv8.dylib`v8::internal::JsonParser<unsigned char>::Parse(isolate=0x00007ffdf8000000, source=<unavailable>, reviver=Handle<v8::internal::Object> @ r15) at json-parser.h:146 [opt]
    frame #2: 0x000000010a19def7 libv8.dylib`v8::JSON::Parse(context=<unavailable>, json_string=<unavailable>) at api.cc:3048:22 [opt]
    frame #3: 0x000000019af4f775 libblink_core.dylib`blink::(anonymous namespace)::BodyJsonConsumer::DidFetchDataLoadedString(this=0x0000001c5e742c80, string=0x00007ffee5ef9fb0) at body.cc:147:9
    frame #4: 0x000000019af5b471 libblink_core.dylib`blink::BodyStreamBuffer::LoaderClient::DidFetchDataLoadedString(this=0x0000001403cc5a50, string=0x00007ffee5ef9fb0) at body_stream_buffer.cc:62:14
    frame #5: 0x000000019af6b66b libblink_core.dylib`blink::(anonymous namespace)::FetchDataLoaderAsString::OnStateChange(this=0x0000001403cc5988) at fetch_data_loader.cc:494:20
    frame #6: 0x00000001b932ecbb libblink_platform.dylib`blink::BufferingBytesConsumer::OnStateChange(this=0x0000002e515b64b0) at buffering_bytes_consumer.cc:181:13
    frame #7: 0x00000001b940b362 libblink_platform.dylib`blink::ResponseBodyLoader::DelegatingBytesConsumer::OnStateChange(this=0x0000001403cc5928) at response_body_loader.cc:187:33
    frame #8: 0x00000001b933830c libblink_platform.dylib`blink::DataPipeBytesConsumer::Notify(this=0x0000002e515b63c8, (null)=0) at data_pipe_bytes_consumer.cc:255:13
    frame #9: 0x00000001b933cbfc libblink_platform.dylib`void base::internal::FunctorTraits<void (blink::DataPipeBytesConsumer::*)(unsigned int), void>::Invoke<void (method=f0 81 33 b9 01 00 00 00 00 00 00 00 00 00 00 00, receiver_ptr=0x00007ffe0a797c20, args=0x00007ffee5efa8a4)(unsigned int), blink::Persistent<blink::DataPipeBytesConsumer> const&, unsigned int>(void (blink::DataPipeBytesConsumer::*)(unsigned int), blink::Persistent<blink::DataPipeBytesConsumer> const&, unsigned int&&) at bind_internal.h:498:12
    frame #10: 0x00000001b933cae6 libblink_platform.dylib`void base::internal::InvokeHelper<false, void>::MakeItSo<void (functor=0x00007ffe0a797c10, args=0x00007ffe0a797c20, args=0x00007ffee5efa8a4)(unsigned int), blink::Persistent<blink::DataPipeBytesConsumer> const&, unsigned int>(void (blink::DataPipeBytesConsumer::* const&)(unsigned int), blink::Persistent<blink::DataPipeBytesConsumer> const&, unsigned int&&) at bind_internal.h:598:12
    frame #11: 0x00000001b933ca77 libblink_platform.dylib`void base::internal::Invoker<base::internal::BindState<void (blink::DataPipeBytesConsumer::*)(unsigned int), blink::Persistent<blink::DataPipeBytesConsumer> >, void (unsigned int)>::RunImpl<void (functor=0x00007ffe0a797c10, bound=size=1, (null)=std::__1::index_sequence<0UL> @ 0x00007ffee5efa858, unbound_args=0x00007ffee5efa8a4)(unsigned int), std::__1::tuple<blink::Persistent<blink::DataPipeBytesConsumer> > const&, 0ul>(void (blink::DataPipeBytesConsumer::* const&)(unsigned int), std::__1::tuple<blink::Persistent<blink::DataPipeBytesConsumer> > const&, std::__1::integer_sequence<unsigned long, 0ul>, unsigned int&&) at bind_internal.h:671:12
    frame #12: 0x00000001b933c9fb libblink_platform.dylib`base::internal::Invoker<base::internal::BindState<void (blink::DataPipeBytesConsumer::*)(unsigned int), blink::Persistent<blink::DataPipeBytesConsumer> >, void (unsigned int)>::Run(base=0x00007ffe0a797bf0, unbound_args=0) at bind_internal.h:653:12
    frame #13: 0x00000001b933a691 libblink_platform.dylib`base::RepeatingCallback<void (unsigned int)>::Run(this=0x00007ffe0a798010, args=0) const & at callback.h:132:12
    frame #14: 0x00000001b933df9f libblink_platform.dylib`WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::RunInternal(callback=0x00007ffe0a798010, args=0x00007ffee5efa96c)>*, unsigned int&&) at functional.h:258:22
    frame #15: 0x00000001b933c733 libblink_platform.dylib`WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::Run(this=0x00007ffe0a797fc0, args=0) at functional.h:248:12
    frame #16: 0x00000001b933d55c libblink_platform.dylib`void base::internal::FunctorTraits<void (WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::*)(unsigned int), void>::Invoke<void (method=40 c6 33 b9 01 00 00 00 00 00 00 00 00 00 00 00, receiver_ptr=0x00007ffe0a7612f0, args=0x00007ffee5efabe4)>, void (unsigned int)>::*)(unsigned int), std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > const&, unsigned int>(void (WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::*)(unsigned int), std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > const&, unsigned int&&) at bind_internal.h:498:12
    frame #17: 0x00000001b933d446 libblink_platform.dylib`void base::internal::InvokeHelper<false, void>::MakeItSo<void (functor=0x00007ffe0a7612e0, args=0x00007ffe0a7612f0, args=0x00007ffee5efabe4)>, void (unsigned int)>::* const&)(unsigned int), std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > const&, unsigned int>(void (WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::* const&)(unsigned int), std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > const&, unsigned int&&) at bind_internal.h:598:12
    frame #18: 0x00000001b933d3d7 libblink_platform.dylib`void base::internal::Invoker<base::internal::BindState<void (WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::*)(unsigned int), std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > >, void (unsigned int)>::RunImpl<void (functor=0x00007ffe0a7612e0, bound=size=1, (null)=std::__1::index_sequence<0UL> @ 0x00007ffee5efab98, unbound_args=0x00007ffee5efabe4)>, void (unsigned int)>::* const&)(unsigned int), std::__1::tuple<std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > > const&, 0ul>(void (WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::* const&)(unsigned int), std::__1::tuple<std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > > const&, std::__1::integer_sequence<unsigned long, 0ul>, unsigned int&&) at bind_internal.h:671:12
    frame #19: 0x00000001b933d35b libblink_platform.dylib`base::internal::Invoker<base::internal::BindState<void (WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>::*)(unsigned int), std::__1::unique_ptr<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)>, std::__1::default_delete<WTF::ThreadCheckingCallbackWrapper<base::RepeatingCallback<void (unsigned int)>, void (unsigned int)> > > >, void (unsigned int)>::Run(base=0x00007ffe0a7612c0, unbound_args=0) at bind_internal.h:653:12
    frame #20: 0x00000001b933a691 libblink_platform.dylib`base::RepeatingCallback<void (unsigned int)>::Run(this=0x00007ffe0a79e6a8, args=0) const & at callback.h:132:12
    frame #21: 0x00000001b9339d8f libblink_platform.dylib`mojo::SimpleWatcher::DiscardReadyState(callback=0x00007ffe0a79e6a8, result=0, state=0x00007ffdc8d835f8)> const&, unsigned int, mojo::HandleSignalsState const&) at simple_watcher.h:194:14
    frame #22: 0x00000001b933a16c libblink_platform.dylib`void base::internal::FunctorTraits<void (*)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), void>::Invoke<void (function=(0x00007ffe0a79e6a0), args=0x00007ffe0a79e6a8, args=0x00007ffee5efadb4, args=0x00007ffdc8d835f8)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&>(void (* const&)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), base::RepeatingCallback<void (unsigned int)> const&, unsigned int&&, mojo::HandleSignalsState const&) at bind_internal.h:398:12
    frame #23: 0x00000001b933a08c libblink_platform.dylib`void base::internal::InvokeHelper<false, void>::MakeItSo<void (functor=(0x00007ffe0a79e6a0), args=0x00007ffe0a79e6a8, args=0x00007ffee5efadb4, args=0x00007ffdc8d835f8)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&>(void (* const&)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), base::RepeatingCallback<void (unsigned int)> const&, unsigned int&&, mojo::HandleSignalsState const&) at bind_internal.h:598:12
    frame #24: 0x00000001b933a01c libblink_platform.dylib`void base::internal::Invoker<base::internal::BindState<void (*)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), base::RepeatingCallback<void (unsigned int)> >, void (unsigned int, mojo::HandleSignalsState const&)>::RunImpl<void (functor=(0x00007ffe0a79e6a0), bound=size=1, (null)=std::__1::index_sequence<0UL> @ 0x00007ffee5efad58, unbound_args=0x00007ffee5efadb4, unbound_args=0x00007ffdc8d835f8)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), std::__1::tuple<base::RepeatingCallback<void (unsigned int)> > const&, 0ul>(void (* const&)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), std::__1::tuple<base::RepeatingCallback<void (unsigned int)> > const&, std::__1::integer_sequence<unsigned long, 0ul>, unsigned int&&, mojo::HandleSignalsState const&) at bind_internal.h:671:12
    frame #25: 0x00000001b9339f80 libblink_platform.dylib`base::internal::Invoker<base::internal::BindState<void (*)(base::RepeatingCallback<void (unsigned int)> const&, unsigned int, mojo::HandleSignalsState const&), base::RepeatingCallback<void (unsigned int)> >, void (unsigned int, mojo::HandleSignalsState const&)>::Run(base=0x00007ffe0a79e680, unbound_args=0, unbound_args=0x00007ffdc8d835f8) at bind_internal.h:653:12
    frame #26: 0x000000010e6bb387 libmojo_public_system_cpp.dylib`base::RepeatingCallback<void (unsigned int, mojo::HandleSignalsState const&)>::Run(this=0x00007ffee5efaed0, args=0, args=0x00007ffdc8d835f8) const & at callback.h:132:12
    frame #27: 0x000000010e6bafe0 libmojo_public_system_cpp.dylib`mojo::SimpleWatcher::OnHandleReady(this=0x0000002e515b63e8, watch_id=1, result=0, state=0x00007ffdc8d835f8) at simple_watcher.cc:292:14
    frame #28: 0x000000010e6bbe87 libmojo_public_system_cpp.dylib`void base::internal::FunctorTraits<void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), void>::Invoke<void (method=50 ad 6b 0e 01 00 00 00 00 00 00 00 00 00 00 00, receiver_ptr=0x00007ffdc8d835e0, args=0x00007ffdc8d835f0, args=0x00007ffdc8d835f4, args=0x00007ffdc8d835f8)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>(void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>&&, int&&, unsigned int&&, mojo::HandleSignalsState&&) at bind_internal.h:498:12
    frame #29: 0x000000010e6bbc66 libmojo_public_system_cpp.dylib`void base::internal::InvokeHelper<true, void>::MakeItSo<void (functor=0x00007ffdc8d835d0, weak_ptr=0x00007ffdc8d835e0, args=0x00007ffdc8d835f0, args=0x00007ffdc8d835f4, args=0x00007ffdc8d835f8)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>(void (mojo::SimpleWatcher::*&&)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>&&, int&&, unsigned int&&, mojo::HandleSignalsState&&) at bind_internal.h:618:5
    frame #30: 0x000000010e6bbb95 libmojo_public_system_cpp.dylib`void base::internal::Invoker<base::internal::BindState<void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>, void ()>::RunImpl<void (functor=0x00007ffdc8d835d0, bound=size=4, (null)=std::__1::index_sequence<0UL, 1UL, 2UL, 3UL> @ 0x00007ffee5efb158)(int, unsigned int, mojo::HandleSignalsState const&), std::__1::tuple<base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>, 0ul, 1ul, 2ul, 3ul>(void (mojo::SimpleWatcher::*&&)(int, unsigned int, mojo::HandleSignalsState const&), std::__1::tuple<base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>&&, std::__1::integer_sequence<unsigned long, 0ul, 1ul, 2ul, 3ul>) at bind_internal.h:671:12
    frame #31: 0x000000010e6bbae9 libmojo_public_system_cpp.dylib`base::internal::Invoker<base::internal::BindState<void (mojo::SimpleWatcher::*)(int, unsigned int, mojo::HandleSignalsState const&), base::WeakPtr<mojo::SimpleWatcher>, int, unsigned int, mojo::HandleSignalsState>, void ()>::RunOnce(base=0x00007ffdc8d835b0) at bind_internal.h:640:12
    frame #32: 0x000000010ceb7e6c libbase.dylib`base::OnceCallback<void ()>::Run(this=0x00007ffe0c01d200) && at callback.h:98:12
    frame #33: 0x000000010d0cb0b7 libbase.dylib`base::TaskAnnotator::RunTask(this=0x00007ffe0a02e868, trace_event_name="SequenceManager RunTask", pending_task=0x00007ffe0c01d200) at task_annotator.cc:142:33
    frame #34: 0x000000010d12a0b1 libbase.dylib`base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWorkImpl(this=0x00007ffe0a02e690, continuation_lazy_now=0x00007ffee5efbbc8, ran_task=0x00007ffee5efbbe7) at thread_controller_with_message_pump_impl.cc:365:23
    frame #35: 0x000000010d12a4cd libbase.dylib`base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::DoWork(this=0x00007ffe0a02e690) at thread_controller_with_message_pump_impl.cc:265:7
    frame #36: 0x000000010cf9096f libbase.dylib`base::MessagePumpCFRunLoopBase::RunWork(this=0x00007ffe0a02dba0) at message_pump_mac.mm:489:30
    frame #37: 0x000000010cf908dc libbase.dylib`::___ZN4base24MessagePumpCFRunLoopBase13RunWorkSourceEPv_block_invoke(.block_descriptor=0x00007ffee5efbce0) at message_pump_mac.mm:464:11
    frame #38: 0x000000010cf4f05a libbase.dylib`base::mac::CallWithEHFrame(void () block_pointer) at call_with_eh_frame_asm.S:36
    frame #39: 0x000000010cf8f965 libbase.dylib`base::MessagePumpCFRunLoopBase::RunWorkSource(info=0x00007ffe0a02dba0) at message_pump_mac.mm:463:3
    frame #40: 0x00007fff35e4d083 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
    frame #41: 0x00007fff35e4d029 CoreFoundation`__CFRunLoopDoSource0 + 108
    frame #42: 0x00007fff35e309eb CoreFoundation`__CFRunLoopDoSources0 + 195
    frame #43: 0x00007fff35e2ffb5 CoreFoundation`__CFRunLoopRun + 1189
    frame #44: 0x00007fff35e2f8be CoreFoundation`CFRunLoopRunSpecific + 455
    frame #45: 0x00007fff380938ef Foundation`-[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 280
    frame #46: 0x000000010cf914fc libbase.dylib`base::MessagePumpNSRunLoop::DoRun(this=0x00007ffe0a02dba0, delegate=0x00007ffe0a02e690) at message_pump_mac.mm:767:5
    frame #47: 0x000000010cf8f073 libbase.dylib`base::MessagePumpCFRunLoopBase::Run(this=0x00007ffe0a02dba0, delegate=0x00007ffe0a02e690) at message_pump_mac.mm:186:3
    frame #48: 0x000000010d12b1a6 libbase.dylib`base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl::Run(this=0x00007ffe0a02e690, application_tasks_allowed=true, timeout=(delta_ = 9223372036854775807)) at thread_controller_with_message_pump_impl.cc:463:12
    frame #49: 0x000000010d0428e2 libbase.dylib`base::RunLoop::Run(this=0x00007ffee5efd6e8) at run_loop.cc:156:14
    frame #50: 0x000000014491d502 libcontent.dylib`content::RendererMain(parameters=0x00007ffee5efd818) at renderer_main.cc:213:16
    frame #51: 0x0000000144de9281 libcontent.dylib`content::RunOtherNamedProcessTypeMain(process_type="renderer", main_function_params=0x00007ffee5efd818, delegate=0x00007ffee5efe2a8) at content_main_runner_impl.cc:571:14
    frame #52: 0x0000000144dea289 libcontent.dylib`content::ContentMainRunnerImpl::Run(this=0x00007ffe0a21c250, start_service_manager_only=false) at content_main_runner_impl.cc:890:10
    frame #53: 0x0000000144de5838 libcontent.dylib`content::ContentServiceManagerMainDelegate::RunEmbedderProcess(this=0x00007ffee5efe1d0) at content_service_manager_main_delegate.cc:52:32
    frame #54: 0x000000010ca09886 libembedder.dylib`service_manager::Main(params=0x00007ffee5efe1b8) at main.cc:423:29
    frame #55: 0x0000000144de90d9 libcontent.dylib`content::ContentMain(params=0x00007ffee5efe278) at content_main.cc:19:10
    frame #56: 0x0000000110cc000a libchrome_dll.dylib`::ChromeMain(argc=15, argv=0x00007ffee5efe448) at chrome_main.cc:110:12
    frame #57: 0x0000000109d01b7c Chromium Helper (Renderer)`main(argc=15, argv=0x00007ffee5efe448) at chrome_exe_main_mac.cc:101:8
    frame #58: 0x00007fff61d5e3d5 libdyld.dylib`start + 1
    frame #59: 0x00007fff61d5e3d5 libdyld.dylib`start + 1

So I would say using XHR (no need to polyfill it for ie) + JSON.parse (as Body::json() still execute v8::JSON::Parse on main thread) is better solution (same perf, more backward compatible).

Any thoughts on that part?

While it seems we can't really attack json parsing perf here, the bigger problem is that this site ended up with this massive json file, and we should look into implementing some perf budgets solutions into build process.

@gatsbot gatsbot bot added the stale? Issue that may be closed soon due to the original author not responding any more. label Nov 25, 2019
@gatsbot
Copy link

gatsbot bot commented Nov 25, 2019

Hiya!

This issue has gone quiet. Spooky quiet. 👻

We get a lot of issues, so we currently close issues after 30 days of inactivity. It’s been at least 20 days since the last update here.

If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!

As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 💪💜

@pieh
Copy link
Contributor

pieh commented Nov 25, 2019

I'll close this issue in favour of #19780 which is more actionable than this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stale? Issue that may be closed soon due to the original author not responding any more.
Projects
None yet
Development

No branches or pull requests

6 participants