【发布时间】:2021-11-19 20:19:37
【问题描述】:
关于:https://github.com/gvasquez95/binance-trader/issues/8
我担心实际的“内部”等待(在 getPriceChange 的每次调用中)不会阻止此方法在外部循环 (getPriceChanges) 上的大约 1.5k 调用的异步调用。好像它是阻塞的,那么循环将是串行处理。
从性能视图和时序来看,我想说它按预期工作,因为完成整个过程只需要几秒钟,但是,如果可能的话,我想要一个假设的编程 ACK。
为那些不想进入 GitHub 的人屏蔽代码,并且更喜欢这里的代码更明显:
外循环:
async function getPriceChanges (since, breakpoint) {
const changes = []
for (const [i, ticker] of tickers.entries()) {
if (!ticker.includes('BIDR') && !ticker.includes('BIFI')) {
changes.push(getPriceChange(ticker, since, breakpoint))
}
}
const res = await Promise.all(changes)
let symbol
let maxChange = 0
let slope = 0
for (const ticker of res) {
if (ticker.percentChange > maxChange && ticker.slope > Math.pow(10, -1 * NUM_DECIMALS)) {
maxChange = ticker.percentChange
symbol = ticker.symbol
slope = ticker.slope
}
}
return { symbol, maxChange: Math.round(100 * maxChange) / 100, slope: round(slope, NUM_DECIMALS) }
}
内部getPriceChange函数:
async function getPriceChange (symbol, since, breakpoint) {
const params = {
TableName: DYNAMODB_TABLE,
ProjectionExpression: '#timestamp, price',
KeyConditionExpression: 'symbol = :symbol and #timestamp > :timestamp',
ExpressionAttributeNames: {
'#timestamp': 'timestamp'
},
ExpressionAttributeValues: {
':symbol': symbol,
':timestamp': since
}
}
const res = await documentClient.query(params).promise()
const prev = []
const recent = []
const trendData = []
for (const data of res.Items) {
if (data.timestamp < breakpoint) {
prev.push(data.price)
} else {
trendData.push({ x: trendData.length, y: data.price })
recent.push(data.price)
}
}
let sumPrev = 0
let sumRecent = 0
for (const price of prev) { sumPrev += price }
for (const price of recent) { sumRecent += price }
const avgPrev = sumPrev / prev.length
const avgRecent = sumRecent / recent.length
const trend = createTrend(trendData, 'x', 'y')
return { symbol, percentChange: (100 * (avgRecent - avgPrev)) / avgRecent, slope: trend.slope }
}
更新: 在 Node.js 14.x AWS Lambda 环境中,函数执行大约需要 30 秒,配置有 624 MB RAM,从成本角度来看,DynamoDB 查询 (ReadRequests) 成本和 Lambda 执行都是实际 DynamoDB Batch 的 1/50放置操作(WriteRequest),因此优化查询应该是一个需要的目标。
【问题讨论】:
-
我认为主要要做的是找到一种方法来进行 one 查询以返回记录列表,而不是进行数千次查询。仅网络延迟,即使查询花费 0 时间,也会很严重。
-
您是否要在循环中顺序执行调用?我不确定你到底关心什么。
-
@Pointy 不幸的是,考虑到底层数据结构、数据存储在 DynamoDB 中的方式以及选择/需要的主键/排序键,使用单个查询对 bd 引擎来说是过度杀伤力,即使我甚至不能 100% 确定它可以完成,但既然你提到了它,我会看看我能做些什么。
-
您的循环中没有
await。所有这些电话都将开始。没有内在等待这样的东西。你必须await getPriceChange(....)来序列化它。按照您的方式,每个 getPriceChange 调用都会运行到它的第一个await并返回一个承诺。结果是许多documentClient.query电话在进行中,并且您有很多承诺。 (如你所知,因为你必须Promise.all很多) -
@gvasquez 你可能应该在你的 dynamodb 中添加一个二级索引。正如 Pointy 所说,一次处理 1.5k 个网络请求并不好。
标签: javascript node.js asynchronous async-await promise