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

Accelarate Realm transformer #3034

Closed
beeender opened this issue Jun 21, 2016 · 20 comments · Fixed by #5925
Closed

Accelarate Realm transformer #3034

beeender opened this issue Jun 21, 2016 · 20 comments · Fixed by #5925
Assignees

Comments

@beeender
Copy link
Contributor

beeender commented Jun 21, 2016

We got some complains (http://stackoverflow.com/questions/37928953/realm-gradle-tasks) about the speed of transformers and there is always space to improve it, like:

  • Replace slow groovy with kotlin
  • ...
@cmelchior
Copy link
Contributor

Is Groovy really slower than Kotlin? It is all byte code under the hood, which in turn is dex. I think we should switch for other reasons though, and there are probably room for improvement in any case.

@emanuelez
Copy link
Contributor

I don't think switching to Groovy would improve performance a lot, simply because most of the time is spent in Javassist. A more promising change would probably be to switch to ASM from Javassist.

@cmelchior
Copy link
Contributor

There is also some things we need to investigate from this: https://twitter.com/ebtokyo/status/808816830118653952

  • When/how is the transformer triggered. Is it possible to be more clever about which files are processed.
  • How does incremental builds effect this.
  • How/when is the annotation processor triggered. Especially, why is it triggered if there is no code changes. I would assume the gradle build system could easily detect this case.

@emanuelez
Copy link
Contributor

The Transform API has support for incremental builds which we're not using right now so there's space for improvements.
We don't have much control over when the AP is triggered. In general, I think it needs to run on every build because the generated classes might use or be indirectly used by the classes being changed.

@eboudrant
Copy link

eboudrant commented Dec 15, 2016

@cmelchior thanks for the followup, I just wanted to update you, the slowness I reported on Twitter about Gradle was not because of Realm, it was another problem (our BuildConfig modified for each build). If we could have incremental builds support for Realm code-gen via Transform API that would be great.

@beeender
Copy link
Contributor Author

@bmeike
Copy link
Contributor

bmeike commented Jul 27, 2017

@nateridderman
Copy link

Incremental builds would be huge. When I change a line of Java code in a class unrelated to Realm, then Realm shouldn't have to transform everything again. Based on profiling my Gradle build, this would save me at least 20 seconds out of a 60 second build for the transformClassesWithRealmTransformer task, and it seems like Realm is also contributing towards the compileJavaWithJavac task.

@meierjan
Copy link

meierjan commented Aug 30, 2017

Any reasons why this task can take up to 38 secs?

:app:transformClassesWithRealmTransformerForXDebug | 37.690s

using "io.realm:realm-gradle-plugin:3.3.2"

@thorbenprimke
Copy link

@beeender @cmelchior Any update on this? It's one of the longest gradle tasks when building our app (@pinterest). Even just improving it for incremental builds would be huge.

@whataa
Copy link

whataa commented Feb 13, 2018

Several modules of our project used realm, the compile time has been steadily increasing linearly with the number of modules. But your team did not make any new progress on the issue in more than a year, any specific schedule on this?

@AamirAbro
Copy link

have been hit by realm slow compilations issues too. transformClassesWithRealm some times take more than 30 secs.
:app:transformClassesWithRealmTransformerForDebug | 38.287s

@muthuraj57
Copy link

muthuraj57 commented Apr 26, 2018

After changing a line in layout xml or anything not even remotely connected to realm still triggers this task which takes more than half of my total build time.

:app:transformClassesWithRealmTransformerForDebug | 1m 18s

@cmelchior
Copy link
Contributor

We have added support for incremental builds in the Realm transformer and would really appreciate if you can try this out in real projects since it changes the logic about which files are being touched and also in order to get input about the improvement on real-world projects.

We have released a special SNAPSHOT build that can be used to test this:

buildscript {
    repositories {
        jcenter()
        google()
        maven {
            url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
        }
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:5.2.0-transformer-SNAPSHOT"
    }
}

allprojects {
    repositories {
        jcenter()
        google()
        maven {
            url 'http://oss.jfrog.org/artifactory/oss-snapshot-local'
        }
    }
}

The debug log will output the amount of time used inside the transformer

// Old logger
./gradlew assemble --debug | grep "Realm Transform time:"

// New logger
./gradlew assemble --debug | grep "realm-stopwatch"

Note, there are edge cases when ignored fields are being changed (marked as either @Ignore, static or transient ). Hitting these cases will cause the incremental build to not do the right thing. These cases are described in the issue: #5925.

@thorbenprimke
Copy link

@cmelchior - thanks for the update. I'll get that patched in on Monday and will report back.

@thorbenprimke
Copy link

thorbenprimke commented May 29, 2018

@cmelchior - looks like it nicely improved things. 💯 🎆 👋 👏

Before:
[initial build] 09:36:26.565 [DEBUG] [realm-logger] Realm Transform time: 16696 milliseconds
[java change] 09:39:19.969 [DEBUG] [realm-logger] Realm Transform time: 21049 milliseconds
[java revert] 09:42:22.689 [DEBUG] [realm-logger] Realm Transform time: 22807 milliseconds

After:
[initial build]
09:57:49.286 [DEBUG] [realm-stopwatch] Prepare output classes: 15 ms.
09:57:49.380 [DEBUG] [realm-stopwatch] Prepare referenced classes: 94 ms.
09:57:49.438 [DEBUG] [realm-stopwatch] Mark mediators as transformed: 57 ms.
09:57:49.460 [DEBUG] [realm-stopwatch] Transform model classes: 21 ms.
09:57:50.384 [DEBUG] [realm-stopwatch] Transform references to model fields: 923 ms.
09:57:50.397 [DEBUG] [realm-stopwatch] Copy resource files: 13 ms.
09:57:50.397 [DEBUG] [realm-stopwatch] Realm Transform time: 1126 ms.
10:00:23.837 [DEBUG] [realm-stopwatch] Prepare output classes: 499 ms.
10:00:24.473 [DEBUG] [realm-stopwatch] Prepare referenced classes: 636 ms.
10:00:24.477 [DEBUG] [realm-stopwatch] Mark mediators as transformed: 3 ms.
10:00:24.477 [DEBUG] [realm-stopwatch] Transform model classes: 0 ms.
10:00:40.175 [DEBUG] [realm-stopwatch] Transform references to model fields: 15697 ms.
10:00:40.666 [DEBUG] [realm-stopwatch] Copy resource files: 491 ms.
10:00:40.666 [DEBUG] [realm-stopwatch] Realm Transform time: 17328 ms.

[java change]
11:23:58.204 [DEBUG] [realm-stopwatch] Prepare output classes: 5 ms.
11:23:58.390 [DEBUG] [realm-stopwatch] Prepare referenced classes: 185 ms.
11:23:58.390 [DEBUG] [realm-stopwatch] Mark mediators as transformed: 0 ms.
11:23:58.390 [DEBUG] [realm-stopwatch] Transform model classes: 0 ms.
11:23:58.477 [DEBUG] [realm-stopwatch] Transform references to model fields: 86 ms.
11:23:59.046 [DEBUG] [realm-stopwatch] Copy resource files: 569 ms.
11:23:59.046 [DEBUG] [realm-stopwatch] Realm Transform time: 846 ms.

[java revert]
11:25:50.004 [DEBUG] [realm-stopwatch] Prepare output classes: 0 ms.
11:25:50.181 [DEBUG] [realm-stopwatch] Prepare referenced classes: 177 ms.
11:25:50.182 [DEBUG] [realm-stopwatch] Mark mediators as transformed: 0 ms.
11:25:50.182 [DEBUG] [realm-stopwatch] Transform model classes: 0 ms.
11:25:50.214 [DEBUG] [realm-stopwatch] Transform references to model fields: 31 ms.
11:25:50.706 [DEBUG] [realm-stopwatch] Copy resource files: 492 ms.
11:25:50.706 [DEBUG] [realm-stopwatch] Realm Transform time: 702 ms.

Test steps:
Do a gradle clean, trigger a build (initial build), then make a java change in the main module (second build) and then revert that change (third build).

Our realm model classes are in a separate gradle module. I think that's why in the java change and java revert steps, only show the output once because the other module didn't change.

@muthuraj57
Copy link

muthuraj57 commented May 31, 2018

@cmelchior This snapshot improved my build time considerably. Previously it took more than 3 minutes to incremental builds. Now it is more or less one minute. Thanks a lot.

@cmelchior
Copy link
Contributor

@muthuraj57 Thank you for reporting back. Would it be possible to post the log numbers for your build as well? A minute still sounds like a lot for incremental builds, so would be interesting to see where the time is actually being spent

@thorbenprimke
Copy link

@cmelchior - do you know when you will release the next version (5.1.1 or 5.2) that will include the new transformer improvements?

@cmelchior
Copy link
Contributor

5.2.0 should be available in the next 24 hours.

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

Successfully merging a pull request may close this issue.