【发布时间】:2019-10-18 08:44:48
【问题描述】:
在解析大型数据时,我注意到从解析器将结果返回给客户端的那一刻起,性能非常缓慢。
我假设apollo-server 会遍历我的结果并检查类型...无论哪种方式,操作都需要很长时间。
在我的产品中,我必须一次性返回大量数据,因为它被一次性用于在 UI 中绘制图表。没有分页选项可供我对数据进行切片。
我怀疑速度慢来自apollo-server,而不是我的解析器对象创建。
请注意,我记录了解析器创建对象所花费的时间,它的速度,而不是瓶颈。
apollo-server 执行的后续操作,我不知道如何衡量,需要很多时间。
现在,我有一个版本,我在其中返回自定义标量类型 JSON,响应速度要快得多。但我真的更喜欢返回我的 Series 类型。
我通过查看网络面板来测量两种类型(Series 和 JSON)之间的差异。
当 AMOUNT 设置为 500 且类型为 Series 时,大约需要 1.5 秒(即秒)
当 AMOUNT 设置为 500 且类型为 JSON 时,大约需要 150 毫秒(快!)
当AMOUNT设置为1000,类型为Series时,速度很慢...
当 AMOUNT 设置为 10000 且类型为 Series 时,我的 JavaScript 堆内存不足(不幸的是,我们在产品中遇到了这种情况)
我还将apollo-server 的性能与express-graphql 进行了比较,后者运行得更快,但仍不如返回自定义标量 JSON 快。
当 AMOUNT 设置为 500 时,apollo-server,网络耗时 1.5s
当 AMOUNT 设置为 500 时,express-graphql,网络耗时 800ms
当 AMOUNT 设置为 1000 时,apollo-server,网络耗时 5.4s
当 AMOUNT 设置为 1000,express-graphql,网络耗时 3.4s
堆栈:
"dependencies": {
"apollo-server": "^2.6.1",
"graphql": "^14.3.1",
"graphql-type-json": "^0.3.0",
"lodash": "^4.17.11"
}
代码:
const _ = require("lodash");
const { performance } = require("perf_hooks");
const { ApolloServer, gql } = require("apollo-server");
const GraphQLJSON = require('graphql-type-json');
// The GraphQL schema
const typeDefs = gql`
scalar JSON
type Unit {
name: String!
value: String!
}
type Group {
name: String!
values: [Unit!]!
}
type Series {
data: [Group!]!
keys: [Unit!]!
hack: String
}
type Query {
complex: Series
}
`;
const AMOUNT = 500;
// A map of functions which return data for the schema.
const resolvers = {
Query: {
complex: () => {
let before = performance.now();
const result = {
data: _.times(AMOUNT, () => ({
name: "a",
values: _.times(AMOUNT, () => (
{
name: "a",
value: "a"
}
)),
})),
keys: _.times(AMOUNT, () => ({
name: "a",
value: "a"
}))
};
let after = performance.now() - before;
console.log("resolver took: ", after);
return result
}
}
};
const server = new ApolloServer({
typeDefs,
resolvers: _.assign({ JSON: GraphQLJSON }, resolvers),
});
server.listen().then(({ url }) => {
console.log(`???? Server ready at ${url}`);
});
游乐场的 gql 查询(对于类型系列):
query {
complex {
data {
name
values {
name
value
}
}
keys {
name
value
}
}
}
游乐场的 gql 查询(用于自定义标量类型 JSON):
query {
complex
}
这是一个工作示例:
https://codesandbox.io/s/apollo-server-performance-issue-i7fk7
任何线索/想法将不胜感激!
【问题讨论】:
-
与 graphql 无关——你只测试节点 js 性能(对象创建)——这样你甚至可以在解析器中挖掘加密货币并指责 graphql
-
@xadm 我也不认为它与 graphql 相关,我没有这么说。我认为它与我在解析器中创建对象后的
apollo-server的以下操作有关(不管它是一个 gql 库,如果有帮助的话)。我的对象创建速度很快,接下来发生的事情很慢,直到内存堆不足......我认为我的 stringify 示例证明了这一点。我的问题是如何克服这个限制? -
您没有提供总体流程结果与记录的对象创建时间...问题是:您真的需要所有这些嵌套数据一次 ...客户端缓存将标准化也需要很多时间
-
@xadm 我不知道如何衡量整个过程的结果,因为它发生在 apollo-server 内部代码中,我相信。正如我所写,我确实测量了我正在记录的解析器对象创建时间,您可以在示例中看到它。我能够测量的另一件事是网络时间,以及当我对对象进行字符串化而不是字符串化时的不同结果。关于我是否一次需要它,现在是的,它是我在客户端上绘制的 UI 图的一部分,或者是一个有很多列的表格。不幸的是,没有分页选项可以让我获取部分。
-
可能您不需要小粒度数据 - 您可以使用 custom scalar types 将整个系列作为一个对象返回 - 如果确实需要详细的粒度,您可以稍后再做,仅限客户端
标签: graphql apollo-server