Giter Club home page Giter Club logo

cppgraphqlgen's Introduction

Introduction

Windows macOS Linux

GraphQL and React go together like peanut butter and jelly, especially if you use a GraphQL client/compiler like Relay or Apollo.

But GraphQL services are only implemented on the server. When using React Native or React JS in a hybrid application, you typically have a native application which hosts islands or entire pages of UI rendered with React components, and you might like to display content that you've cached offline or that you otherwise generate on the client without needing to declare a separate data interface or require a server round trip to load it.

This project includes a graphqlservice library with the core functionality of a GraphQL service and a schemagen utility to generate types for your custom GraphQL service schema definition. Once you implement the pure virtual methods on the object interfaces and add hooks to the Relay Network Layer/Apollo Terminating Link to call your service, you can use the same GraphQL client code to access your native data source or a GraphQL service online. You might even be able to share some more of that code between a progressive web app and your native/hybrid app.

If what you're after is a way to consume a GraphQL service from C++, this project also includes a graphqlclient library and a clientgen utility to generate types matching a GraphQL request document, its variables, and all of the serialization code you need to talk to a graphqlservice implementation. If you want to consume another service, you will need access to the schema definition (rather than the Introspection query results), and you will need be able to send requests along with any variables to the service and parse its responses into a graphql::response::Value (e.g. with the graphqljson library) in your code.

Related projects

The most complete examples I've built are related to GqlMAPI:

  • eMAPI: Windows-only Electron app which lets you access the MAPI interface used by Microsoft Outlook. Its goal is to be a spiritual successor to a debugging and diagnostic tool called MFCMAPI.
  • electron-gqlmapi: Native module for Electron which hosts GqlMAPI in eMAPI. It includes JS libraries for calling the native module across the Electron IPC channel.
  • Tauri-GqlMAPI: Reimplementation of eMAPI built in Rust and TypeScript on top of Tauri.
  • gqlmapi-rs: Rust crate I built to expose safe bindings for GqlMAPI. It is loosely based on electron-gqlmapi, and it is used by Tauri-GqlMAPI.

I created a couple of sample projects to demonstrate integrating the schema.today.graphql service into an Electron app. The schema.today.graphql schema and service implementation in TodayMock.* are focused on testing, so the specific bootstrapping used in these projects should not be re-used, but you can use them as a scaffold to start your own integration with Electron or Node.js. They're available under my personal account, and I recently updated them to match the latest release of cppgraphqlgen:

  • electron-cppgraphql: Node Native Module which compiles against the version of the Node headers included in Electron. This was the starting point for electron-gqlmapi, and it is still useful as a sample because it does not depend on a platform-specific API like MAPI, so it works cross-platform.
  • cppgraphiql: Electron app which consumes electron-cppgraphql and exposes an instance of GraphiQL on top of it.

Feel free to use either or both of these as a starting point to integrate your own generated service with Node, Electron, or Tauri. PRs with links to your own samples are always welcome.

Getting Started

Installation process

The minimum OS and toolchain versions I've tested with this version of cppgraphqlgen are:

  • Microsoft Windows: Visual Studio 2019
  • Linux: Ubuntu 20.04 LTS with gcc 10.3.0
  • macOS: 11 (Big Sur) with AppleClang 13.0.0.

The key compiler requirement is support for C++20 including coroutines and concepts. Some of these compiler versions still treat coroutine support as experimental, and the CMake configuration can auto-detect that, but earlier versions of gcc and clang do not seem to have enough support for C++20.

The easiest way to build and install cppgraphqlgen is to use microsoft/vcpkg. See the Getting Started section of the vcpkg README for details. Once you have that configured, run vcpkg install cppgraphqlgen (or cppgraphqlgen:x64-windows, cppgraphqlgen:x86-windows-static, etc. depending on your platform). That will build and install all of the dependencies for cppgraphqlgen, and then build cppgraphqlgen itself without any other setup. The cppgraphqlgen package (and its dependencies) are advertised to the CMake find_package function through the -DCMAKE_TOOLCHAIN_FILE=<...>/scripts/buildsystems/vcpkg.cmake parameter/variable. There are more details about this in the vcpkg documentation.

If you want to build cppgraphqlgen yourself, you can do that with CMake from a clone or archive of this repo. See the Build and Test section below for instructions. You will need to install the dependencies first where find_package can find them. If vcpkg works otherwise, you can do that with vcpkg install pegtl boost-program-options rapidjson gtest. Some of these are optional, if for example you do not build the tests. If vcpkg does not work, please see the documentation for each of those dependencies, as well as your platform/toolchain documentation for perferred installation mechanisms. You may need to build some or all of them separately from source.

Software dependencies

The build system for this project uses CMake. You will need to have CMake (at least version 3.15.0) installed, and the library dependencies need to be where CMake can find them. Otherwise you need to disable the options which depend on them.

Besides the MIT license for this project, if you redistribute any source code or binaries built from these library dependencies, you should still follow the terms of their individual licenses. As of this writing, this library and all of its dependencies are available under either the MIT License or the Boost Software License (BSL). Both licenses roughly mean that you may redistribute them freely as long as you include an acknowledgement along with the license text. Please see the license or copyright notice which comes with each project for more details.

graphqlpeg

  • GraphQL parsing: Parsing Expression Grammar Template Library (PEGTL) release 3.2.6, which is part of The Art of C++ library collection. I've added this as a sub-module, so you do not need to install this separately. If you already have 3.2.6 installed where CMake can find it, it will use that instead of the sub-module and avoid installing another copy of PEGTL.

graphqlservice

The core library depends on graphqlpeg and it references the PEGTL headers itself at build time. Both of those mean it depends on PEGTL as well.

graphqljson (GRAPHQL_USE_RAPIDJSON=ON)

  • JSON support: RapidJSON release 1.1.0. If you don't need JSON support, you can also avoid installing this dependency. You will need to set GRAPHQL_USE_RAPIDJSON=OFF in your CMake configuration to do that.

schemagen

I'm using Boost for schemagen:

Usage:  schemagen [options] <schema file> <output filename prefix> <output namespace>
Command line options:
  --version              Print the version number
  -? [ --help ]          Print the command line options
  -v [ --verbose ]       Verbose output including generated header names as
                         well as sources
  -s [ --schema ] arg    Schema definition file path
  -p [ --prefix ] arg    Prefix to use for the generated C++ filenames
  -n [ --namespace ] arg C++ sub-namespace for the generated types
  --source-dir arg       Target path for the <prefix>Schema.cpp source file
  --header-dir arg       Target path for the <prefix>Schema.h header file
  --stubs                Unimplemented fields throw runtime exceptions instead
                         of compiler errors
  --no-introspection     Do not generate support for Introspection

I've tested this with several versions of Boost going back to 1.65.0. I expect it will work fine with most versions of Boost after that. The Boost dependencies are only used by the schemagen utility at or before your build, so you probably don't need to redistribute it or the Boost libraries with your project.

If you are building shared libraries on Windows (DLLs) using vcpkg or BUILD_SHARED_LIBS=ON in CMake, be aware that this adds a runtime dependency on a Boost DLL. The schemagen tool won't run without it. However, in addition to automating the install of Boost, vcpkg also takes care of installing the dependencies next to schemagen.exe when building the Windows and UWP shared library targets (the platform triplets which don't end in -static).

clientgen

The clientgen utility is based on schemagen and shares the same external dependencies. The command line arguments are almost the same, except it takes an extra file for the request document and there is no equivalent to --stubs:

Usage:  clientgen [options] <schema file> <request file> <output filename prefix> <output namespace>
Command line options:
  --version              Print the version number
  -? [ --help ]          Print the command line options
  -v [ --verbose ]       Verbose output including generated header names as
                         well as sources
  -s [ --schema ] arg    Schema definition file path
  -r [ --request ] arg   Request document file path
  -o [ --operation ] arg Operation name if the request document contains more
                         than one
  -p [ --prefix ] arg    Prefix to use for the generated C++ filenames
  -n [ --namespace ] arg C++ sub-namespace for the generated types
  --source-dir arg       Target path for the <prefix>Client.cpp source file
  --header-dir arg       Target path for the <prefix>Client.h header file
  --no-introspection     Do not expect support for Introspection

This utility should output one header and one source file for each request document. A request document may contain more than one operation, in which case it will output definitions for all of them together. You may limit the output to a single operation from the request document by specifying the --operation (or -o) argument with the operation name.

The generated code depends on the graphqlclient library for serialization of built-in types. If you link the generated code, you'll also need to link graphqlclient, graphqlpeg for the pre-parsed, pre-validated request AST, and graphqlresponse for the graphql::response::Value implementation.

Sample output for clientgen is in the sub-directories of samples/client, and several of them are consumed by unit tests in test/ClientTests.cpp.

tests (GRAPHQL_BUILD_TESTS=ON)

  • Unit testing: Google Test for the unit testing framework. If you don't want to build or run the unit tests, you can avoid this dependency as well by setting GRAPHQL_BUILD_TESTS=OFF in your CMake configuration.

API references

See GraphQLService.h for the base types implemented in the graphql::service namespace.

Take a look at the samples/learn directory, starting with StarWarsData.cpp to see a sample implementation of a custom schema defined in schema.learn.graphql. This is the same schema and sample data used in the GraphQL tutorial on https://graphql.org/learn/. This directory builds an interactive command line application which can execute query and mutation operations against the sample data in memory.

There are several helper functions for CMake declared in cmake/cppgraphqlgen-functions.cmake, which is automatically included if you use find_package(cppgraphqlgen) in your own CMake project. See samples/learn/schema/CMakeLists.txt and samples/learn/CMakeLists.txt, or the CMakeLists.txt files in some of the other samples sub-directories for examples of how to use them to automatically rerun the code generators and update the files in your source directory.

Migrating from v3.x to main

Please see the Migration Guide for v4.x for more details about upgrading to from the v3.x branch to the main branch. Active development takes place almost entirely in main.

Additional Documentation

There are some more targeted documents in the doc directory:

Samples

All of the samples are under samples, with nested sub-directories for generated files:

  • samples/today: There are two different samples generated from schema.today.graphql in this directory. The default schema target includes Introspection support (which is the default), while the nointrospection target demonstrates how to disable Introspection support with the schemagen --no-introspection parameter. The mock implementation of the service for both schemas is in samples/today/TodayMock.h and samples/today/TodayMock.cpp. It builds an interactive sample/sample_nointrospection and benchmark/benchmark_nointrospection target for each version, and it uses each of them in several unit tests.
  • samples/client: Several sample queries built with clientgen against the schema.today.graphql schema shared with samples/today. It includes a client_benchmark executable for comparison with benchmark executables using the same hardcoded query in [samples/today/]. The benchmark links with the default schema target in samples/today to handle the benchmark query.
  • samples/learn: Simpler standalone which builds a learn_star_wars executable that follows the tutorial examples on https://graphql.org/learn/.
  • samples/validation: This schema is based on the examples and counter-examples from the Validation section of the October 2021 GraphQL spec. There is no implementation of this schema, it relies entirely generated stubs (created with schemagen --stubs) to build successfully without defining more than placeholder objects fo the Query, Mutation, and Subscription operations in samples/validation/ValidationMock.h. It is used to test the validation logic with every example or counter-example in the spec in test/ValidationTests.cpp.
  • samples/proxy (GRAPHQL_BUILD_HTTP_SAMPLE=ON): Generates a client and server pair of executables which proxy requests from the client to the server over HTTP (on port 8080 for localhost). The HTTP support in both samples comes from Boost.Beast, which must be included in your Boost installation to build this directory. If you are using vcpkg, it will install the necessary Boost components on demand. Note: This directory uses the Boost Software License because the samples borrow heavily from examples in the Boost.Beast documentation.

Build and Test

Visual Studio on Windows

Use the Open Folder command to open the root of the repo. If you've installed the dependencies with vcpkg and run its Visual Studio integration command, Visual Studio should know how to build each of the targets in this project automatically.

Once you've built the project Visual Studio's Test Explorer window should list the unit tests, and you can run all of them from there.

Command Line on any platform

Your experience will vary depending on your build toolchain. The same instructions should work for any platform that CMake supports. These basic steps will build and run the tests. You can add options to build in another target directory, change the config from Debug (default) to Release, use another build tool like Ninja, etc. If you are using vcpkg to install the dependencies, remember to specify the -DCMAKE_TOOLCHAIN_FILE=... option when you run the initial build configuration.

  • Create a build directory: "mkdir build && cd build"
  • Configure the build system: "cmake .."
  • Tell CMake to invoke the build system: "cmake --build ." You can repeat this step to rebuild your changes.
  • CTest comes with CMake and runs the tests: "ctest ." Run this frequently, and make sure it passes before commits.

You can then optionally install the public outputs by configuring it with Release:

  • cmake -DCMAKE_BUILD_TYPE=Release ..
  • cmake --build . --target install You probably need to use sudo on Unix to do this.

Interactive tests

If you want to try an interactive version, you can run samples/today/sample or samples/today/sample_nointrospection and paste in queries against the same mock service or load a query from a file on the command line.

Reporting Security Issues

Security issues and bugs should be reported privately, via email, to the Microsoft Security Response Center (MSRC) at [email protected]. You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Further information, including the MSRC PGP key, can be found in the Security TechCenter.

Contributing

This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com.

When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA.

This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.

cppgraphqlgen's People

Contributors

andrewlipscomb avatar barbieri avatar bjoe avatar d-frey avatar matuskysel avatar mbodmer avatar mensinda avatar microsoft-github-policy-service[bot] avatar microsoftopensource avatar msftgits avatar nike4613 avatar sarcasm avatar wravery avatar yuval-k avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cppgraphqlgen's Issues

Calling two mutations at the same time from different requests run serially

I understand that the GraphQL spec calls for mutations called from the same request be executed serially, however currently two separate requests calling mutations at the same time are also run serially. How do we call resolve such that each request is treated as a different object and we can have two clients running mutations at the same time? I've tried creating a new Operations object prior to each resolve call, but it is still deferring execution of the second client's request until the first client's request is finished.

For example, when calling Client 1 and then calling Client 2 (3x) while Client 1 is executing:

Client 1

mutation a50 {
  sleep(time: 50)
}

Client 2

mutation a5 {
  sleep(time: 5)
}

Expected output (and output from the Graphene python library)

Starting to sleep for 50 seconds.
Starting to sleep for 5 seconds.
Done sleeping!
Starting to sleep for 5 seconds.
Done sleeping!
Starting to sleep for 5 seconds.
Done sleeping!
Done sleeping!

Actual output

<2020-12-17 16:37:12.660> Starting to sleep for 50 seconds.
<2020-12-17 16:38:02.660> Done sleeping!
<2020-12-17 16:38:02.661> Starting to sleep for 5 seconds.
<2020-12-17 16:38:07.661> Done sleeping!
<2020-12-17 16:38:07.661> Starting to sleep for 5 seconds.
<2020-12-17 16:38:12.662> Done sleeping!
<2020-12-17 16:38:12.662> Starting to sleep for 5 seconds.
<2020-12-17 16:38:17.662> Done sleeping!

Exported headers should be in a graphqlservice subdirectory in the source dir

There's a potential conflict in the include paths where the installed directory used with the SYSTEM PUBLIC paths in CMake are rooted at the source directory while building and in the include directory in the installed exports. But the files are actually copied to a graphqlservice sub-directory, which means if you use schemagen to build a custom schema it won't find them unless you add include/graphqlservice to the local include path. Ideally all of the generated files should use <graphqlservice/*.h> and reference a graphqlservice sub-directory in the source directory.

Add exception handling to Request::resolve and Object::resolve

Per issue #26, if we're going to accept invalid (default constructed) std::future results from resolvers to skip subscription updates, we need to be prepared to receive them in the other operation types as well. There are also some unhandled exception types (notably PEGTL parse errors and std::logic_error in response::Value) which we're expecting the implementer to catch and handle separately from schema_exception, which we handle internally and convert into an errors result. Any of those which can be triggered based on the user's input (e.g. malformed GraphQL or input values which don't match the schema and call the wrong methods on response::Value) should be converted into an errors response.

Theoretically we could also bubble up some errors along with partial results, e.g. if a single resolver returned an invalid future. That'll require augmenting the service::ResolverParams to flow a reference to the errors collection to each resolver call site in Object::resolve so it can check for std::future<>::valid() and/or catch exceptions.

Replace ResolverMap with a sorted std::array and perform a binary search for lookups

ResolverMap is using std::unordered_map right now, which is generally considered too slow and memory inefficient. One figure I've heard is that it doesn't pay off until you have 100 or more elements. It's flexible and would scale to enormous field sets, but since this is generated code we don't need to take that hit. We can use a much more efficient generation-time sort to create a flat array and use a binary search for the lookups.

Mutation input object resolving not working

Hi,

I am trying to create a mutation graphql api with similar input object as below.

type Mutation { addSomething(input: SomeInput!): SomeReturnValue! }

Schemagen works ok and objects get created and input struct is also created.

But when running/using the mutation from altair client I can't get it to work. I have used similar query as below (with variables defined).

mutation inputs($data: SomeInput!){ addSomething(input: $data) { field1 } }

Errow what I am getting is:

"message": "Field error name: addSomething unknown error: Invalid call to Value::find for MapType"
which is coming form the first require() call on created convert() method.

Should this work? There is similar thing done in samples for CompleteTaskInput

Avoid abusing response::MapType

Currently to cope with a single resolve() interface that returns a MapType, we're creating too many of them in intermediate steps only to hold data and errors keys.

See https://github.com/microsoft/cppgraphqlgen/blob/master/src/GraphQLService.cpp#L1271-L1297 and the related code.

I tried to convert to a ResolveResult struct with only 2 optionals: data and errors. This would save lots of memory pressure, allow simple lookups and all. But it was very cumbersome, it would require some changes to the generators and I did abort the patch (but it's partially saved, if you think it's the way to go I can resume work on that).

Another approach that I though is to add another response::ResultType that is compatible with map (would change the internals of GraphQLResponse.cpp to handle the new type), the internal usages would go with the new type, such as a new getData() and getErrors() that works only on ResultType. For externals (like the user application resolve()), once get<MapType>() or release<MapType>() it could create an internal map on demand (for get, release just returns it). This would be more "backwards compatible".

Do you think this may work? If so I can work on another PR.

Add a way to notify objects when there's a new subscription

Subscription updates are generated whenever the service calls Request::deliver. Subscription listeners get to filter the results based on field arguments, but the publisher doesn't know if anyone is listening.

Since generating a subscription update may be expensive or require reserving resources, it would be good to add a mechanism to the Subscription object hierarchy letting them know when a subscription has been registered for a given field, with the arguments and directives in effect for that subscription. It would essentially be a version of the getter method which would return void for scalar fields and objects for object fields so the service can recursively notify them too.

A few questions about the future of the API

Hello,

First, thank you for this project!
There is a lot of things going on about GraphQL for many languages, but somehow there is so few projects about it in the C++ ecosystem.

I have been watching the project and the recent changes, and I like the direction it goes.
I have a few questions regarding the future of the API:

  1. Do you think it would make sense to provide access to the SelectionSet to the resolvers?
    It feels like it could be useful sometimes to know what fields or subfields will be required to make the right query.
  2. One of the thing I find elegant in GraphQL, is how the query execution can be run concurrently in JavaScript and make "optimal" use of the event loop and future/promise JS has. Fields can be resolved concurrently, data loaders can batch requests to the data store, etc.
    I am under the impression that for now cppgraphqlgen does not make it possible to have this kind of concurrency. C++ makes it difficult because the future/promises API from the STL is limited for now (e.g. no std::future::then() yet) and there is no event loop (io_context or what not) yet.
    I'd really like to be able to resolve multiple things, blocking on I/O, concurrently. To get better throughput.
    Is is something you have already thought about?
  3. Regarding the representation of the results. I see that you recently changed from cpprestsdk to RapidJSON to represent the data. I feel like the GraphQL API does not really mandate JSON, but more like a dynamic object container that can be serialized to JSON. And I'm wondering if this could not be represented simply with some std::variant equivalent, or something akin to Folly's Dynamic: https://github.com/facebook/folly/blob/74eb516913af8374a895014e2aa67561cfd1ab46/folly/docs/Dynamic.md
    Maybe an object type that respect the "Serialized Map Ordering" from the GraphQL spec: https://facebook.github.io/graphql/June2018/#sec-Serialized-Map-Ordering

cmake fails in ubuntu 18.04

cmake brings the following error:

cmake .
CMake Error at CMakeLists.txt:16 (find_package):
  Could not find a package configuration file provided by "pegtl" with any of
  the following names:

    pegtlConfig.cmake
    pegtl-config.cmake

  Add the installation prefix of "pegtl" to CMAKE_PREFIX_PATH or set
  "pegtl_DIR" to a directory containing one of the above files.  If "pegtl"
  provides a separate development package or SDK, be sure it has been
  installed.


-- Configuring incomplete, errors occurred!
See also "/home/alkis/p/cpp/graphql/cppgraphqlgen/CMakeFiles/CMakeOutput.log".
See also "/home/alkis/p/cpp/graphql/cppgraphqlgen/CMakeFiles/CMakeError.log".

I tried to run
sudo apt install pegtl-dev
which installed a bunch of header files under /usr/include/pegtl, but cmake still outputs the same error.

How can I proceed?
Thanks a lot!

CMake fails to build

Hi all,

I was trying to build the project by command line following the descriptions from README, however the build is failing without providing a build dir.

Steps to Reproduce:

  1. Cloned the project
  2. git submodule update --init --recursive
  3. cmake .
  4. cmake --build .

System Info:

  • Ubuntu 18.04 LTS
  • cmake version 3.10.2

Logs:

Scanning dependencies of target update_samples
[ 26%] Generating ValidationSchema files
ValidationSchema.cpp
[ 28%] Generating mock TodaySchema files
TodaySchema.cpp
[ 29%] Generating mock TodaySchema (--separate-files)
[ 31%] Updating sample files
[ 31%] Built target update_samples
Scanning dependencies of target separateschema
make[2]: *** No rule to make target 'samples/separate/TodaySchema.cpp', needed by 'samples/CMakeFiles/separateschema.dir/separate/TodaySchema.cpp.o'.  Stop.
CMakeFiles/Makefile2:1315: recipe for target 'samples/CMakeFiles/separateschema.dir/all' failed
make[1]: *** [samples/CMakeFiles/separateschema.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2

Also, another problem is regarding the installation outputs following README instructions:

$ cmake --build . --config Release --target install
...
Install the project...                                                                                                                                                                                                         
-- Install configuration: ""                                                                                                                                                                                
-- Up-to-date: /usr/local/lib/cmake/cppgraphqlgen/cppgraphqlgen-config.cmake                                                                                                                                
-- Up-to-date: /usr/local/lib/cmake/cppgraphqlgen/cppgraphqlgen-config-version.cmake                                                                                                                        
-- Installing: /usr/local/lib/libgraphqljson.a                                                                                                                                                              
-- Installing: /usr/local/lib/libgraphqlpeg.a                                                                                                                                                               
-- Installing: /usr/local/lib/libgraphqlresponse.a                                                                                                                                                          
-- Installing: /usr/local/lib/libgraphqlservice.a                                                                                                                                                           
-- Up-to-date: /usr/local/lib/cmake/cppgraphqlgen/cppgraphqlgen-targets.cmake                                                                                                                               
-- Up-to-date: /usr/local/lib/cmake/cppgraphqlgen/cppgraphqlgen-targets-noconfig.cmake

The README command won't setup correctly the configuration inside CMake. On (https://cmake.org/cmake/help/latest/guide/tutorial/index.html#packaging-debug-and-release-step-12)[cmake official doc], their example is a bit different and I think we could improve the README.md with it:

cmake -DCMAKE_BUILD_TYPE=Release . && cmake --build . --target install

If you guys think it is a valid issue, I can already open a PR for that.

[]'s

Replace reserved identifiers

I noticed that you used reserved identifiers in a few places, namely _Rule, _Input, _States, _Type and _Value. Those are reserved by the C++ standard (everything that starts with underscore plus an uppercase character). They need to be replaced with something else, and as I don't know what style you'd prefer I'll leave it to you to choose.

Build failed in Visual Studio 2019 - Missing Boost_INCLUDE_IDR program_options

Visual studio 2019 Build Error:
Target: x64-Debug

Error:

Severity Code Description Project File Line Suppression State
Error CMake Error at C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake:164 (message):
Could NOT find Boost (missing: Boost_INCLUDE_DIR program_options) C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake 164

Visual Studio 2019 latest Preview Build Error:

Target: x64-Debug

Severity Code Description Project File Line Suppression State
Error CMake Error at C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake:164 (message):
Could NOT find Boost (missing: Boost_INCLUDE_DIR program_options) C:/Program Files (x86)/Microsoft Visual Studio/2019/Preview/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/share/cmake-3.17/Modules/FindPackageHandleStandardArgs.cmake 164

New error handling is not done properly in the generated __typename resolver

The response from a typical Relay query looks like this:

{
  "data":{โ€ฆ},
  "errors":[
    "Field error name: __typename unknown error: Invalid call to Value::release for MapType",
    ...
  ]
}

And the console error you get in Relay looks like this:

'RelayResponseNormalizer(): Expected a typename for record `{'

Since I backported this to v1.2 it affects v1.2.0 and v2.0.0.

Schema extensions don't get added to the schema

When I tried using extend schema I realized that it wasn't adding those operations to the resulting code.

The Generator::visitDefinition method is calling the same method to visit either a schema definition or a schema extension, and since I split those into different AST types to improve the error messages and reflect the fact that they're actually different grammar rules, it's not finding any of the children it expects in a schema extension.

Fix for #66 did not create all of the right specializations

The specializations should be on the decayed value type, which specializes the ValueTypeTraits struct in turn.

I put compatibility wrappers in place which will handle the reference type specializations and delegate to the newer versions. They have [[deprecated]] attributes which instruct the caller to migrate to the simpler version of the specialization.

Empty List input values cause a parse error

The following query can't be parsed/resolved even though it's valid GraphQL syntax

query QueryWithEmptyListVariable($empty: [Boolean!]! = []) {
	fieldWithArg(arg: $empty)
}

The grammar for list_value matches list_value_content, which matches an opt<list<list_entry,...>>, which matches input_value, which matches must<input_value_content>, and the must<> invokes the global error handler.

The simplest fix is just to make list_entry inherit directly from input_value_content so it matches the same content but it bypasses the must<> rule in input_value.

Fragment definitions not sufficiently validated in v3.0.2?

The following query got accepted even if there are unused, duplicated fragments or even fragments depending on nonexistent types:

query packageList {
    packages {
      ...frag1
      ...frag2
    }
}

# ok
fragment frag1 on Package {
      id
      weight
}

# ok
fragment frag2 on Package {
      cost
      policy
      reference
}

# duplicated fragment frag1
# <!> 5.5.1.1 Fragment Name Uniquenes
fragment frag1 on Package {
      id
      weight
      box
}

# duplicated fragment frag1 with typo: 
# <!> 5.5.1.1 Fragment Name Uniquenes
# <!> 5.5.1.2 Fragment Spread Type Existence
fragment frag1 on xPackage {
      id
      weight
}

# unused fragment
# <!> 5.5.1.4 Fragments Must Be Used
# <!> 5.5.1.2 Fragment Spread Type Existence
fragment frag3 on xPackage {
      cost
      policy
      reference
}

Build break on Linux with g++ 8.3.0

Per vcpkg:10407, if you use g++-8.3.0 to build cppgraphqlgen, it fails properly resolve these template method overloads. It works fine on g++-7.5.0, which is stock on Ubuntu:

/usr/bin/g++-8   -isystem src/../include -I../src/../include -I../src/../PEGTL/include -isystem /home/bill/vcpkg/installed/x64-linux/include -std=gnu++1z -MD -MT src/CMakeFiles/graphqlservice.dir/__/IntrospectionSchema.cpp.o -MF src/CMakeFiles/graphqlservice.dir/__/IntrospectionSchema.cpp.o.d -o src/CMakeFiles/graphqlservice.dir/__/IntrospectionSchema.cpp.o -c IntrospectionSchema.cpp
In file included from src/../include/graphqlservice/IntrospectionSchema.h:9,
                 from ../src/../include/graphqlservice/Introspection.h:9,
                 from IntrospectionSchema.cpp:4:
../src/../include/graphqlservice/GraphQLService.h: In instantiation of โ€˜graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]::<lambda(auto:4&&, graphql::service::ResolverParams&&)> [with auto:4 = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >]โ€™:
/usr/include/c++/8/type_traits:2246:26:   required by substitution of โ€˜template<class _Fn, class ... _Args> static std::__result_of_success<decltype (declval<_Fn>()((declval<_Args>)()...)), std::__invoke_other> std::__result_of_other_impl::_S_test(int) [with _Fn = graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]::<lambda(auto:4&&, graphql::service::ResolverParams&&)>; _Args = {graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type>, std::allocator<std::shared_ptr<graphql::introspection::object::Type> > > >, graphql::service::ResolverParams}]โ€™
/usr/include/c++/8/type_traits:2257:55:   required from โ€˜struct std::__result_of_impl<false, false, graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]::<lambda(auto:4&&, graphql::service::ResolverParams&&)>, graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type>, std::allocator<std::shared_ptr<graphql::introspection::object::Type> > > >, graphql::service::ResolverParams>โ€™
/usr/include/c++/8/type_traits:2262:12:   required from โ€˜struct std::__invoke_result<graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]::<lambda(auto:4&&, graphql::service::ResolverParams&&)>, graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type>, std::allocator<std::shared_ptr<graphql::introspection::object::Type> > > >, graphql::service::ResolverParams>โ€™
/usr/include/c++/8/type_traits:2275:12:   required from โ€˜class std::result_of<graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]::<lambda(auto:4&&, graphql::service::ResolverParams&&)>(graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >, graphql::service::ResolverParams)>โ€™
/usr/include/c++/8/future:1712:5:   required by substitution of โ€˜template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_Types>::type ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]::<lambda(auto:4&&, graphql::service::ResolverParams&&)>; _Args = {graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type>, std::allocator<std::shared_ptr<graphql::introspection::object::Type> > > >, graphql::service::ResolverParams}]โ€™
../src/../include/graphqlservice/GraphQLService.h:584:20:   required from โ€˜static std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > graphql::service::ModifiedResult<Type>::convert(typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type, graphql::service::ResolverParams&&) [with graphql::service::TypeModifier Modifier = (graphql::service::TypeModifier)2; graphql::service::TypeModifier ...Other = {}; Type = graphql::introspection::object::Type; std::enable_if_t<(List == Modifier), std::future<graphql::response::Value> > = std::future<graphql::response::Value>; typename graphql::service::ModifiedResult<Type>::ResultTraits<Type, Modifier, Other ...>::future_type = graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type> > >&&]โ€™
IntrospectionSchema.cpp:137:113:   required from here
../src/../include/graphqlservice/GraphQLService.h:606:20: error: โ€˜convertโ€™ was not declared in this scope
      children.push(convert<Other...>(std::move(entry), ResolverParams(wrappedParams)));

specialisations of ValueType::get() not obvious in GraphqlResponse.h

When looking at the definition of ValueType::get() in include/graphqlgen/GraphqlResponse.h,

91  // Specialized for all Types.
92  template <typename ValueType>
93  ValueType get() const;

the actually implemented template specialisations are not obvious. For example, trying to access a stringType value by

  v.get<graphql::response::stringType>()

will result in a linker error:

ctas.cxx:35: undefined reference to `std::__cxx11::basic_string<char, std::char_traits, std::allocator > graphql::response::Value::get<std::__cxx11::basic_string<char, std::char_traits, std::allocator > >() const'

This is because the actually implemented specialisation is

template <>
const StringType& Value::get<const StringType&>() const 

Note the const reference type. I think the actually implemented specialisations template specialisation should be listed in GraphqlResponse.h:

  • const MapType& get<const MapType&>()
  • const ListType& get<const ListType&>()
  • const StringType& get<const StringType&>()
  • const ScalarType& get<const ScalarType&>()
  • BoleanType get()
  • IntType get()
  • FloatType get()

Subscription support is currently deactivated by throwing a schema_exception

When taking in account #24, #26, #31 as proposed by GitHub and thus also the existence of Request::subcribe(.) and Request::unsubscribe(.), I still observe that aside from a test fragments in "TodayTests.cpp" there is no documentation or example of how to make use of these methods within the graphql::service framework. Probably I don't see the forest for the trees.

Currently (v3.0.2) any query along the lines

subscription sPersons {
    change(rid:"70-20-91-04" ) {
         rid
         status 
         person {
             id
             name
         }
    }
}

will be aborted with the message "Unexpected Subscription" (in GraphqlService.cpp +1631)

My current idea wrt subscription requests is to return a status (e.g. "registered") along with an empty changeSet after having written the subscription request to the database, since waiting for dataset changes within the service framework would block the main loop and thus require to implement it reentrant or multi-threaded.
A second thread or process would wait for notifications from the database, calculate the changeset and send it to the client using the same channel as was used for the request, so a client would be able to receive synchronous and asynchronous messages by the same channel. Yet in order to create asynchronous replies, the selection set as defined in the subscription query is needed, since the field composition and order are controlled by the client request. However, that information is not available in the standard "FieldParams" parameter as passed to the service::Object getter methods.

Compile errors with VS 2017

Using the following tools:

Visual C++ 2017 00369-60000-00001-AA270 (Community) 15.8.5

Cmake:
C:\repos\cpp\cppgraphqlgen>"C:\PROGRAM FILES (X86)\MICROSOFT VISUAL STUDIO\2017\COMMUNITY\COMMON7\IDE\COMMONEXTENSIONS\MICROSOFT\CMAKE\CMake\bin\cmake.exe" --version
cmake version 3.11.18040201-MSVC_2

I have installed vcpkg with packages gtest, rapidjson, and boost.

Attempting to build cppgraphqlgen gives me the following errors, which I get from my own project schema in both Visual Studio 2017 and 2019. (x86) I have tested versions 3.1.1, 3.2.0 and master

  [16/58] C:\PROGRA~2\MICROS~2\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\HostX86\x86\cl.exe  /nologo /TP  -Isrc\..\include -IC:\repos\cpp\cppgraphqlgen\src\..\include -IC:\repos\cpp\cppgraphqlgen\src\..\PEGTL\include -IC:\repos\cpp\vcpkg\installed\x86-windows\include /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MD /Zi /O2 /Ob1 /DNDEBUG   -std:c++17 /showIncludes /Fosrc\CMakeFiles\graphqlservice.dir\__\IntrospectionSchema.cpp.obj /Fdsrc\CMakeFiles\graphqlservice.dir\graphqlservice.pdb /FS -c IntrospectionSchema.cpp
  FAILED: src/CMakeFiles/graphqlservice.dir/__/IntrospectionSchema.cpp.obj 
  C:\PROGRA~2\MICROS~2\2017\COMMUN~1\VC\Tools\MSVC\1415~1.267\bin\HostX86\x86\cl.exe  /nologo /TP  -Isrc\..\include -IC:\repos\cpp\cppgraphqlgen\src\..\include -IC:\repos\cpp\cppgraphqlgen\src\..\PEGTL\include -IC:\repos\cpp\vcpkg\installed\x86-windows\include /DWIN32 /D_WINDOWS /W3 /GR /EHsc /MD /Zi /O2 /Ob1 /DNDEBUG   -std:c++17 /showIncludes /Fosrc\CMakeFiles\graphqlservice.dir\__\IntrospectionSchema.cpp.obj /Fdsrc\CMakeFiles\graphqlservice.dir\graphqlservice.pdb /FS -c IntrospectionSchema.cpp
C:\repos\cpp\cppgraphqlgen\include\graphqlservice\GraphQLService.h(583): error C3539: a template-argument cannot be a type that contains 'auto'
  IntrospectionSchema.cpp(137): note: see reference to function template instantiation 'std::future<graphql::response::Value> graphql::service::ModifiedResult<graphql::introspection::object::Type>::convert<graphql::service::TypeModifier::List,>(graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type>,std::allocator<_Ty>>> &&,graphql::service::ResolverParams &&)' being compiled
          with
          [
              _Ty=std::shared_ptr<graphql::introspection::object::Type>
          ]
  IntrospectionSchema.cpp(137): note: see reference to function template instantiation 'std::future<graphql::response::Value> graphql::service::ModifiedResult<graphql::introspection::object::Type>::convert<graphql::service::TypeModifier::List,>(graphql::service::FieldResult<std::vector<std::shared_ptr<graphql::introspection::object::Type>,std::allocator<_Ty>>> &&,graphql::service::ResolverParams &&)' being compiled
          with
          [
              _Ty=std::shared_ptr<graphql::introspection::object::Type>
          ]
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\type_traits(616): note: see reference to class template instantiation 'std::basic_string_view<char,std::char_traits<char>>' being compiled
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\xstring(2124): note: see reference to class template instantiation 'std::is_convertible<const _StringViewIsh (&),std::basic_string_view<char,std::char_traits<char>>>' being compiled
          with
          [
              _StringViewIsh=char [2]
          ]
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\xstring(2122): note: see reference to variable template 'const bool conjunction_v<std::is_convertible<char const (&)[2],std::basic_string_view<char,std::char_traits<char> > >,std::negation<std::is_convertible<char const (&)[2],char const *> > >' being compiled
  C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.15.26726\include\xstring(3774): note: see reference to alias template instantiation '_Is_string_view_ish<char[2]>' being compiled
C:\repos\cpp\cppgraphqlgen\include\graphqlservice\GraphQLService.h(592): error C2510: 'decay_t<int>': left of '::' must be a class/struct/union
C:\repos\cpp\cppgraphqlgen\include\graphqlservice\GraphQLService.h(583): error C2146: syntax error: missing '>' before identifier 'reference'

I'm assuming I have some environment setup issue wrong here? This seems like something the package authors would have run into, especially since it's pervasive across versions?

Regards!

Subscription API unable to notify only some subscribers per schema subscription?

Assuming a Subscription from a schema like this:

type Subscription {
    onEntityChanged(id: ID!) : Entity
}

I'd like a client to be notified only about the changes on the entity, or entities, it chose with id:

subscription EntityChanged {
     onEntityChanged(id: "someid") : Entity
}

I am under the impression that the current deliver mechanism does not allow for this granularity.

I can do things like service->deliver("onEntityChanged", nullptr); to notify when any entity changed, and getOnEntityChanged(params, id) has to generate a value for it. However, I'd like the subscription to notify only about the specified id, not about any id.

Did I miss something or is it a limitation of the current implementation?

Changing MapData to a simple std::map?

Currently the MapData uses an unordered map and a vector, this is likely used to keep the insertion order, however there is no requirement the results should be in a specific order (at least changing this breaks the tests, that expects the JSON serialization to be equal, instead of comparing the objects).

However this is resulting in 2 strings to be created, plus the extra indirections to get the pairs.

Could we change the MapData to be a std::map and fix the tests?

Float arguments reject whole numbers

When passing a whole number as an argument that is defined as a Float, the error "not a float" is thrown. For example, the following query fails with "not a float":

type Mutation {
    setFloat(float: Float!): Float
}
mutation a {
  setFloat(float: 0)
}

I can resolve this in the generated resolveSetFloat() by trying to require it as a response::IntType, catching a schema_exception, then trying to require it as a response::FloatType:

        graphql::response::FloatType argFloat;
	
	try {
		argFloat = service::ModifiedArgument<response::IntType>::require("float", params.arguments);
	} catch (graphql::service::schema_exception & ex) {
		argFloat = service::ModifiedArgument<response::FloatType>::require("float", params.arguments);
	}

I think this can be fixed in the library GraphQLService.cpp by changing this:

template <>
response::FloatType ModifiedArgument<response::FloatType>::convert(const response::Value& value)
{
	if (value.type() != response::Type::Float)
	{
		throw schema_exception { { "not a float" } };
	}

	return value.get<response::FloatType>();
}

to

template <>
response::FloatType ModifiedArgument<response::FloatType>::convert(const response::Value& value)
{
	if (value.type() != response::Type::Float || value.type() != response::Type::Int)
	{
		throw schema_exception { { "not a float" } };
	}

	return value.get<response::FloatType>();
}

Thoughts? I can create a pull request for this later, but I wanted to get this out there.

vcpkg version: 2020.02.04
cppgraphqlgen version: 3.2.2
OS: Debian Buster

Empty lists should return [] instead of omitting the field

Bug in ModifiedResult where it handles the List modifier. If values.size() == 0 it doesn't emplace it. Relay seems to not like specifying empty selection sets in the compiled GraphQL, but for the sake of completeness it should probably do the same thing in Object::resolve when data.size() == 0. If all of the specified members are removed due to field errors we could still return an empty {} object and that would at least indicate that the object exists.

Fragment type conditions don't work for union types

Take the following example from the schema.today.graphql sample:

{
	appointments {
		edges {
			node {
				...AppointmentUnionFragment
			}
		}
	}
}

fragment AppointmentUnionFragment on UnionType {
	...on Appointment {
		appointmentId: id
		subject
		when
		isNow
	}
}

The AppointmentUnionFragment fragment never matches on the Appointment type.

improve memory consumption

Creating this issue to track the improvements. Compared to my https://github.com/profusion/cppgraphqlgen/tree/parser-tweaks we still have some ground to cover. Results are comparing using the samples_nointrospection running a loop of 500:

diff --git a/samples/today/sample.cpp b/samples/today/sample.cpp
index 376a730..b097fdc 100644
--- a/samples/today/sample.cpp
+++ b/samples/today/sample.cpp
@@ -84,6 +84,7 @@ int main(int argc, char** argv)
 
                std::cout << "Executing query..." << std::endl;
 
+               for (int i = 0; i < 500; i++) {
                std::cout << response::toJSON(service
                                                                                  ->resolve(nullptr,
                                                                                          query,
@@ -91,6 +92,7 @@ int main(int argc, char** argv)
                                                                                          response::Value(response::Type::Map))
                                                                                  .get())
                                  << std::endl;
+               }
        }
        catch (const std::runtime_error& ex)
        {

DHAT

Branch/Commit GMax (instrs) End (instrs) Total bytes
daecf27 6,334,065 312,692,430 8,166,830
bd725ac 7,615,736 699,347,168 10,489,271
Difference +36.94% +28.25% +28.43%

parser-tweaks daecf27

Highest consumer path, the biggest source is graphqlpeg:


โ–ผ AP 1/1 (2 children) {
    Total:     8,166,830 bytes (100%, 26,117.77/Minstr) in 88,453 blocks (100%, 282.88/Minstr), avg size 92.33 bytes, avg lifetime 1,525,957.39 instrs (0.49% of program duration)
  โ”œโ”€โ–ผ AP 1.1/2 (10 children) {
  โ”‚     Total:     8,013,934 bytes (98.13%, 25,628.81/Minstr) in 88,248 blocks (99.77%, 282.22/Minstr), avg size 90.81 bytes, avg lifetime 1,511,853.03 instrs (0.48% of program duration)
  โ”‚   โ”œโ”€โ–ถ AP 1.1.1/10 (27 children) {
  โ”‚   โ”‚     Total:     5,081,600 bytes (62.22%, 16,251.11/Minstr) in 39,700 blocks (44.88%, 126.96/Minstr), avg size 128 bytes, avg lifetime 318,113.36 instrs (0.1% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x3DFD96: std::_MakeUniq<graphql::peg::ast_node>::__single_object std::make_unique<graphql::peg::ast_node>() (unique_ptr.h:857)
  โ”‚   โ”‚       #3: 0x3DEF3F: tao::graphqlpeg::parse_tree::internal::state<graphql::peg::ast_node>::emplace_back() (parse_tree.hpp:175)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ”€ AP 1.1.2/10 {
  โ”‚   โ”‚     Total:     993,670 bytes (12.17%, 3,177.79/Minstr)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       [101 insignificant]
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ–ถ AP 1.1.3/10 (2 children) {
  โ”‚   โ”‚     Total:     453,600 bytes (5.55%, 1,450.63/Minstr) in 900 blocks (1.02%, 2.88/Minstr), avg size 504 bytes, avg lifetime 56,523.02 instrs (0.02% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x2CF150: __gnu_cxx::new_allocator<graphql::service::FragmentDirectives>::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x2CCFD9: std::allocator_traits<std::allocator<graphql::service::FragmentDirectives> >::allocate(std::allocator<graphql::service::FragmentDirectives>&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x2CAA17: std::_Deque_base<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_allocate_node() (stl_deque.h:620)
  โ”‚   โ”‚       #5: 0x2CA732: std::_Deque_base<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_create_nodes(graphql::service::FragmentDirectives**, graphql::service::FragmentDirectives**) (stl_deque.h:745)
  โ”‚   โ”‚       #6: 0x2C6B23: std::_Deque_base<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_initialize_map(unsigned long) (stl_deque.h:719)
  โ”‚   โ”‚       #7: 0x2C2231: std::_Deque_base<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_Deque_base() (stl_deque.h:510)
  โ”‚   โ”‚       #8: 0x2BC551: std::deque<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::deque() (stl_deque.h:915)
  โ”‚   โ”‚       #9: 0x2B670D: std::stack<graphql::service::FragmentDirectives, std::deque<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> > >::stack<std::deque<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >, void>() (stl_stack.h:157)
  โ”‚   โ”‚       #10: 0x28B484: graphql::service::SelectionVisitor::SelectionVisitor(graphql::service::SelectionSetParams const&, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::service::Fragment, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&, std::unordered_set<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, std::vector<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::response::Value> (graphql::service::ResolverParams&&)> >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::response::Value> (graphql::service::ResolverParams&&)> > > > const&) (GraphQLService.cpp:797)
  โ”‚   โ”‚       #11: 0x28E6BF: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::service::Fragment, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1110)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ”€ AP 1.1.4/10 {
  โ”‚   โ”‚     Total:     396,000 bytes (4.85%, 1,266.42/Minstr) in 5,500 blocks (6.22%, 17.59/Minstr), avg size 72 bytes, avg lifetime 178,984.23 instrs (0.06% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x3C8B91: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x3C8282: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x3C6DBD: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:97)
  โ”‚   โ”‚       #5: 0x3C56DB: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >>(std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >*&, std::_Sp_alloc_shared_tag<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > > >) (shared_ptr_base.h:677)
  โ”‚   โ”‚       #6: 0x3C4007: std::__shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >>(std::_Sp_alloc_shared_tag<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > > >) (shared_ptr_base.h:1344)
  โ”‚   โ”‚       #7: 0x3C23F8: std::shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >::shared_ptr<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >>(std::_Sp_alloc_shared_tag<std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > > >) (shared_ptr.h:359)
  โ”‚   โ”‚       #8: 0x3BFC9B: std::shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > > std::allocate_shared<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >, std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > >>(std::allocator<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > > const&) (shared_ptr.h:702)
  โ”‚   โ”‚       #9: 0x3BC20A: std::shared_ptr<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > > > std::make_shared<std::unordered_map<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, unsigned long, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, unsigned long> > >>() (shared_ptr.h:718)
  โ”‚   โ”‚       #10: 0x3BA27D: graphql::response::MapData::MapData() (GraphQLResponse.cpp:310)
  โ”‚   โ”‚       #11: 0x3BDFFF: std::_MakeUniq<graphql::response::MapData>::__single_object std::make_unique<graphql::response::MapData>() (unique_ptr.h:857)
  โ”‚   โ”‚       #12: 0x3B69A9: graphql::response::Value::Value(graphql::response::Type) (GraphQLResponse.cpp:733)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ–ถ AP 1.1.5/10 (1 children) {
  โ”‚   โ”‚     Total:     220,000 bytes (2.69%, 703.57/Minstr) in 5,500 blocks (6.22%, 17.59/Minstr), avg size 40 bytes, avg lifetime 180,717.23 instrs (0.06% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_dhat-amd64-linux.so)
  โ”‚   โ”‚       #2: 0x3BDFF0: std::_MakeUniq<graphql::response::MapData>::__single_object std::make_unique<graphql::response::MapData>() (unique_ptr.h:857)
  โ”‚   โ”‚       #3: 0x3B69A9: graphql::response::Value::Value(graphql::response::Type) (GraphQLResponse.cpp:733)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ”€ AP 1.1.6/10 {
  โ”‚   โ”‚     Total:     220,000 bytes (2.69%, 703.57/Minstr) in 5,500 blocks (6.22%, 17.59/Minstr), avg size 40 bytes, avg lifetime 180,393.23 instrs (0.06% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x3C8A43: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x3C8130: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::allocator<std::_Sp_counted_ptr_inplace<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >, (__gnu_cxx::_Lock_policy)2> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x3C6B7B: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >, (__gnu_cxx::_Lock_policy)2> > >(std::allocator<std::_Sp_counted_ptr_inplace<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >, (__gnu_cxx::_Lock_policy)2> >&) (allocated_ptr.h:97)
  โ”‚   โ”‚       #5: 0x3C559B: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >>(std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >*&, std::_Sp_alloc_shared_tag<std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > > >) (shared_ptr_base.h:677)
  โ”‚   โ”‚       #6: 0x3C3FB3: std::__shared_ptr<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >>(std::_Sp_alloc_shared_tag<std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > > >) (shared_ptr_base.h:1344)
  โ”‚   โ”‚       #7: 0x3C23AE: std::shared_ptr<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >::shared_ptr<std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >>(std::_Sp_alloc_shared_tag<std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > > >) (shared_ptr.h:359)
  โ”‚   โ”‚       #8: 0x3BFC2F: std::shared_ptr<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > > std::allocate_shared<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >, std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > >>(std::allocator<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > > const&) (shared_ptr.h:702)
  โ”‚   โ”‚       #9: 0x3BC180: std::shared_ptr<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > > > std::make_shared<std::vector<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value>, std::allocator<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, graphql::response::Value> > >>() (shared_ptr.h:718)
  โ”‚   โ”‚       #10: 0x3BA26D: graphql::response::MapData::MapData() (GraphQLResponse.cpp:310)
  โ”‚   โ”‚       #11: 0x3BDFFF: std::_MakeUniq<graphql::response::MapData>::__single_object std::make_unique<graphql::response::MapData>() (unique_ptr.h:857)
  โ”‚   โ”‚       #12: 0x3B69A9: graphql::response::Value::Value(graphql::response::Type) (GraphQLResponse.cpp:733)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ–ถ AP 1.1.7/10 (2 children) {
  โ”‚   โ”‚     Total:     215,464 bytes (2.64%, 689.06/Minstr) in 2,380 blocks (2.69%, 7.61/Minstr), avg size 90.53 bytes, avg lifetime 6,172,229.42 instrs (1.97% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x21D0E5: __gnu_cxx::new_allocator<std::__detail::_Hash_node_base*>::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x20C954: std::allocator_traits<std::allocator<std::__detail::_Hash_node_base*> >::allocate(std::allocator<std::__detail::_Hash_node_base*>&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”œโ”€โ–ถ AP 1.1.8/10 (2 children) {
  โ”‚   โ”‚     Total:     212,000 bytes (2.6%, 677.98/Minstr) in 11,500 blocks (13%, 36.78/Minstr), avg size 18.43 bytes, avg lifetime 347,942.45 instrs (0.11% of program duration)
  โ”‚   โ”‚     At t-gmax: 200 bytes (0.17%) in 16 blocks (3.02%), avg size 12.5 bytes
  โ”‚   โ”‚     At t-end:  0 bytes (0%) in 0 blocks (0%), avg size 0 bytes
  โ”‚   โ”‚     Reads:     1,415,200 bytes (8.83%, 4,525.85/Minstr), 6.68/byte
  โ”‚   โ”‚     Writes:    1,219,200 bytes (5.95%, 3,899.04/Minstr), 5.75/byte
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_dhat-amd64-linux.so)
  โ”‚   โ”‚       #2: 0x3E41FF: __gnu_cxx::new_allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x3E3043: std::allocator_traits<std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > >::allocate(std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x3E25C3: std::_Vector_base<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >, std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚       #5: 0x3E11A0: void std::vector<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >, std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > >::_M_realloc_insert<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > >(__gnu_cxx::__normal_iterator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >*, std::vector<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >, std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > > >, std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >&&) (vector.tcc:440)
  โ”‚   โ”‚       #6: 0x3DFE67: std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >& std::vector<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >, std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > >::emplace_back<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > >(std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >&&) (vector.tcc:121)

master bd725ac

You can see 18% is wasted on field_path (stl_vector + variant makes it clear), that comes from SelectionSetParams constructor (graphql::service::SelectionSetParams::SelectionSetParams(graphql::service::SelectionSetParams const&) (GraphQLService.h:139)).


โ–ผ AP 1/1 (3 children) {
    Total:     10,489,271 bytes (100%, 14,998.66/Minstr) in 98,231 blocks (100%, 140.46/Minstr), avg size 106.78 bytes, avg lifetime 5,431,052.27 instrs (0.78% of program duration)
  โ”œโ”€โ–ผ AP 1.1/3 (25 children) {
  โ”‚     Total:     10,029,175 bytes (95.61%, 14,340.77/Minstr) in 97,226 blocks (98.98%, 139.02/Minstr), avg size 103.15 bytes, avg lifetime 5,450,952.8 instrs (0.78% of program duration)
  โ”‚   โ”œโ”€โ–ผ AP 1.1.1/25 (2 children) {
  โ”‚   โ”‚     Total:     1,968,000 bytes (18.76%, 2,814.05/Minstr) in 22,500 blocks (22.91%, 32.17/Minstr), avg size 87.47 bytes, avg lifetime 127,205.04 instrs (0.02% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”‚   โ”œโ”€โ–ผ AP 1.1.1.1/2 (3 children) {
  โ”‚   โ”‚   โ”‚     Total:     1,356,000 bytes (12.93%, 1,938.95/Minstr) in 17,500 blocks (17.82%, 25.02/Minstr), avg size 77.49 bytes, avg lifetime 134,440.04 instrs (0.02% of program duration)
  โ”‚   โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long) (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_dhat-amd64-linux.so)
  โ”‚   โ”‚   โ”‚       ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚   โ”‚       ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚   โ”‚       ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚   โ”‚       #5: 0x16289A: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_create_storage(unsigned long) (stl_vector.h:358)
  โ”‚   โ”‚   โ”‚       #6: 0x15D044: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_Vector_base(unsigned long, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > const&) (stl_vector.h:302)
  โ”‚   โ”‚   โ”‚       #7: 0x156E1A: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::vector(std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > const&) (stl_vector.h:552)
  โ”‚   โ”‚   โ”‚     }
  โ”‚   โ”‚   โ”‚   }
  โ”‚   โ”‚   โ”‚   โ”œโ”€โ–ถ AP 1.1.1.1.1/3 (3 children) {
  โ”‚   โ”‚   โ”‚   โ”‚     Total:     804,000 bytes (7.66%, 1,149.64/Minstr) in 9,500 blocks (9.67%, 13.58/Minstr), avg size 84.63 bytes, avg lifetime 214,990.61 instrs (0.03% of program duration)
  โ”‚   โ”‚   โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚   โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚   โ”‚   โ”‚       ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚   โ”‚   โ”‚       ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚   โ”‚   โ”‚       ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚   โ”‚   โ”‚       ^5: 0x16289A: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_create_storage(unsigned long) (stl_vector.h:358)
  โ”‚   โ”‚   โ”‚   โ”‚       ^6: 0x15D044: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_Vector_base(unsigned long, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > const&) (stl_vector.h:302)
  โ”‚   โ”‚   โ”‚   โ”‚       ^7: 0x156E1A: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::vector(std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > const&) (stl_vector.h:552)
  โ”‚   โ”‚   โ”‚   โ”‚       #8: 0x19C3D6: graphql::service::SelectionSetParams::SelectionSetParams(graphql::service::SelectionSetParams const&) (GraphQLService.h:139)
  โ”‚   โ”‚   โ”‚   โ”‚     }
  โ”‚   โ”‚   โ”‚   โ”‚   }
  โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ AP 1.1.1.1.2/3 {
  โ”‚   โ”‚   โ”‚   โ”‚     Total:     276,000 bytes (2.63%, 394.65/Minstr) in 4,000 blocks (4.07%, 5.72/Minstr), avg size 69 bytes, avg lifetime 75,226.88 instrs (0.01% of program duration)
  โ”‚   โ”‚   โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚   โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚   โ”‚   โ”‚       ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚   โ”‚   โ”‚       ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚   โ”‚   โ”‚       ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚   โ”‚   โ”‚       ^5: 0x16289A: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_create_storage(unsigned long) (stl_vector.h:358)
  โ”‚   โ”‚   โ”‚   โ”‚       ^6: 0x15D044: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_Vector_base(unsigned long, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > const&) (stl_vector.h:302)
  โ”‚   โ”‚   โ”‚   โ”‚       ^7: 0x156E1A: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::vector(std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > const&) (stl_vector.h:552)
  โ”‚   โ”‚   โ”‚   โ”‚       #8: 0x2DFBAD: graphql::service::SelectionVisitor::SelectionVisitor(graphql::service::SelectionSetParams const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&, std::unordered_set<std::basic_string_view<char, std::char_traits<char> >, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > const&, std::vector<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::service::ResolverResult> (graphql::service::ResolverParams&&)> >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::service::ResolverResult> (graphql::service::ResolverParams&&)> > > > const&) (GraphQLService.cpp:895)
  โ”‚   โ”‚   โ”‚   โ”‚       #9: 0x2E30DD: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1213)
  โ”‚   โ”‚   โ”‚   โ”‚       #10: 0x2DF9F8: graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}::operator()(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) const (GraphQLService.cpp:830)
  โ”‚   โ”‚   โ”‚   โ”‚       #11: 0x308D58: graphql::service::ResolverResult std::__invoke_impl<graphql::service::ResolverResult, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::__invoke_other, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}&&, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) (invoke.h:60)
  โ”‚   โ”‚   โ”‚   โ”‚       #12: 0x30866B: std::__invoke_result<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>::type std::__invoke<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::__invoke_result&&, (graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}&&)...) (invoke.h:96)
  โ”‚   โ”‚   โ”‚   โ”‚     }
  โ”‚   โ”‚   โ”‚   โ”‚   }
  โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ AP 1.1.1.1.3/3 {
  โ”‚   โ”‚   โ”‚         Total:     276,000 bytes (2.63%, 394.65/Minstr) in 4,000 blocks (4.07%, 5.72/Minstr), avg size 69 bytes, avg lifetime 2,345.63 instrs (0% of program duration)
  โ”‚   โ”‚   โ”‚         Allocated at {
  โ”‚   โ”‚   โ”‚           ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚   โ”‚           ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚   โ”‚           ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚   โ”‚           ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚   โ”‚           ^5: 0x16289A: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_create_storage(unsigned long) (stl_vector.h:358)
  โ”‚   โ”‚   โ”‚           ^6: 0x15D044: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_Vector_base(unsigned long, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > const&) (stl_vector.h:302)
  โ”‚   โ”‚   โ”‚           ^7: 0x156E1A: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::vector(std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > const&) (stl_vector.h:552)
  โ”‚   โ”‚   โ”‚           #8: 0x2E06F5: graphql::service::SelectionVisitor::visitField(graphql::peg::ast_node const&) (GraphQLService.cpp:1004)
  โ”‚   โ”‚   โ”‚           #9: 0x2DFDE6: graphql::service::SelectionVisitor::visit(graphql::peg::ast_node const&) (GraphQLService.cpp:913)
  โ”‚   โ”‚   โ”‚           #10: 0x2E3101: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1215)
  โ”‚   โ”‚   โ”‚           #11: 0x2DF9F8: graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}::operator()(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) const (GraphQLService.cpp:830)
  โ”‚   โ”‚   โ”‚           #12: 0x308D58: graphql::service::ResolverResult std::__invoke_impl<graphql::service::ResolverResult, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::__invoke_other, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}&&, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) (invoke.h:60)
  โ”‚   โ”‚   โ”‚         }
  โ”‚   โ”‚   โ”‚       }
  โ”‚   โ”‚   โ””โ”€โ–ผ AP 1.1.1.2/2 (2 children) {
  โ”‚   โ”‚         Total:     612,000 bytes (5.83%, 875.1/Minstr) in 5,000 blocks (5.09%, 7.15/Minstr), avg size 122.4 bytes, avg lifetime 101,882.54 instrs (0.01% of program duration)
  โ”‚   โ”‚         Allocated at {
  โ”‚   โ”‚           ^1: 0x4839E23: operator new(unsigned long) 
  โ”‚   โ”‚           ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚           ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚           ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚           #5: 0x1AE830: void std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_realloc_insert<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >(__gnu_cxx::__normal_iterator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>*, std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > >, std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (vector.tcc:440)
  โ”‚   โ”‚           #6: 0x1A6CA1: std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>& std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::emplace_back<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >(std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (vector.tcc:121)
  โ”‚   โ”‚           #7: 0x1A063F: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::push_back(std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (stl_vector.h:1201)
  โ”‚   โ”‚         }
  โ”‚   โ”‚       }
  โ”‚   โ”‚       โ”œโ”€โ–ผ AP 1.1.1.2.1/2 (2 children) {
  โ”‚   โ”‚       โ”‚     Total:     564,000 bytes (5.38%, 806.47/Minstr) in 4,500 blocks (4.58%, 6.43/Minstr), avg size 125.33 bytes, avg lifetime 30,666.06 instrs (0% of program duration)
  โ”‚   โ”‚       โ”‚     Allocated at {
  โ”‚   โ”‚       โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       โ”‚       ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       โ”‚       ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       โ”‚       ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚       โ”‚       ^5: 0x1AE830: void std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_realloc_insert<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >(__gnu_cxx::__normal_iterator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>*, std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > >, std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (vector.tcc:440)
  โ”‚   โ”‚       โ”‚       ^6: 0x1A6CA1: std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>& std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::emplace_back<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >(std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (vector.tcc:121)
  โ”‚   โ”‚       โ”‚       ^7: 0x1A063F: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::push_back(std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (stl_vector.h:1201)
  โ”‚   โ”‚       โ”‚       #8: 0x2E0727: graphql::service::SelectionVisitor::visitField(graphql::peg::ast_node const&) (GraphQLService.cpp:1006)
  โ”‚   โ”‚       โ”‚       #9: 0x2DFDE6: graphql::service::SelectionVisitor::visit(graphql::peg::ast_node const&) (GraphQLService.cpp:913)
  โ”‚   โ”‚       โ”‚       #10: 0x2E3101: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1215)
  โ”‚   โ”‚       โ”‚     }
  โ”‚   โ”‚       โ”‚   }
  โ”‚   โ”‚       โ”‚   โ”œโ”€โ”€ AP 1.1.1.2.1.1/2 {
  โ”‚   โ”‚       โ”‚   โ”‚     Total:     552,000 bytes (5.26%, 789.31/Minstr) in 4,000 blocks (4.07%, 5.72/Minstr), avg size 138 bytes, avg lifetime 29,027 instrs (0% of program duration)
  โ”‚   โ”‚       โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       โ”‚   โ”‚       ^2: 0x16E950: __gnu_cxx::new_allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       โ”‚   โ”‚       ^3: 0x16B8DF: std::allocator_traits<std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::allocate(std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       โ”‚   โ”‚       ^4: 0x1677FB: std::_Vector_base<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚       โ”‚   โ”‚       ^5: 0x1AE830: void std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::_M_realloc_insert<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >(__gnu_cxx::__normal_iterator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>*, std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > > >, std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (vector.tcc:440)
  โ”‚   โ”‚       โ”‚   โ”‚       ^6: 0x1A6CA1: std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>& std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::emplace_back<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> >(std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (vector.tcc:121)
  โ”‚   โ”‚       โ”‚   โ”‚       ^7: 0x1A063F: std::vector<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>, std::allocator<std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long> > >::push_back(std::variant<std::basic_string_view<char, std::char_traits<char> >, unsigned long>&&) (stl_vector.h:1201)
  โ”‚   โ”‚       โ”‚   โ”‚       ^8: 0x2E0727: graphql::service::SelectionVisitor::visitField(graphql::peg::ast_node const&) (GraphQLService.cpp:1006)
  โ”‚   โ”‚       โ”‚   โ”‚       ^9: 0x2DFDE6: graphql::service::SelectionVisitor::visit(graphql::peg::ast_node const&) (GraphQLService.cpp:913)
  โ”‚   โ”‚       โ”‚   โ”‚       ^10: 0x2E3101: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1215)
  โ”‚   โ”‚       โ”‚   โ”‚       #11: 0x2DF9F8: graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}::operator()(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) const (GraphQLService.cpp:830)
  โ”‚   โ”‚       โ”‚   โ”‚       #12: 0x308D58: graphql::service::ResolverResult std::__invoke_impl<graphql::service::ResolverResult, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::__invoke_other, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}&&, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) (invoke.h:60)
  โ”‚   โ”œโ”€โ–ผ AP 1.1.3/25 (2 children) {
  โ”‚   โ”‚     Total:     756,000 bytes (7.21%, 1,081.01/Minstr) in 4,500 blocks (4.58%, 6.43/Minstr), avg size 168 bytes, avg lifetime 63,480.14 instrs (0.01% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x32CA50: __gnu_cxx::new_allocator<graphql::service::FragmentDirectives>::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x3287DF: std::allocator_traits<std::allocator<graphql::service::FragmentDirectives> >::allocate(std::allocator<graphql::service::FragmentDirectives>&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x32459B: std::_Vector_base<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚       #5: 0x31E928: void std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_realloc_insert<graphql::service::FragmentDirectives>(__gnu_cxx::__normal_iterator<graphql::service::FragmentDirectives*, std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> > >, graphql::service::FragmentDirectives&&) (vector.tcc:440)
  โ”‚   โ”‚       #6: 0x318A68: graphql::service::FragmentDirectives& std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::emplace_back<graphql::service::FragmentDirectives>(graphql::service::FragmentDirectives&&) (vector.tcc:121)
  โ”‚   โ”‚       #7: 0x311ABD: std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::push_back(graphql::service::FragmentDirectives&&) (stl_vector.h:1201)
  โ”‚   โ”‚       #8: 0x2DFCA5: graphql::service::SelectionVisitor::SelectionVisitor(graphql::service::SelectionSetParams const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&, std::unordered_set<std::basic_string_view<char, std::char_traits<char> >, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > const&, std::vector<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::service::ResolverResult> (graphql::service::ResolverParams&&)> >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::service::ResolverResult> (graphql::service::ResolverParams&&)> > > > const&) (GraphQLService.cpp:897)
  โ”‚   โ”‚       #9: 0x2E30DD: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1213)
  โ”‚   โ”‚     }
  โ”‚   โ”‚   }
  โ”‚   โ”‚   โ”œโ”€โ”€ AP 1.1.3.1/2 {
  โ”‚   โ”‚   โ”‚     Total:     672,000 bytes (6.41%, 960.9/Minstr) in 4,000 blocks (4.07%, 5.72/Minstr), avg size 168 bytes, avg lifetime 61,708.63 instrs (0.01% of program duration)
  โ”‚   โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚   โ”‚       ^2: 0x32CA50: __gnu_cxx::new_allocator<graphql::service::FragmentDirectives>::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚   โ”‚       ^3: 0x3287DF: std::allocator_traits<std::allocator<graphql::service::FragmentDirectives> >::allocate(std::allocator<graphql::service::FragmentDirectives>&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚   โ”‚       ^4: 0x32459B: std::_Vector_base<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_allocate(unsigned long) (stl_vector.h:343)
  โ”‚   โ”‚   โ”‚       ^5: 0x31E928: void std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::_M_realloc_insert<graphql::service::FragmentDirectives>(__gnu_cxx::__normal_iterator<graphql::service::FragmentDirectives*, std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> > >, graphql::service::FragmentDirectives&&) (vector.tcc:440)
  โ”‚   โ”‚   โ”‚       ^6: 0x318A68: graphql::service::FragmentDirectives& std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::emplace_back<graphql::service::FragmentDirectives>(graphql::service::FragmentDirectives&&) (vector.tcc:121)
  โ”‚   โ”‚   โ”‚       ^7: 0x311ABD: std::vector<graphql::service::FragmentDirectives, std::allocator<graphql::service::FragmentDirectives> >::push_back(graphql::service::FragmentDirectives&&) (stl_vector.h:1201)
  โ”‚   โ”‚   โ”‚       ^8: 0x2DFCA5: graphql::service::SelectionVisitor::SelectionVisitor(graphql::service::SelectionSetParams const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&, std::unordered_set<std::basic_string_view<char, std::char_traits<char> >, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > const&, std::vector<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::service::ResolverResult> (graphql::service::ResolverParams&&)> >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> >, std::function<std::future<graphql::service::ResolverResult> (graphql::service::ResolverParams&&)> > > > const&) (GraphQLService.cpp:897)
  โ”‚   โ”‚   โ”‚       ^9: 0x2E30DD: graphql::service::Object::resolve(graphql::service::SelectionSetParams const&, graphql::peg::ast_node const&, std::unordered_map<std::basic_string_view<char, std::char_traits<char> >, graphql::service::Fragment, std::hash<std::basic_string_view<char, std::char_traits<char> > >, std::equal_to<std::basic_string_view<char, std::char_traits<char> > >, std::allocator<std::pair<std::basic_string_view<char, std::char_traits<char> > const, graphql::service::Fragment> > > const&, graphql::response::Value const&) const (GraphQLService.cpp:1213)
  โ”‚   โ”‚   โ”‚       #10: 0x2DF9F8: graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}::operator()(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) const (GraphQLService.cpp:830)
  โ”‚   โ”‚   โ”‚       #11: 0x308D58: graphql::service::ResolverResult std::__invoke_impl<graphql::service::ResolverResult, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::__invoke_other, graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}&&, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) (invoke.h:60)
  โ”‚   โ”‚   โ”‚       #12: 0x30866B: std::__invoke_result<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>::type std::__invoke<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::__invoke_result&&, (graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}&&)...) (invoke.h:96)
  โ”‚   โ”œโ”€โ”€ AP 1.1.4/25 {
  โ”‚   โ”‚     Total:     672,000 bytes (6.41%, 960.9/Minstr) in 2,000 blocks (2.04%, 2.86/Minstr), avg size 336 bytes, avg lifetime 650,920.47 instrs (0.09% of program duration)
  โ”‚   โ”‚     Allocated at {
  โ”‚   โ”‚       ^1: 0x4839E23: operator new(unsigned long)
  โ”‚   โ”‚       #2: 0x2FFD16: __gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, (__gnu_cxx::_Lock_policy)2> >::allocate(unsigned long, void const*) (new_allocator.h:114)
  โ”‚   โ”‚       #3: 0x2FE6BC: std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, (__gnu_cxx::_Lock_policy)2> > >::allocate(std::_Sp_counted_ptr_inplace<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, (__gnu_cxx::_Lock_policy)2>&, unsigned long) (alloc_traits.h:444)
  โ”‚   โ”‚       #4: 0x2FBD3F: std::__allocated_ptr<std::allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, (__gnu_cxx::_Lock_policy)2> > > std::__allocate_guarded<std::allocator<std::_Sp_counted_ptr_inplace<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, (__gnu_cxx::_Lock_policy)2> > >(std::__allocated_ptr&) (allocated_ptr.h:97)
  โ”‚   โ”‚       #5: 0x2FA10F: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >(std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>*&, std::_Sp_alloc_shared_tag<std::allocator<graphql::service::ResolverResult> >, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>&&) (shared_ptr_base.h:677)
  โ”‚   โ”‚       #6: 0x2F9899: std::__shared_ptr<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<graphql::service::ResolverResult>, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >(std::_Sp_alloc_shared_tag<std::allocator<graphql::service::ResolverResult> >, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>&&) (shared_ptr_base.h:1344)
  โ”‚   โ”‚       #7: 0x2F925E: std::shared_ptr<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult> >::shared_ptr<std::allocator<graphql::service::ResolverResult>, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >(std::_Sp_alloc_shared_tag<std::allocator<graphql::service::ResolverResult> >, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>&&) (shared_ptr.h:359)
  โ”‚   โ”‚       #8: 0x2F7A84: std::shared_ptr<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult> > std::allocate_shared<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::allocator<graphql::service::ResolverResult>, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >(std::allocator<graphql::service::ResolverResult> const&, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>&&) (shared_ptr.h:702)
  โ”‚   โ”‚       #9: 0x2F4416: std::shared_ptr<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult> > std::make_shared<std::__future_base::_Deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >, graphql::service::ResolverResult>, std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >(std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>&&) (shared_ptr.h:718)
  โ”‚   โ”‚       #10: 0x2EF320: std::shared_ptr<std::__future_base::_State_baseV2> std::__future_base::_S_make_deferred_state<std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> > >(std::thread::_Invoker<std::tuple<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams> >&&) (future:1691)
  โ”‚   โ”‚       #11: 0x2EB382: std::future<std::__invoke_result<std::decay<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}>::type, std::__invoke_result<graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> > >::type, std::__invoke_result<graphql::service::ResolverParams>::type>::type> std::async<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}, graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >, graphql::service::ResolverParams>(std::launch, std::decay&&, (std::decay<graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)::{lambda(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&)#1}>::type&&)...) (future:1730)
  โ”‚   โ”‚       #12: 0x2DFAE5: graphql::service::ModifiedResult<graphql::service::Object>::convert(graphql::service::FieldResult<std::shared_ptr<graphql::service::Object> >&&, graphql::service::ResolverParams&&) (GraphQLService.cpp:837)

Massif

Branch/Commit Lowest Peak
daecf27 106,288 121,376
bd725ac 145,552 155,672
Difference +36.94% +28.25%

parser-tweaks daecf27

    KB
118.5^ #                                                                      
     | #   :::::     :::::  ::::::@@@:@@:         ::::::::::@@:::  :: :::     
     | #:::: : ::::::: :::::::  ::@  :@ ::::::::::: : :: : :@ :: :::::: :::: :
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
     | #: :: : :: : :: :::: ::  ::@  :@ :: :::: ::: : :: : :@ :: :::::: :: :::
   0 +----------------------------------------------------------------------->Mi
     0                                                                   297.0

master bd725ac

    KB
152.0^                                                                    @   
     |#:: :::::::: :::::: ::: :@:: : ::::@::::::@:::::@: ::: @:: ::@: ::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
     |#::@::::::::::::@::::::::@:::::::: @::::::@:::::@::::::@:::::@::::::@:::
   0 +----------------------------------------------------------------------->Mi
     0                                                                   662.3

Specifying an empty string for an argument description crashes schemagen

If you put empty double quotes (or block quotes) in front of a field argument, schemagen crashes when trying to parse the schema:

std::__uniq_ptr_impl<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >::_M_ptr(const std::__uniq_ptr_impl<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > * this) (/usr/include/c++/9/bits/unique_ptr.h:154)
std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >::get(const std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > * this) (/usr/include/c++/9/bits/unique_ptr.h:361)
std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >::operator->(const std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > * this) (/usr/include/c++/9/bits/unique_ptr.h:355)
graphql::schema::Generator::getInputFields(const std::vector<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >, std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > > & fields) (cppgraphqlgen/src/SchemaGenerator.cpp:1305)
graphql::schema::Generator::getOutputFields(const std::vector<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> >, std::allocator<std::unique_ptr<graphql::peg::ast_node, std::default_delete<graphql::peg::ast_node> > > > & fields) (cppgraphqlgen/src/SchemaGenerator.cpp:1201)
graphql::schema::Generator::visitObjectTypeExtension(graphql::peg::ast_node const&)::$_7::operator()(graphql::peg::ast_node const&) const(const class {...} * this, const graphql::peg::ast_node & child) (cppgraphqlgen/src/SchemaGenerator.cpp:806)
std::_Function_handler<void (graphql::peg::ast_node const&), graphql::schema::Generator::visitObjectTypeExtension(graphql::peg::ast_node const&)::$_7>::_M_invoke(std::_Any_data const&, graphql::peg::ast_node const&)(const std::_Any_data & __functor, const graphql::peg::ast_node & __args) (/usr/include/c++/9/bits/std_function.h:300)
std::function<void (graphql::peg::ast_node const&)>::operator()(graphql::peg::ast_node const&) const(const std::function<void (const graphql::peg::ast_node &)> * this, const graphql::peg::ast_node & __args) (/usr/include/c++/9/bits/std_function.h:688)
graphql::peg::on_first_child<graphql::peg::fields_definition>(graphql::peg::ast_node const&, std::function<void (graphql::peg::ast_node const&)>&&)(const graphql::peg::ast_node & n, std::function<void (const graphql::peg::ast_node &)> && func) (cppgraphqlgen/include/graphqlservice/GraphQLGrammar.h:44)
graphql::schema::Generator::visitObjectTypeExtension(graphql::schema::Generator * this, const graphql::peg::ast_node & objectTypeExtension) (cppgraphqlgen/src/SchemaGenerator.cpp:803)
graphql::schema::Generator::visitObjectTypeDefinition(graphql::schema::Generator * this, const graphql::peg::ast_node & objectTypeDefinition) (cppgraphqlgen/src/SchemaGenerator.cpp:778)
graphql::schema::Generator::visitDefinition(graphql::schema::Generator * this, const graphql::peg::ast_node & definition) (cppgraphqlgen/src/SchemaGenerator.cpp:715)
graphql::schema::Generator::Generator(graphql::schema::Generator * this, graphql::schema::GeneratorOptions && options) (cppgraphqlgen/src/SchemaGenerator.cpp:291)
main(int argc, char ** argv) (cppgraphqlgen/src/SchemaGenerator.cpp:3585)

The problem is that the children vector of the description node is empty, so de-referencing front() causes a segmentation fault:

else if (child->is_type<peg::description>())
{
	field.description = child->children.front()->unescaped;
}

Undefined reference to std::vector<string> in samples

Unfortunately I get a undefined reference to std::vector when I compile the samples/tests.

My environment:
Ubuntu 19.04 disco with clang 8.0.1

Verbose linker output:
clang version 8.0.1-svn360950-1~exp1~20190517001536.70 (branches/release_80)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.4.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Selected multilib: .;@m64
"/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o samples/sample /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/9/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/usr/lib/x86_64-linux-gnu/../../lib64 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../.. -L/usr/lib/llvm-8/bin/../lib -L/lib -L/usr/lib samples/CMakeFiles/sample.dir/today/sample.cpp.o samples/libseparategraphql.a src/libgraphqljson.a src/libgraphqlservice.a src/libgraphqlpeg.a -lpthread -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib/gcc/x86_64-linux-gnu/9/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o

Link error:

/usr/bin/ld: samples/libseparategraphql.a(SeparateToday.cpp.o): in function `graphql::today::EdgeConstraints<graphql::today::Appointment, graphql::today::AppointmentConnection>::operator()(std::optional<int> const&, std::optional<graphql::response::Value> const&, std::optional<int> const&, std::optional<graphql::response::Value> const&) const':
SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_11AppointmentENS0_21AppointmentConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_11AppointmentENS0_21AppointmentConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x583): undefined reference to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()'

Full error output:

[2/2 0.3/sec] Linking CXX executable samples/sample
FAILED: samples/sample 
: && /usr/bin/clang++  -std=c++17   samples/CMakeFiles/sample.dir/today/sample.cpp.o  -o samples/sample  -v samples/libseparategraphql.a src/libgraphqljson.a src/libgraphqlservice.a src/libgraphqlpeg.a -lpthread && :
clang version 8.0.1-svn360950-1~exp1~20190517001536.70 (branches/release_80)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.4.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.4.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/9
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/9
Candidate multilib: .;@m64
Selected multilib: .;@m64
 "/usr/bin/ld" -z relro --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o samples/sample /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crt1.o /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crti.o /usr/bin/../lib/gcc/x86_64-linux-gnu/9/crtbegin.o -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../lib64 -L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib64 -L/usr/lib/x86_64-linux-gnu/../../lib64 -L/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../.. -L/usr/lib/llvm-8/bin/../lib -L/lib -L/usr/lib samples/CMakeFiles/sample.dir/today/sample.cpp.o samples/libseparategraphql.a src/libgraphqljson.a src/libgraphqlservice.a src/libgraphqlpeg.a -lpthread -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/bin/../lib/gcc/x86_64-linux-gnu/9/crtend.o /usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/crtn.o
/usr/bin/ld: samples/libseparategraphql.a(SeparateToday.cpp.o): in function `graphql::today::EdgeConstraints<graphql::today::Appointment, graphql::today::AppointmentConnection>::operator()(std::optional<int> const&, std::optional<graphql::response::Value> const&, std::optional<int> const&, std::optional<graphql::response::Value> const&) const':
SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_11AppointmentENS0_21AppointmentConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_11AppointmentENS0_21AppointmentConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x583): undefined reference to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()'
/usr/bin/ld: SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_11AppointmentENS0_21AppointmentConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_11AppointmentENS0_21AppointmentConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x8b8): undefined reference to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()'
/usr/bin/ld: samples/libseparategraphql.a(SeparateToday.cpp.o): in function `graphql::today::EdgeConstraints<graphql::today::Task, graphql::today::TaskConnection>::operator()(std::optional<int> const&, std::optional<graphql::response::Value> const&, std::optional<int> const&, std::optional<graphql::response::Value> const&) const':
SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_4TaskENS0_14TaskConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_4TaskENS0_14TaskConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x583): undefined reference to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()'
/usr/bin/ld: SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_4TaskENS0_14TaskConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_4TaskENS0_14TaskConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x8b8): undefined reference to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()'
/usr/bin/ld: samples/libseparategraphql.a(SeparateToday.cpp.o): in function `graphql::today::EdgeConstraints<graphql::today::Folder, graphql::today::FolderConnection>::operator()(std::optional<int> const&, std::optional<graphql::response::Value> const&, std::optional<int> const&, std::optional<graphql::response::Value> const&) const':
SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_6FolderENS0_16FolderConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_6FolderENS0_16FolderConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x583): undefined reference to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()'
/usr/bin/ld: samples/libseparategraphql.a(SeparateToday.cpp.o):SeparateToday.cpp:(.text._ZNK7graphql5today15EdgeConstraintsINS0_6FolderENS0_16FolderConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_[_ZNK7graphql5today15EdgeConstraintsINS0_6FolderENS0_16FolderConnectionEEclERKSt8optionalIiERKS5_INS_8response5ValueEES8_SD_]+0x8b8): more undefined references to `std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~vector()' follow
clang: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.
08:17:47: The process "/usr/bin/cmake" exited with code 1.

Any idea?

"graphqlservice/IntrospectionSchema.h" file is not found

First of all: really excited to be using this library. Seems like a good modern solution for GraphQL in cpp. :)

I'm running schemagen and a .cpp and .h come rolling out, but get a compilation error when I try to compile the source file. The generated.cpp contains the following line:

#include "graphqlservice/Introspection.h"

which, in turn, contains this line:

#include "graphqlservice/IntrospectionSchema.h"

But IntrospectionSchema.h is nowhere to be found? Should that also be generated? If so, that doesn't seem to be happening, and if not, I can't find it in the repository anywhere.

Using the master branch, compiling with Xcode on macOS.

boost program_options linking error when compiling schemagen on ubuntu 16.04 with clang++ 9

I have a server with Ubuntu 16.04 and without internet, so I have to copy llvm9.0 prebuilt binary into server.

clang++ with arguments -stdlib=libc++ -fuse-ld=lld

I can build graphqlpeg and graphqlresponse, but with schemagen, I get error with boost::program_options linking error.

[  4%] Built target graphqlpeg
[  8%] Built target graphqlresponse
[ 11%] Linking CXX executable schemagen
ld.lld: error: undefined symbol: boost::program_options::operator<<(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, boost::program_options::options_description const&)
>>> referenced by SchemaGenerator.cpp
>>>               CMakeFiles/schemagen.dir/SchemaGenerator.cpp.o:(outputUsage(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, boost::program_options::options_description const&))

ld.lld: error: undefined symbol: boost::program_options::options_description::options_description(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned int, unsigned int)
>>> referenced by SchemaGenerator.cpp
>>>               CMakeFiles/schemagen.dir/SchemaGenerator.cpp.o:(main)
>>> referenced by SchemaGenerator.cpp
>>>               CMakeFiles/schemagen.dir/SchemaGenerator.cpp.o:(main)

I have tried the newest release 1.73 and the version you have mentioned in README aka 1.65, all failed with the same error.

can you replace boost with other library?

Use mainloop, callbacks (or observer) instead of std::async

Currently the project uses std::async() to execute the resolvers, it may take different execution modes using std::launch::deferred:

  • std::launch::deferred (default) postpones the execution until future.get() is called, blocking the thread execution
  • std::launch::async creates a new thread (on Linux it doesn't use thread pools), allows resolvers to work in parallel.

None of them works good in practice, since either you serialize all the work, which is horrible to reach REST, DB or other systems with higher latency; or you create lots of threads in the system (which implies in reaching the kernel, all the thread bookkeeping, etc).

Most production systems will use some kind of "Main Loop" or "Event Loop", that in UNIX will use select(), poll(), epoll (Linux), kqueue (MacOS) or variants, which allows the same thread to wait on multiple resources in the same thread.

Then I'd like to see if there is any chance this project will support some kind of callbacks (or observer pattern) that could allow a mainloop/eventloop to be used, or use some primitives such as setImmediate() where we can implement a more
https://promisesaplus.com/ promise, instead of the C++ version, namely allowing Promise.all() to be used to get all the fields of an object.

Subscriptions should use the Operations object as a fallback

That way either the subscriptionObject parameter to Request::deliver or the parameter to the generated Operations constructor can be treated as optional, and consumers who only want to serve subscription queries from a single instance can pass that to the constructor.

Cannot pass enum values in variables

I need to relax the ModifiedArgument<EnumType> parameter validation to accept string values, or maybe better yet provide a mechanism to convert a response::Value of type String to EnumValue from the resolver's generated implementation so it can do that dynamically before calling require or find.

Why response::Value::_data is allocated

Why do we have response::Value::_data allocated on demand? Given that it's a std::variant<> of the internal types

Allocation https://github.com/microsoft/cppgraphqlgen/blob/master/src/GraphQLResponse.cpp#L70-L96
Variant https://github.com/microsoft/cppgraphqlgen/blob/master/src/GraphQLResponse.cpp#L58-L60

Unless there is a reason I didn't see, I'd propose to unify that in a single memory unit, inlining _data or even making that the response::Value itself, since we don't even need to hold the type, given that we could discover it using std::variant, such as std::holds_alternative.

Generated files should have NYI stub implementations

It's inconvenient to have to subclass and override every method in the implementation classes before you can even build and link a project.

Using a stub implementation might also make it possible to create optional synchronous resolvers, so simpler overrides don't need to go through a construct std::promise - set_value - get_future dance. I think it should be possible (might require template metaprogramming, maybe just additional protected virtual methods) to override either an async or synchronous version of the resolver and have the default implementation of the async method call the synchronous version if that's the one the implementer chose to override.

Add support for schema/type extensions

The schema spec and PEG parser include support for schema and type extension definitions, but schemagen doesn't do anything with them. It should append the extensions to the types/schema as appropriate.

Parser refuses valid query input if immediately followed by a fragment definition

If the query below was passed by stdin, the Parser (v3.0.2) reacted with an error message like ..."/graphql/June2018/#Document".

        query { 
           person(name: "Joe") { ...personFields } 
        }

        fragment personFields on Person { id  }

Note the blank line before the fragment definition. I found this while testing a main loop more or less copied from the today example. Therein, the statement


        while (std::getline(std::cin, line)) {input.append(line);}

effectively strips newline characters.

When feeding the query via stdin, the query resulted in an error -- but not when the query was passed as a filename to be read via peg::parseFile(argv[1]) directly. Yet the real problem seems to be hidden in the parser. The follwing input (with angle brackets denoting the exact content )

      <query{person(name:"Joe"){...personFields}}fragment personFields on Person {id}>

fails with boths variants (stdin, passing file name: premature EOF), whereas inserting a space between "} and "fragment" is sufficient to get the input accepted.

Since the grammar looks fine this behaviour may also be caused by a compiler bug. I used gcc-9.1. gcc-9.2 did not succeed because of some weired problems within a cppgraphqlgen header.

cpprestsdk is overkill (and too big) to use it all the time for JSON support

I used Microsoft/cpprestsdk for JSON support since it's fairly common in Microsoft projects and is often already included as a dependency. But there are a lot of other header-only JSON libraries I could use instead, and they would greatly reduce the dependency list and package size.

I think it makes sense to add support for an alternate JSON library in another branch and possibly as a configuration option in CMake.

schemagen invalid output

This minimal schema:

schema {
  query: RootQuery
}

type RootQuery {
  test: Int!
}

produces this ApiSchema.h, which cloese the object namespace in the wrong location:

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

#pragma once

#include <graphqlservice/GraphQLService.h>
#include <memory>
#include <string>
#include <vector>

namespace graphql {
namespace introspection {

class Schema;
class ObjectType;

} /* namespace introspection */

namespace roll42 {

namespace object {

class RootQuery;

class Operations : public service::Request {
 public:
  Operations(std::shared_ptr<object::RootQuery> query);

 private:
  std::shared_ptr<object::RootQuery> _query;
};

void AddRootQueryDetails(std::shared_ptr<introspection::ObjectType> typeRootQuery,
                         std::shared_ptr<introspection::Schema>     schema);

void AddTypesToSchema(std::shared_ptr<introspection::Schema> schema);

} /* namespace object */
} /* namespace roll42 */
} /* namespace graphql */

This only happens when --separate-files is used. This happens both with the latest master and v3.0.3.

Planned changes in 3.0

I'm starting a list of improvements I'd like to make for 3.0. Many of these will break backwards compatibility, so I hope to do as many of them as possible in a single major version release.

Adopting C++17

  • Move to PEGTL master/3.0.0 (not yet officially released, also requires PR #43)
  • Use std::variant for response::Value
  • Replace std::unique_ptr for nullable fields with std::optional

Schemagen improvements

  • Make NYI stub generation optional
  • Split the class definitions/declarations into separate files. May also help with making the NYI stubs optional (i.e. decide whether or not to compile and link them individually).
  • Improve error handling/reporting. Currently if there's a schema validation error it gives a very poor error message and requires attaching a debugger to track down what caused the error.
  • Add command line options for things like defining a target directory. Also another way to make the NYI stubs optional.
  • Change the names of the generated Mutation accessors to something like applyFieldName. Calling everything getFieldName feels strange when performing a mutation.

Miscellaneous/TBD

  • Let the caller specify the std::launch policy for the Request::resolve top-level call.
  • Replace resolver std::unordered_map with either a pre-sorted std::vector or generated if/else if blocks?
  • Build a separate library target for the grammar/AST.
  • Replace std::string with std::string_view where appropriate.
  • Replace ast<std::string> with ast<std::string_view> or ast<std::vector<char>> to deal with small-string-optimization issues rather than reserving extra space when the string is too short.
  • Replace the facebook::graphql namespace with just graphql for the sake of brevity.

Documentation

  • Should add more documentation, either to the README.md or in sub-documents.

Postponed to 3.1

  • Use a PIMPL pattern or CRTP instead of inheritance for more static polymorphism?
  • Experiment with Protocol Buffers for response serialization, but maybe in a separate project like cppgraphiql.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.