Skip to content

listRepos is too slow #80

Description

@snarfed

I'm seeing it take 20+s in prod right now for limit=1000, which is way too slow.

$ time curl -v 'https://atproto.brid.gy/xrpc/com.atproto.sync.listRepos?limit=1000'
...
0.022u 0.028s 0:22.79 0.1%	0+0k 0+0io 2pf+0w

Not sure why though. All it does is call storage.load_repos and then construct the output, and all load_repos does is query AtpRepos, load their head AtpBlocks, and then return.

def list_repos(input, limit=500, cursor=None):
"""Handler for ``com.atproto.sync.listRepos`` XRPC method."""
STATUSES = {'tombstoned': 'deactivated'}
repos = []
for repo in server.storage.load_repos(limit=limit, after=cursor, minimal=True):
repo_obj = {
'did': repo.did,
'head': repo.head.cid.encode('base32'),
'rev': util.int_to_tid(repo.head.seq, clock_id=0),
'active': repo.status is None,
}
if repo.status:
repo_obj['status'] = STATUSES.get(repo.status) or repo.status
repos.append(repo_obj)
ret = {'repos': repos}
if len(repos) == limit:
ret['cursor'] = repos[-1]['did']
return ret

def load_repos(self, after=None, limit=500, minimal=False):
query = AtpRepo.query()
if after:
query = query.filter(AtpRepo.key > AtpRepo(id=after).key)
# duplicates parts of Repo.load but batches reading blocks from storage
atp_repos = query.fetch(limit=limit)
cids = [CID.decode(r.head) for r in atp_repos]
blocks = self.read_many(cids) # dict mapping CID to block
heads = [blocks[cid] for cid in cids]
if minimal:
return [Repo(storage=self, head=head, status=atp_repo.status)
for atp_repo, head in zip(atp_repos, heads)]
# MST.load doesn't read from storage
msts = [MST.load(storage=self, cid=block.decoded['data']) for block in heads]
return [Repo(storage=self, mst=mst, head=head, status=atp_repo.status,
handle=atp_repo.handles[0] if atp_repo.handles else None,
signing_key=atp_repo.signing_key,
rotation_key=atp_repo.rotation_key)
for atp_repo, head, mst in zip(atp_repos, heads, msts)]

Note the minimal=True. I originally though the private key parsing and loading was the culprit, so I now skip that, but that didn't really help. 😕

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions