Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Big performance issues with v10.24.2 and Synced Realm #7743

Closed
duncangroenewald opened this issue Apr 11, 2022 · 46 comments
Closed

Big performance issues with v10.24.2 and Synced Realm #7743

duncangroenewald opened this issue Apr 11, 2022 · 46 comments

Comments

@duncangroenewald
Copy link

duncangroenewald commented Apr 11, 2022

How frequently does the bug occur?

All the time

Description

We have just encountered quite significant performance issues with generating reports from a Synced Realm.

The same issue does not occur when the same realm is opened as a local realm.

I am going to revert to earlier versions to see if I can find out when this because an issue.

I believe we might have previously used v10.19.0 but updated because of the Xcode 13.3 support in the built binaries with 10.24.

In the meantime if anyone has any ideas please let me know. I will revert to 10.19.0 to confirm that version does not have the issue.

Stacktrace & log output

N/A

Can you reproduce the bug?

Yes, always

Reproduction Steps

Generating standard reports usually take around 111 seconds but now take upwards of 30 minutes or more.

Version

10.24.2

What SDK flavour are you using?

MongoDB Realm (i.e. Sync, auth, functions)

Are you using encryption?

No, not using encryption

Platform OS and version(s)

macOS 12.0

Build environment

Xcode version: 13.3
Dependency manager and version: Prebuilt Binaries

@duncangroenewald
Copy link
Author

OK I just rebuilt using v10.19.0 and the problem goes away so something has been broken that is causing a major slow down with queries in 10.24.2.
I will try with 10.20.x etc to see when the problem starts occurring and post and update here.

@duncangroenewald
Copy link
Author

duncangroenewald commented Apr 11, 2022

Hmm so unable to build v10.21.0 or v10.22.0 with Xcode 13.3 using SPM. v10.23.0 builds OK but now the Realm App we use for testing has become unresponsive and never responds to the initial client sync request.

I have logged an issue with Atlas but since it is a Shared Free environment I doubt they will look at it. So perhaps someone from MongoDB team can check it out as it is most likely a bug that needs fixing as well.

So I can either blow away that broken environment and build a new on to continue testing the SDK versions for the performance issues or keep the environment there for someone to check why it has become unresponsive.

Here is the trace from a node.js client trying to connect the first time.

`Apr 11 2022 16:04:01 : run()
Apr 11 2022 16:04:01 : app: makespacetest-mfbpk
Apr 11 2022 16:04:01 : logging in...
Apr 11 2022 16:04:02 : logged in.
Apr 11 2022 16:04:02 : queryRealm()
Realm sync client ([realm-core-11.12.0])
Supported protocol versions: 2-3
Platform: macOS Darwin 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:46:32 PDT 2022; root:xnu-8020.101.415/RELEASE_ARM64_T6000 arm64
Build mode: Release
Config param: one_connection_per_session = true
Config param: connect_timeout = 120000 ms
Config param: connection_linger_time = 30000 ms
Config param: ping_keepalive_period = 60000 ms
Config param: pong_keepalive_timeout = 120000 ms
Config param: fast_reconnect_limit = 60000 ms
Config param: disable_upload_compaction = false
Config param: disable_sync_to_disk = false
User agent string: 'RealmSync/11.12.0 (macOS Darwin 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:46:32 PDT 2022; root:xnu-8020.101.4
15/RELEASE_ARM64_T6000 arm64) RealmJS/10.14.0 (node.js, darwin, vv16.13.0) '
Connection[1]: Session[1]: Binding '/Users/duncangroenewald/Development/RealmDB/RealmMigrationMongoDB3/mongodb-realm/makespacetest-mfbpk/6252b698aeeebad015282c23/s_default.realm' to '"default"'
Connection[1]: Session[1]: Activating
Connection[1]: Session[1]: client_reset_config = false, Realm exists = true, client reset = false
Connection[1]: Session[1]: client_file_ident = 0, client_file_ident_salt = 0
Connection[1]: Session[1]: last_version_available = 0
Connection[1]: Session[1]: progress_server_version = 0
Connection[1]: Session[1]: progress_client_version = 0
Connection[1]: Session[1]: Progress handler called, downloaded = 0, downloadable(total) = 0, uploaded = 0, uploadable = 0, reliable_download_progress = false, snapshot version = 1
Apr 11 2022 16:04:02 : realm opened.
WebSocket::Websocket()
Resolving 'ws.ap-southeast-2.aws.realm.mongodb.com:443'
Apr 11 2022 16:04:02 : ==============
Apr 11 2022 16:04:02 : ==============
Apr 11 2022 16:04:02 : objects: 0
Apr 11 2022 16:04:02 : links: 0
Apr 11 2022 16:04:02 : ==============
Apr 11 2022 16:04:02 : Done (queryRealm)
Apr 11 2022 16:04:02 : Enter to quit (queryRealm)
Connecting to endpoint '13.54.209.90:443' (1/1)

Connected to endpoint '13.54.209.90:443' (from '10.0.1.20:56013')
WebSocket::initiate_client_handshake()
HTTP request =
GET /api/client/v2.0/app/makespacetest-mfbpk/realm-sync?baas_at=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJiYWFzX2RldmljZV9pZCI6IjYyNTNjNGQxYWVlZWJhZDAxNTM0M2NlNSIsImJhYXNfZG9tYWluX2lkIjoiNjI1MmI2MjVhZWVlYmFkMDE1MjgyNjc4IiwiZXhwIjoxNjQ5NjU4ODQxLCJpYXQiOjE2NDk2NTcwNDEsImlzcyI6IjYyNTNjNGQxYWVlZWJhZDAxNTM0M2NlNiIsInN0aXRjaF9kZXZJZCI6IjYyNTNjNGQxYWVlZWJhZDAxNTM0M2NlNSIsInN0aXRjaF9kb21haW5JZCI6IjYyNTJiNjI1YWVlZWJhZDAxNTI4MjY3OCIsInN1YiI6IjYyNTJiNjk4YWVlZWJhZDAxNTI4MmMyMyIsInR5cCI6ImFjY2VzcyJ9.7gDCh0v4QhnKsIS98-azlhbpcGLbcHDngFHsdIJr2NQ HTTP/1.1
Host: ws.ap-southeast-2.aws.realm.mongodb.com
Connection: Upgrade
Sec-WebSocket-Key: J3d0gFeeeeeedJAjwAMTNg==
Sec-WebSocket-Protocol: com.mongodb.realm-sync/3, com.mongodb.realm-sync/2
Sec-WebSocket-Version: 13
Upgrade: websocket
User-Agent: RealmSync/11.12.0 (macOS Darwin 21.4.0 Darwin Kernel Version 21.4.0: Fri Mar 18 00:46:32 PDT 2022; root:xnu-8020.101.4~15/RELEASE_ARM64_T6000 arm64) RealmJS/10.14.0 (node.js, darwin, vv16.13.0)

WebSocket::handle_http_response_received()
HTTP response = HTTP/1.1 101 Switching Protocols
cache-control: no-cache, no-store, must-revalidate
connection: Upgrade
date: Mon, 11 Apr 2022 06:04:02 GMT
sec-websocket-accept: TsS8Zwj+sDZxv+Y1Z4M24/Ywv4s=
sec-websocket-protocol: com.mongodb.realm-sync/3
server: envoy
upgrade: websocket
vary: Origin
x-frame-options: DENY

Connection[1]: Negotiated protocol version: 3
Connection[1]: Will emit a ping in 32394 milliseconds
Connection[1]: Session[1]: Received: IDENT(client_file_ident=12, client_file_ident_salt=3811047377168359999)
Connection[1]: Session[1]: Sending: IDENT(client_file_ident=12, client_file_ident_salt=3811047377168359999, scan_server_version=0, scan_client_version=0, latest_server_version=0, latest_server_version_salt=0)
Connection[1]: Session[1]: Sending: MARK(request_ident=1)
Connection[1]: Sending: PING(timestamp=29673521, rtt=0)`

@duncangroenewald
Copy link
Author

And then it just hangs indefinitely

@pavel-ship-it
Copy link
Contributor

Hi @duncangroenewald , thank you for the info. It will help to diagnose the problem. We are working on this. At the moment you can remain on v10.19.0

@duncangroenewald
Copy link
Author

Ok, let me know if you want any testing done.

@jlavyan
Copy link

jlavyan commented May 3, 2022

I am not sure if it's related, but I use synced realm too. previous my version was 10.18.0 after update to latest one 10.25.2 app working very slow. it's looks like problem coming from this method pathForPartitionValue that's working slow

@dianaafanador3
Copy link
Contributor

Hi @jlavyan thanks for informing about the issue, I'll try to check why this is happening

@duncangroenewald
Copy link
Author

Just tested with 10.26.0 and same issue exists

@AdamGerthel
Copy link

@duncangroenewald could you see if the problem starts with 10.21.1? If so, it's probably the same issue as in #7734

@duncangroenewald
Copy link
Author

duncangroenewald commented May 23, 2022

@AdamGerthel - I tried to build 10.21.0 using SPM but it fails to build with Xcode 13.4 so I was unable to test. I also tried to clone the repo and build that but get the same build error.
Happy to test with 10.21 and 10.21.1 if you can provide binaries or a branch that will build with Xcode 13.4

@duncangroenewald
Copy link
Author

@AdamGerthel - hang on let me just double check it was 10.21.0 that has the build issue not 10.20.0

@duncangroenewald
Copy link
Author

Yes 10.21.0 won't build

....ates.noindex/Realm.build/Release/RealmSwift.build/Objects-normal/arm64/Sync.o -o /Users/duncangroenewald/Development/realm-cocoa/build/DerivedData/Realm/Build/Intermediates.noindex/Realm.build/Release/RealmSwift.build/Objects-normal/arm64/ThreadSafeReference.o -o /Users/duncangroenewald/Development/realm-cocoa/build/DerivedData/Realm/Build/Intermediates.noindex/Realm.build/Release/RealmSwift.build/Objects-normal/arm64/Util.o

  1.  Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12)
    
  2.  Compiling with the current language version
    
  3.  While evaluating request TypeCheckSourceFileRequest(source_file "/Users/duncangroenewald/Development/realm-cocoa/RealmSwift/Query.swift")
    
  4.  While type-checking extension of Query (at /Users/duncangroenewald/Development/realm-cocoa/RealmSwift/Query.swift:523:1)
    
  5.  While evaluating request RequirementRequest(extension of Query, 1, interface)
    
  6.  While evaluating request ResolveTypeRequest(while resolving type , T.Element, (null))
    
  7.  While building rewrite system for generic signature <τ_0_0 where τ_0_0 : RealmCollection, τ_0_0.Element : PersistableEnum, τ_0_0.Element.RawValue : RealmCollectionValue>
    

Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var LLVM_SYMBOLIZER_PATH to point to it):
0 swift-frontend 0x0000000104b33078 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x0000000104b3208c llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x0000000104b33708 SignalHandler(int) + 344
3 libsystem_platform.dylib 0x00000001a13234a4 _sigtramp + 56
4 libsystem_pthread.dylib 0x00000001a130bee0 pthread_kill + 288
5 libsystem_c.dylib 0x00000001a1246340 abort + 168
6 swift-frontend 0x0000000101661fa8 swift::rewriting::RuleBuilder::~RuleBuilder() + 0
7 swift-frontend 0x0000000101661420 swift::rewriting::RequirementMachine::computeCompletion(swift::rewriting::RewriteSystem::ValidityPolicy) + 176
8 swift-frontend 0x0000000101661298 swift::rewriting::RequirementMachine::initWithGenericSignature(swift::CanGenericSignature) + 892
9 swift-frontend 0x00000001016682ec swift::rewriting::RewriteContext::getRequirementMachine(swift::CanGenericSignature) + 240
10 swift-frontend 0x000000010158eb5c swift::GenericSignatureImpl::lookupNestedType(swift::Type, swift::Identifier) const + 544
11 swift-frontend 0x0000000101265918 (anonymous namespace)::TypeResolver::resolveIdentifierType(swift::IdentTypeRepr*, swift::TypeResolutionOptions) + 1716
12 swift-frontend 0x0000000101261f80 (anonymous namespace)::TypeResolver::resolveType(swift::TypeRepr*, swift::TypeResolutionOptions) + 228
13 swift-frontend 0x0000000101261d04 swift::ResolveTypeRequest::evaluate(swift::Evaluator&, swift::TypeResolution const*, swift::TypeRepr*, swift::GenericParamList*) const + 104
14 swift-frontend 0x0000000101270ea4 llvm::Expectedswift::ResolveTypeRequest::OutputType swift::Evaluator::getResultUncachedswift::ResolveTypeRequest(swift::ResolveTypeRequest const&) + 484
15 swift-frontend 0x0000000101261c14 swift::TypeResolution::resolveType(swift::TypeRepr*, swift::GenericParamList*) const + 96
16 swift-frontend 0x00000001011e1bcc swift::RequirementRequest::evaluate(swift::Evaluator&, swift::WhereClauseOwner, unsigned int, swift::TypeResolutionStage) const + 608
17 swift-frontend 0x00000001016a18f0 llvm::Expectedswift::RequirementRequest::OutputType swift::Evaluator::getResultUncachedswift::RequirementRequest(swift::RequirementRequest const&) + 1044
18 swift-frontend 0x000000010169f374 swift::WhereClauseOwner::visitRequirements(swift::TypeResolutionStage, llvm::function_ref<bool (swift::Requirement, swift::RequirementRepr*)>) const && + 936
19 swift-frontend 0x00000001011c1efc checkGenericParams(swift::GenericContext*) + 292
20 swift-frontend 0x00000001011bd2c8 swift::ASTVisitor<(anonymous namespace)::DeclChecker, void, void, void, void, void, void>::visit(swift::Decl*) + 15096
21 swift-frontend 0x00000001011b69f4 (anonymous namespace)::DeclChecker::visit(swift::Decl*) + 400
22 swift-frontend 0x00000001011b6858 swift::TypeChecker::typeCheckDecl(swift::Decl*, bool) + 204
23 swift-frontend 0x00000001012727b4 swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*) const + 540
24 swift-frontend 0x0000000101275558 llvm::Expectedswift::TypeCheckSourceFileRequest::OutputType swift::Evaluator::getResultUncachedswift::TypeCheckSourceFileRequest(swift::TypeCheckSourceFileRequest const&) + 564
25 swift-frontend 0x0000000101272544 swift::performTypeChecking(swift::SourceFile&) + 120
26 swift-frontend 0x0000000100547890 swift::CompilerInstance::performSema() + 328
27 swift-frontend 0x00000001003d45d4 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4072
28 swift-frontend 0x000000010039c3c4 swift::mainEntry(int, char const**) + 808
29 dyld 0x00000001073c108c start + 520
error: Abort trap: 6 (in target 'RealmSwift' from project 'Realm')

@duncangroenewald
Copy link
Author

v10.20.2 appears to be OK. I will try the prebuilt binaries from here to see if they are compatible with Xcode 13.4

@AdamGerthel
Copy link

AdamGerthel commented May 23, 2022

Happy to test with 10.21 and 10.21.1 if you can provide binaries or a branch that will build with Xcode 13.4

I don't have any binaries and I don't even know how to use realm-swift :D So whether or not it will build is not something I really have any knowledge of.

We're having performance issues over in realm/realm-js#4383 and I'm trying to figure out if this issue is related, because it seems there are at least two issues pointing towards 10.21.1 being the culprit (and possibly because of realm-core 11.8.0 being introduced in that version).

@duncangroenewald
Copy link
Author

Oh, ok, sorry though you were one of the realm folks - the prebuilt binaries are an older version of swift so don't work with Xcode 13.4 and I can't build 10.21.0 because of errors. Perhaps @jsflax can help with getting 10.21.0 and 10.21.1 to build under Xcode 13.4 in order to test this.

@leemaguire
Copy link
Contributor

@duncangroenewald if you use the xcframework script here on v10.21.0 it should build for Xcode 13.4

@duncangroenewald
Copy link
Author

@leemaguire - ah, thanks I will try that

@duncangroenewald
Copy link
Author

@leemaguire - I used the command "sh build.sh xcframework" but get what looks like the same error

/Realm/Build/Intermediates.noindex/Realm.build/Release/RealmSwift.build/Objects-normal/arm64/ThreadSafeReference.o -o /Users/duncangroenewald/Development/realm-cocoa/build/DerivedData/Realm/Build/Intermediates.noindex/Realm.build/Release/RealmSwift.build/Objects-normal/arm64/Util.o

  1.  Apple Swift version 5.6.1 (swiftlang-5.6.0.323.66 clang-1316.0.20.12)
    
  2.  Compiling with the current language version
    
  3.  While evaluating request TypeCheckSourceFileRequest(source_file "/Users/duncangroenewald/Development/realm-cocoa/RealmSwift/Query.swift")
    
  4.  While type-checking extension of Query (at /Users/duncangroenewald/Development/realm-cocoa/RealmSwift/Query.swift:523:1)
    
  5.  While evaluating request RequirementRequest(extension of Query, 1, interface)
    
  6.  While evaluating request ResolveTypeRequest(while resolving type , T.Element, (null))
    
  7.  While building rewrite system for generic signature <τ_0_0 where τ_0_0 : RealmCollection, τ_0_0.Element : PersistableEnum, τ_0_0.Element.RawValue : RealmCollectionValue>
    

Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var LLVM_SYMBOLIZER_PATH to point to it):
0 swift-frontend 0x0000000105713078 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
1 swift-frontend 0x000000010571208c llvm::sys::RunSignalHandlers() + 112
2 swift-frontend 0x0000000105713708 SignalHandler(int) + 344
3 libsystem_platform.dylib 0x00000001a13234a4 _sigtramp + 56
4 libsystem_pthread.dylib 0x00000001a130bee0 pthread_kill + 288
5 libsystem_c.dylib 0x00000001a1246340 abort + 168
6 swift-frontend 0x0000000102241fa8 swift::rewriting::RuleBuilder::~RuleBuilder() + 0
7 swift-frontend 0x0000000102241420 swift::rewriting::RequirementMachine::computeCompletion(swift::rewriting::RewriteSystem::ValidityPolicy) + 176
8 swift-frontend 0x0000000102241298 swift::rewriting::RequirementMachine::initWithGenericSignature(swift::CanGenericSignature) + 892
9 swift-frontend 0x00000001022482ec swift::rewriting::RewriteContext::getRequirementMachine(swift::CanGenericSignature) + 240
10 swift-frontend 0x000000010216eb5c swift::GenericSignatureImpl::lookupNestedType(swift::Type, swift::Identifier) const + 544
11 swift-frontend 0x0000000101e45918 (anonymous namespace)::TypeResolver::resolveIdentifierType(swift::IdentTypeRepr*, swift::TypeResolutionOptions) + 1716
12 swift-frontend 0x0000000101e41f80 (anonymous namespace)::TypeResolver::resolveType(swift::TypeRepr*, swift::TypeResolutionOptions) + 228
13 swift-frontend 0x0000000101e41d04 swift::ResolveTypeRequest::evaluate(swift::Evaluator&, swift::TypeResolution const*, swift::TypeRepr*, swift::GenericParamList*) const + 104
14 swift-frontend 0x0000000101e50ea4 llvm::Expectedswift::ResolveTypeRequest::OutputType swift::Evaluator::getResultUncachedswift::ResolveTypeRequest(swift::ResolveTypeRequest const&) + 484
15 swift-frontend 0x0000000101e41c14 swift::TypeResolution::resolveType(swift::TypeRepr*, swift::GenericParamList*) const + 96
16 swift-frontend 0x0000000101dc1bcc swift::RequirementRequest::evaluate(swift::Evaluator&, swift::WhereClauseOwner, unsigned int, swift::TypeResolutionStage) const + 608
17 swift-frontend 0x00000001022818f0 llvm::Expectedswift::RequirementRequest::OutputType swift::Evaluator::getResultUncachedswift::RequirementRequest(swift::RequirementRequest const&) + 1044
18 swift-frontend 0x000000010227f374 swift::WhereClauseOwner::visitRequirements(swift::TypeResolutionStage, llvm::function_ref<bool (swift::Requirement, swift::RequirementRepr*)>) const && + 936
19 swift-frontend 0x0000000101da1efc checkGenericParams(swift::GenericContext*) + 292
20 swift-frontend 0x0000000101d9d2c8 swift::ASTVisitor<(anonymous namespace)::DeclChecker, void, void, void, void, void, void>::visit(swift::Decl*) + 15096
21 swift-frontend 0x0000000101d969f4 (anonymous namespace)::DeclChecker::visit(swift::Decl*) + 400
22 swift-frontend 0x0000000101d96858 swift::TypeChecker::typeCheckDecl(swift::Decl*, bool) + 204
23 swift-frontend 0x0000000101e527b4 swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*) const + 540
24 swift-frontend 0x0000000101e55558 llvm::Expectedswift::TypeCheckSourceFileRequest::OutputType swift::Evaluator::getResultUncachedswift::TypeCheckSourceFileRequest(swift::TypeCheckSourceFileRequest const&) + 564
25 swift-frontend 0x0000000101e52544 swift::performTypeChecking(swift::SourceFile&) + 120
26 swift-frontend 0x0000000101127890 swift::CompilerInstance::performSema() + 328
27 swift-frontend 0x0000000100fb45d4 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) + 4072
28 swift-frontend 0x0000000100f7c3c4 swift::mainEntry(int, char const**) + 808
29 dyld 0x000000010802d08c start + 520
error: Abort trap: 6 (in target 'RealmSwift' from project 'Realm')

@leemaguire
Copy link
Contributor

This version will require an older version of Xcode to build, I can build it on Xcode 13.0, You'll also need to enable library evolution mode when building the XCFramework.

@duncangroenewald
Copy link
Author

Not sure I understand any of that.

Why is is possible to build 10.19.0 and 10.20.2 but not 10.21.0 on XCode 13.4 ?

How does one enable library evolution mode ?

@leemaguire
Copy link
Contributor

We introduced some new code which at the time worked, then after the next version of the Swift compiler was released a regression was introduced to the compiler. That code is not present in versions of realm older than 10.21.0

To build with evolution mode from Terminal: export REALM_EXTRA_BUILD_ARGUMENTS="$REALM_EXTRA_BUILD_ARGUMENTS REALM_BUILD_LIBRARY_FOR_DISTRIBUTION=YES"

@duncangroenewald
Copy link
Author

duncangroenewald commented May 23, 2022

Thanks, btw what does evolution mode do ?

And just so I don't waste my time can you confirm that I need to do the following:

  1. Install Xcode 13
  2. Build v10.21.0 and v10.21.1 using above evolution mode
  3. Add framework to current application under Xcode 13.4 and it should work. I am not going to get complaints about the wrong version of swift in the framework doing this am I ?

@leemaguire
Copy link
Contributor

It allows a library built with an older version of the swift compiler to be forward compatible with newer versions. https://www.swift.org/blog/library-evolution/

Yes, but use the script I attached above (just copy paste it to the build.sh) for the version you're building. Also don't forget to do xcode-select to build from an older version in the terminal.

@duncangroenewald
Copy link
Author

duncangroenewald commented May 23, 2022

OK thanks.

So is that compiler error actually a bug in the compiler and not an error in the code ? Is there not a workaround to fix that code so it does compile rather than having to install Xcode 13 ?

@leemaguire
Copy link
Contributor

Yes, it was fixed in 10.23.0

@duncangroenewald
Copy link
Author

Why are the prebuilt binaries not being built with evolution mode - then they would work with Xcode 13.4 no ?

@duncangroenewald
Copy link
Author

@leemaguire - ok I installed Xcode 13.2.1 and was able to build Realm-Swift but when I include this framework in the Xcode 13.4 project and try and build I still get the same (or similar) error.

  1. While evaluating request TypeCheckSourceFileRequest(source_file "/Users/duncangroenewald/Development/makespace2/RealmSwift.framework/Modules/RealmSwift.swiftmodule/arm64-apple-macos.swiftinterface")
  2. While type-checking extension of Query (at /Users/duncangroenewald/Development/makespace2/RealmSwift.framework/Modules/RealmSwift.swiftmodule/arm64-apple-macos.swiftinterface:2333:1)
  3. While evaluating request RequirementRequest(extension of RealmSwift.Query, 1, interface)
  4. While evaluating request ResolveTypeRequest(while resolving type , T.Element, (null))
  5. While building rewrite system for generic signature <τ_0_0 where τ_0_0 : RealmCollection, τ_0_0.Element : PersistableEnum, τ_0_0.Element.RawValue : RealmCollectionValue>
    Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var LLVM_SYMBOLIZER_PATH to point to it):
    0 swift-frontend 0x0000000107647078 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 56
    1 swift-frontend 0x000000010764608c llvm::sys::RunSignalHandlers() + 112
    2 swift-frontend 0x0000000107647708 SignalHandler(int) + 344
    3 libsystem_platform.dylib 0x00000001a13234a4 _sigtramp + 56
    4 libsystem_pthread.dylib 0x00000001a130bee0 pthread_kill + 288
    5 libsystem_c.dylib 0x00000001a1246340 abort + 168
    6 swift-frontend 0x0000000104175fa8 swift::rewriting::RuleBuilder::~RuleBuilder() + 0
    7 swift-frontend 0x0000000104175420 swift::rewriting::RequirementMachine::computeCompletion(swift::rewriting::RewriteSystem::ValidityPolicy) + 176
    8 swift-frontend 0x0000000104175298 swift::rewriting::RequirementMachine::initWithGenericSignature(swift::CanGenericSignature) + 892
    9 swift-frontend 0x000000010417c2ec swift::rewriting::RewriteContext::getRequirementMachine(swift::CanGenericSignature) + 240
    10 swift-frontend 0x00000001040a2b5c swift::GenericSignatureImpl::lookupNestedType(swift::Type, swift::Identifier) const + 544
    11 swift-frontend 0x0000000103d79918 (anonymous namespace)::TypeResolver::resolveIdentifierType(swift::IdentTypeRepr*, swift::TypeResolutionOptions) + 1716
    12 swift-frontend 0x0000000103d75f80 (anonymous namespace)::TypeResolver::resolveType(swift::TypeRepr*, swift::TypeResolutionOptions) + 228
    13 swift-frontend 0x0000000103d75d04 swift::ResolveTypeRequest::evaluate(swift::Evaluator&, swift::TypeResolution const*, swift::TypeRepr*, swift::GenericParamList*) const + 104
    14 swift-frontend 0x0000000103d84ea4 llvm::Expectedswift::ResolveTypeRequest::OutputType swift::Evaluator::getResultUncachedswift::ResolveTypeRequest(swift::ResolveTypeRequest const&) + 484
    15 swift-frontend 0x0000000103d75c14 swift::TypeResolution::resolveType(swift::TypeRepr*, swift::GenericParamList*) const + 96
    16 swift-frontend 0x0000000103cf5bcc swift::RequirementRequest::evaluate(swift::Evaluator&, swift::WhereClauseOwner, unsigned int, swift::TypeResolutionStage) const + 608
    17 swift-frontend 0x00000001041b58f0 llvm::Expectedswift::RequirementRequest::OutputType swift::Evaluator::getResultUncachedswift::RequirementRequest(swift::RequirementRequest const&) + 1044
    18 swift-frontend 0x00000001041b3374 swift::WhereClauseOwner::visitRequirements(swift::TypeResolutionStage, llvm::function_ref<bool (swift::Requirement, swift::RequirementRepr*)>) const && + 936
    19 swift-frontend 0x0000000103cd5efc checkGenericParams(swift::GenericContext*) + 292
    20 swift-frontend 0x0000000103cd12c8 swift::ASTVisitor<(anonymous namespace)::DeclChecker, void, void, void, void, void, void>::visit(swift::Decl*) + 15096
    21 swift-frontend 0x0000000103cca9f4 (anonymous namespace)::DeclChecker::visit(swift::Decl*) + 400
    22 swift-frontend 0x0000000103cca858 swift::TypeChecker::typeCheckDecl(swift::Decl*, bool) + 204
    23 swift-frontend 0x0000000103d867b4 swift::TypeCheckSourceFileRequest::evaluate(swift::Evaluator&, swift::SourceFile*) const + 540
    24 swift-frontend 0x0000000103d89558 llvm::Expectedswift::TypeCheckSourceFileRequest::OutputType swift::Evaluator::getResultUncachedswift::TypeCheckSourceFileRequest(swift::TypeCheckSourceFileRequest const&) + 564
    25 swift-frontend 0x0000000103d86544 swift::performTypeChecking(swift::SourceFile&) + 120
    26 swift-frontend 0x000000010305b890 swift::CompilerInstance::performSema() + 328
    27 swift-frontend 0x0000000103061f3c std::__1::error_code llvm::function_ref<std::__1::error_code (swift::SubCompilerInstanceInfo&)>::callback_fn<swift::ModuleInterfaceBuilder::buildSwiftModuleInternal(llvm::StringRef, bool, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_deletellvm::MemoryBuffer >, llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >)::$_1::operator()() const::'lambda'(swift::SubCompilerInstanceInfo&)>(long, swift::SubCompilerInstanceInfo&) + 416
    28 swift-frontend 0x000000010306bbb8 swift::InterfaceSubContextDelegateImpl::runInSubCompilerInstance(llvm::StringRef, llvm::StringRef, llvm::StringRef, swift::SourceLoc, llvm::function_ref<std::__1::error_code (swift::SubCompilerInstanceInfo&)>) + 5852
    29 swift-frontend 0x0000000103061d74 void llvm::function_ref<void ()>::callback_fn<swift::ModuleInterfaceBuilder::buildSwiftModuleInternal(llvm::StringRef, bool, std::__1::unique_ptr<llvm::MemoryBuffer, std::__1::default_deletellvm::MemoryBuffer >
    , llvm::ArrayRef<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >)::$_1>(long) + 132
    30 swift-frontend 0x00000001075a627c RunSafelyOnThread_Dispatch(void*) + 48
    31 swift-frontend 0x00000001075a63cc void* llvm::thread::ThreadProxy<std::__1::tuple<void ()(void), (anonymous namespace)::RunSafelyOnThreadInfo*> >(void*) + 24
    32 libsystem_pthread.dylib 0x00000001a130c26c _pthread_start + 148
    33 libsystem_pthread.dylib 0x00000001a130708c thread_start + 8
    error: Abort trap: 6 (in target 'MakeSpace' from project 'MakeSpace')

@duncangroenewald
Copy link
Author

I will just rebuild the entire project with Xcode 13.2.1 and test the performance with RealmSwift v10.21.0 and 10.21.1...

@duncangroenewald
Copy link
Author

@AdamGerthel @leemaguire @dianaafanador3

OK RealmSwift v10.21.0 appears to be working fine and v10.21.1 does not - same performance issue as with 10.24.x.

Hope this helps.

@tgoyne
Copy link
Member

tgoyne commented May 27, 2022

v10.27.0 partially fixes this, and in the most extreme cases is ~10x faster than v10.26.0. It will still be slower than v10.21.0 as the root cause of the slowdown is a fix for potential data corruption if a device powers off at exact the wrong point in committing a write transaction, and we're trying to keep that fix. If 10.27.0's write performance is still a problem, using async commits may be a good solution.

@duncangroenewald
Copy link
Author

duncangroenewald commented May 27, 2022

@tgoyne - thanks - we are not doing any writes - just reading data and generating reports.

I just tested this with v10.27.0 and the report now takes 580 seconds when using a Synced Realm vs 330 seconds with older RealmSwift v10.21.0 - so still nearly twice as slow as is.

Note that when using a local realm with v10.27.0 performance is identical to the older version(synced or local) at 330 seconds .

Still this is substantially better than the hour or more it was taking with 10.21.1 or greater - but still 10 minutes for report to generate vs 5 minutes !?!

What I don't understand is this is a query only process - no writes are being performed during this operation - so why such a big impact to read performance and why the difference in performance with Synced and Local realms for reads ?

Now I am wondering if there is something else we can do for the reports - we currently run these from a background thread and perhaps we could open the realm as read only or something ?? Any ideas to get back performance ??

@duncangroenewald
Copy link
Author

@tgoyne - quite a few other queries that support updating the UI information are still noticeably slower (from sub second to > 2 seconds) than the pre v10.21.1 SDK.

Given this optimisation is apparently to handle an edge case of power failure during a write transaction - could we have this as an optional configuration setting. Our app runs on desktops and laptops so power failure during a write transaction is an unlikely event. It hasn't happened in 4 years.

If it does happen what is the worst case scenario with the corrupt database ? Will it crash the app or synchronise the corrupted data ?

Thanks

@tgoyne
Copy link
Member

tgoyne commented May 27, 2022

v10.27.0 should have no difference from v10.26.0 for pure read scenarios. Since you're seeing a difference only on sync Realms, that suggests that the sync client's background writes are causing problems. They don't block other threads from reading, but if the work you're doing is i/o-bound then perhaps additional writing on the background thread could slow down disk reads on your thread. A dumb workaround could be to call realm.syncSession.suspend() before kicking off your report and then realm.syncSession.resume() at the end.

The most likely result of a crash at the wrong time is that the next time you try to open the file it hits an assertion failure, and the file is irrecoverable without manually fiddling with it in a hex editor. If you're really unlucky, the file will open successfully and just read corrupted data. Async commits (particularly with allowGrouping: true) are an attempt at exposing a durability mode where a crash might lead to loss of data written in the last few seconds, but is guaranteed to leave the file in a valid state. We do internally have universal reduced durability modes which we use for things like running tests, and exposing that as a configuration setting may be an option.

@duncangroenewald
Copy link
Author

@tgoyne - thanks for the explanation.

The test scenario we are using is a single client connected to a MongoDB Realm App and there are no realm writes being performed at any time during the running of the reports so I don't think it can be background writes causing a problem.

For this pure read scenario there is a substantial improvement in performance with v10.27.0 over v10.26.0 - at a guess at least 10x faster.

I will test using syncSession.suspend() to see if that prevents the problem.

Don't really want to go down the reduced durability path at this stage.

I am happy to have a closer look at what is happening in the database but it would be helpful if you could provide an explanation of what the specific changes were - I can obviously look into the commit code changes but a higher level explanation of how things worked before and how they work now would be helpful to get started.

Also any pointers as to what is different with a synced realm for pure read scenarios that might have been effected by the changes to improve durability. I assume some call somewhere made frequently during reads on synced realms is taking considerably longer than it used to.

Thanks

@duncangroenewald
Copy link
Author

@tgoyne - I tried suspending sync but that doesn't help. What is did find is that the versions since 10.21.1 are completely destroying thread performance which is the main cause of the problem.

Our reports break up the work into segments and then run each segments queries on different threads - typically N-2 threads where N = number of CPU cores.

When running with versions prior to 10.21.1 all threads run at nearly 100% regardless of whether synced or local realm is being used. Since 10.21.1 and including 10.27.0 something is killing the thread performance and performance of threads declines to zero as per the attached graphs. So it seems something is progressively blocking threads.

Screen Shot 2022-06-01 at 12 02 08 pm

Screen Shot 2022-06-01 at 12 01 46 pm

@tgoyne
Copy link
Member

tgoyne commented Jun 14, 2022

I've successfully reproduced a significant performance regression in multithreaded read-only usage and I'm now looking into the cause.

@duncangroenewald
Copy link
Author

@tgoyne - thanks, let me know if there is anything I can do to help.

@tgoyne
Copy link
Member

tgoyne commented Jun 15, 2022

It turns out I accidentally actually just compared the performance of @Persisted to old-style property declarations in one of the scenarios where @Persisted is slower, and after controlling for that I'm not seeing a difference.

The thing I'm testing is variations on the following, which is attempting to simulate a read-heavy workflow on many threads at once (using 14 threads as I'm testing on a m1 ultra with 16 performance cores):

var config: Realm.Configuration!
try autoreleasepool {
    let user = try logInUser(for: basicCredentials())
    let realm = try openRealm(partitionValue: #function, user: user)
    config = realm.configuration
    for _ in 0..<5 {
        try realm.write {
            for _ in 0..<100000 {
                realm.add(SwiftPerson(firstName: "a", lastName: "b"))
            }
        }
    }
    waitForUploads(for: realm)
}

measure {
    let queue = DispatchQueue.global()
    let group = DispatchGroup()
    for _ in 0..<14 {
        group.enter()
        queue.async {
            for _ in 0..<5 {
                autoreleasepool {
                    var str = ""
                    let realm = try! Realm(configuration: config)
                    for obj in realm.objects(SwiftPerson.self) {
                        str += obj.firstName
                    }
                }
                autoreleasepool {
                    var str = ""
                    let realm = try! Realm(configuration: config)
                    for obj in realm.objects(SwiftPerson.self) {
                        str += obj.lastName
                    }
                }
            }
            group.leave()
        }
    }
    group.wait()
}

Running this on sync and local Realms on both v10.20.0 and v10.28.1 give very similar results, and all of them sit around 1400% CPU during the testing phase. This of course is a very simple test case, so it's unsurprising that it's failing to hit problems.

Are you using frozen objects anywhere? With no frozen objects, no encryption, no writes being performed, and the sync session suspended, very little involves acquring locks or any sort of cross-thread coordination. Initializing new Realm instances does, so are you possible initializing and then throwing away a very large number of Realm instances?

Since you're seeing blocked threads, enabling "Record Waiting Threads" in File -> Recording Options in Instruments may be informative. This makes it so that the threads which should be running on the idle cores report the spot where they're blocked as time spent, which should reveal something useful.

@duncangroenewald
Copy link
Author

@tgoyne - OK, thanks let me see see if I can find out where the threads are being blocked.

@duncangroenewald
Copy link
Author

@tgoyne - not sure I really understand Instruments but it seems to be blocking on the call to SyncManager.get_current_user().

HOWEVER - we have a deep hierarchy and the report traverses the entire hierarchy and what was happening was that right near the deepest part of the hierarchy we were trying to open a new Realm to access an object using it's ID instead of just reusing the parent objects realm. This would be called many times - obviously inefficient.

Fixing this and our performance problem in the report goes away now (testing with 10.27.0) - however it is still a bit unclear why this call would block suddenly in the newer version.

I suspect we have the same issue in some of the background threads performing calculations for the UI as they still appear slow so will investigate if there are more unnecessary calls to Realm() that are blocking.

Am I mistaken in the understanding that there should be no additional overhead to call Realm() more than once from the same thread. I seem to recall this coming up in discussion a long time ago and Realm would simply return the same realm if one is already open on the same thread ?

1.45 min 38.7% 0 s -[RLMApp currentUser]
1.45 min 38.7% 0 s realm::SyncManager::get_current_user() const
1.43 min 38.3% 0 s std::__1::mutex::lock()
1.43 min 38.3% 0 s _pthread_mutex_firstfit_lock_slow
1.43 min 38.3% 0 s _pthread_mutex_firstfit_lock_wait
1.43 min 38.3% 1.43 min __psynch_mutexwait
904.03 ms 0.4% 0 s realm::SyncMetadataManager::get_current_user_identity() const
5.00 ms 0.0% 0 s std::__1::mutex::unlock()

@duncangroenewald
Copy link
Author

@tgoyne - it seems the same issue on the other background threads where we are opening another realm inside the query from the same thread which seems to cause blocking. These UI updates take around 3 seconds normally and are taking 10 seconds or more. We just have a static function that gets called from anywhere to fetch a reference record from Realm and we don't pass in a realm we just open one in the static function. In the earlier versions of the SDK this appears to have no performance impact whereas now it is quite a severe impact.

Workaround is to just pass in a realm from the extension method call rather than opening a new realm. Still you might want to check this out since it should just pass back the realm that is already open on the same thread - I think.

544.35 ms 0.1% 0 s GlobalVars.activeLaunchPeriod.getter
533.76 ms 0.1% 0 s $s10MakeSpace210GlobalVarsC5realm10RealmSwift0F0VSgvg
533.76 ms 0.1% 0 s DataManager.realmI.getter
343.59 ms 0.0% 0 s DataManager.realmSyncConfig.getter
266.41 ms 0.0% 0 s -[RLMApp currentUser]
266.41 ms 0.0% 0 s realm::SyncManager::get_current_user() const
246.41 ms 0.0% 0 s std::__1::mutex::lock()
246.41 ms 0.0% 0 s _pthread_mutex_firstfit_lock_slow
246.41 ms 0.0% 0 s _pthread_mutex_firstfit_lock_wait
246.41 ms 0.0% 246.41 ms __psynch_mutexwait

@duncangroenewald
Copy link
Author

Not sure if this will be of any use but the basic code to test would be this

measure {
    // Some report parameter to fetch the SwiftPeriod object - passed in from main thread
    let periodId ="someid"

    let queue = DispatchQueue.global()
    let group = DispatchGroup()
    for _ in 0..<14 {
        group.enter()
        queue.async {
            for _ in 0..<5 {
                autoreleasepool {
                    var str = ""
                    let realm1 = try! Realm(configuration: config)
                    for obj in realm1.objects(SwiftPerson.self) {
                        str += obj.firstName

                        // If some condition then call a function to do stuff
                        if obj.firstName == "Something" {


                            // func someFunction(id: periodId) {}
                            // This call should return the same realm as realm1 ??
                            let realm2 = try! Realm(configuration: config)          // <<<<<<< Seems to block on SyncManager.get_current_user()

                            let period = realm2.object(ofType: SwiftPeriod.self, forPrimaryKey: periodId)

                            // calc stuff for the period...

                            // end of function

                        }


                    }
                }
                
            }
            group.leave()
        }
    }
    group.wait()
}

@tgoyne
Copy link
Member

tgoyne commented Jun 17, 2022

Thanks, I think I see what the actual problem is now. The Swift sync config type only stores the partition key but not the file path derived from the partition, and we compute the file path each time a Realm instance is obtained. This isn't a particularly expensive operation, but it ends up being the bulk of the runtime of Realm(configuration: config) because after computing the path we just do a cache lookup using the path and return the existing Realm. In addition, we have to hold a lock while doing this, so multithreaded code which calls Realm() a lot with sync configs ends up serialized. This hopefully won't be too difficult to fix.

The weird thing though is that this isn't anything new and I see the same behavior in v10.20.0, so I'm not sure why it used to be faster.

@duncangroenewald
Copy link
Author

Thanks for the explanation - it is probably worth understanding why it has become slower. I am happy to do more testing with the two versions of the SDK if you have any suggestions on specific things to test/measure and the best way to do that.

@tgoyne
Copy link
Member

tgoyne commented Jun 22, 2022

#7857 fixes the problem of Realm cache lookups being really slow for synchronized Realms.

@duncangroenewald
Copy link
Author

OK I am going to close this now

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 18, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

7 participants