graphql-java / graphql-java/graphql-java

1% possible memory and cpu improvements

オープン
#3,939 コメント 4 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

keep-open performance
主要言語
Java
スター
6.2k
フォーク
1.1k
平均マージ
22分
マージ済み PR(30日)
14

説明

graphql-java is a mature and optimised library. So its increasingly difficult to find performance improvements that really stand out.

This leads us to the 1% club where we need to do a bunch of work to get a small 1% gain

This issue tries to capture investigations of these 1%'ers and hence be a list of possible micro improvements

Profiler investigations - memory

Running ComplexQueryPeformance as load and using JProfiler

The biggest objects are as follows

Image

"graphql.execution.ExecutionStrategyParameters", 4% of memory
"graphql.execution.ExecutionStrategyParameters$Builder", 4% of memory use
"graphql.execution.ExecutionStepInfo" 2%
"graphql.execution.ExecutionStepInfo$Builder", 2%
"graphql.execution.NonNullableFieldValidator", 2%
"graphql.execution.FetchedValue", 2%

I have PRS that try to reduce all these - eg either remove the builder usage for "transforms" (ExecutionStrategyParameters and ExecutionStepInfo)

or avoid re-allocating per field (NonNullableFieldValidator and FetchedValue)

https://github.com/graphql-java/graphql-java/pull/3924
https://github.com/graphql-java/graphql-java/pull/3929
https://github.com/graphql-java/graphql-java/pull/3934
https://github.com/graphql-java/graphql-java/pull/3935

The builder ones reduce by memory per type by half right - because we no longer create a builder to actually create a ExecutionStepInfo say

interesting future things to look into

  • "graphql.util.IntraThreadMemoizedSupplier", 4%
    ** why so heavy - do we strictly need it

  • "graphql.schema.FieldCoordinates" 2%
    ** can we avoid this some how - flyweights?

  • "graphql.schema.PropertyFetchingImpl$CacheKey", 2%
    ** can we avoid this some how - flyweights?

  • "com.google.common.collect.SingletonImmutableList", 2%
    ** why so high?? Are we wrapping something for no reason

  • "graphql.schema.DataFetcherFactoryEnvironment", 2%
    ** "graphql.schema.DataFetcherFactoryEnvironment$Builder" 2%
    ** this can go I think

asserts cost cpu and memory

Image

eg :

this.executionStepInfo = assertNotNull(executionStepInfo, () -> "executionStepInfo is null");

These asserts are great for code reasons - but they cost something to run

Can we use the jspecify annotations here and remove these because static analysis is giving us the safety ?

cpu hot spots to look into

  • 1.6% - 1,256 ms - 1,372,469 hot spot inv. graphql.schema.GraphQLCodeRegistry.getDataFetcherImpl

  • 1.5% - 1,190 ms - 7,119,736 hot spot inv. graphql.schema.GraphQLTypeUtil.unwrapNonNull

  • 1.5% - 1,209 ms - 7,088,722 hot spot inv. graphql.execution.ExecutionStepInfo.getUnwrappedNonNullType

  • 1.3% - 1,010 ms - 12,160,902 hot spot inv. graphql.Assert.assertNotNull(java.lang.Object, java.util.function.Supplier)

  • 1.0% - 786 ms - 1,485,657 hot spot inv. graphql.execution.ExecutionStrategy.unboxPossibleDataFetcherResult

This is an interesting one - its called on DataFetch BUT its also called in completeValueForList

meaning can a DF returns a DataFetcherResult that itself is a list of DataFetcherResult of values. Is this even remotely sensible?? Can we kill it in lists the name of 1% ??

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

調査の方向性

プロファイラの調査結果と既存のPR 3924、3929、3934、3935から始め、次にComplexQueryPeformanceを実行してベースラインを確立します。一覧にあるメモリまたはCPUホットスポットを1つ選び、その関連するエントリポイントを追跡します。完了とするには、ベースラインに対して検証された測定可能な改善が必要です。

索引モデルが issue の本文から書いたものです。

評価

技術スタック
graphql, java
領域
backend-api-design, performance
issue の種類
リファクタリング
難易度
5/5
見積もり時間
1週間以上
活発さ
停滞
明瞭さ
説明が足りない
初心者へのやさしさ
25/100

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。