Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Xtext beyond the defaults - how to tackle performance problems

1.394 visualizaciones

Publicado el

Nearly every Eclipse user is aware what Xtext is and what it is useful for. It is always a pleasure to see in which kind of areas it is used.
One reason is clearly, that it is really easy to build a first working example in no time. The grammar alone is sufficient and the rest is done by a code generator. Xtext will generate stub classes, that are ready to fill in individual logic for different areas.
By doing that most of the things just work, because Xtext comes with a lot of defaults that suits in most of the cases.
But as projects get bigger and the amount of models grow, the defaults might not scale and you might need to tweak your language to make working smooth again.
Here it becomes more complicated and you need to understand what’s going on under the covers.

In this session I will go through typical problems and solutions, that we have seen in customer projects. Sometimes it’s a tradeoff to tackle those problems, but it’s important to understand the implications.
For some typical examples I will go into details and explain what’s going on under the covers.
After the session attendees should have an idea how to tweak their own languages and why it might be worth the effort to migrate to a newer version of Xtext.

Publicado en: Ingeniería
  • Sé el primero en comentar

Xtext beyond the defaults - how to tackle performance problems

  1. 1. Xtext beyond the defaults How to tackle performance problems
  2. 2. Who is that guy?
  3. 3. Xtext defaults are a good start! But one size does not fit all!
  4. 4. Xtext defaults are a good start! But one size does not fit all! Amount of DSLs increases
  5. 5. Xtext defaults are a good start! But one size does not fit all! Amount of DSLs increases Files get bigger
  6. 6. Xtext defaults are a good start! But one size does not fit all! Amount of DSLs increases Files get bigger Amount of files increases
  7. 7. Xtext defaults are a good start! But one size does not fit all! Amount of DSLs increases Files get bigger Amount of files increases Many cross references
  8. 8. Xtext defaults are a good start! But one size does not fit all! Amount of DSLs increases Files get bigger Amount of files increases Many cross references Maybe transitive cross references…
  9. 9. Look what we have build!
  10. 10. Look what we have build! More than 20 DSLs…
  11. 11. Look what we have build! More than 20 DSLs… and 200.000 lines in one file…
  12. 12. Look what we have build! More than 20 DSLs… and 200.000 lines in one file… and we can check in broken models…
  13. 13. Look what we have build! More than 20 DSLs… and 200.000 lines in one file… and we can check in broken models… and we generate the missing stuff…
  14. 14. Look what we have build! More than 20 DSLs… and 200.000 lines in one file… and we can check in broken models… and we generate the missing stuff… to make them valid again!
  15. 15. Look what we have build! More than 20 DSLs… and 200.000 lines in one file… We are on Xtext 2.6.2 and can’t update! and we can check in broken models… and we generate the missing stuff… to make them valid again!
  16. 16. Look what we have build! More than 20 DSLs… and 200.000 lines in one file… We are on Xtext 2.6.2 and can’t update! and we can check in broken models… and we generate the missing stuff… to make them valid again! Could you please back-port the changes?
  17. 17. Everything is sooo slow!!! Xtext sucks!!!
  18. 18. Finally think about improving the situation!
  19. 19. Update to newest Xtext Version 2.10.x
  20. 20. Update to newest Xtext Version 2.10.x Xtext 2.11 released early 2017
  21. 21. Why should I update???
  22. 22. Because…we killed bugs…
  23. 23. Because…we killed bugs… Let workarounds not last forever!
  24. 24. …Speed…
  25. 25. …Speed… Resolving cross- references has never been faster…
  26. 26. …new features…
  27. 27. …new features… Make Xtext work with other platform s
  28. 28. …let’s work together.
  29. 29. …let’s work together. It was never easier to contribute! We are on G ithub :-D
  30. 30. What about Performance…
  31. 31. Most problems happen in… …Index and scoping… …Memory consumption. Validations… … Complex generators…
  32. 32. I need Xbase in every language…
  33. 33. I need Xbase in every language… … because my language is complicated…
  34. 34. I need Xbase in every language… … because my language is complicated… … no I can’t explain why…
  35. 35. I need Xbase in every language… … because my language is complicated… … no I can’t explain why… … but there is this small corner case…
  36. 36. Is a FAST validation really fast…
  37. 37. Is a FAST validation really fast… … it’s triggered every time I stop typing
  38. 38. Scoping is sooo complicated…
  39. 39. Scoping is sooo complicated… … I heard that in nearly every project…
  40. 40. Scoping is sooo complicated… … I heard that in nearly every project… …and people stop improving things when it work’s for the first time…
  41. 41. Scoping is sooo complicated… … I heard that in nearly every project… …and people stop improving things when it work’s for the first time… … code is not touched any more because who knows…
  42. 42. Scoping is sooo complicated… … I heard that in nearly every project… …and people stop improving things when it work’s for the first time… … code is not touched any more because who knows… … it worked before you touched it!
  43. 43. What’s the problem? LocalScope GlobalScope ImportScopeTypeScope Caches everywhere The Index Lazylinking EcoreUtils.resolveAll should do the trick! DerivedState ContainerState BatchLinkableResource
  44. 44. Scoping API scope_Element_feature(Element element ,EReference ref)
  45. 45. Scoping API scope_Element_feature(Element element ,EReference ref)
  46. 46. Scoping API scope_Element_feature(Element element ,EReference ref)
  47. 47. Scoping API scope_Element_feature(Element element ,EReference ref)
  48. 48. Scoping API scope_Element_feature(Element element ,EReference ref) Called by the PolymorphicDispatcher…
  49. 49. Scoping API scope_Element_feature(Element element ,EReference ref) Called by the PolymorphicDispatcher… …in a reflective way…
  50. 50. Scoping API scope_Element_feature(Element element ,EReference ref) Called by the PolymorphicDispatcher… and if grammar changed it might not get called any more… …in a reflective way…
  51. 51. Scoping API scope_Element_feature(Element element ,EReference ref) Called by the PolymorphicDispatcher… and if grammar changed it might not get called any more… …in a reflective way… …BECAUSE IT’S SLOW!
  52. 52. Scoping API scope_Element_feature(Element element ,EReference ref) Called by the PolymorphicDispatcher… and if grammar changed it might not get called any more… …in a reflective way… …BECAUSE IT’S SLOW! Implement getScope(EObject context, EReference ref) if(context instanceof Element && ref == MyPackage.Literals.ELEMENT_FEATURE) up to 10 %
  53. 53. Scoping API scope_Element_feature(Element element ,EReference ref) Called by the PolymorphicDispatcher… and if grammar changed it might not get called any more… …in a reflective way… …BECAUSE IT’S SLOW! Implement getScope(EObject context, EReference ref) if(context instanceof Element && ref == MyPackage.Literals.ELEMENT_FEATURE) up to 10 %Will not work with Xbase anyway…
  54. 54. Use caches in the ScopeProvider
  55. 55. Use caches in the ScopeProvider For each cross reference the ScopeProvider gets asked…
  56. 56. Use caches in the ScopeProvider …and it calculates the very same stuff over and over again… For each cross reference the ScopeProvider gets asked…
  57. 57. Use caches in the ScopeProvider …and it calculates the very same stuff over and over again… For each cross reference the ScopeProvider gets asked… …cache the calculated stuff and invalidate it when necessary!
  58. 58. Use caches in the ScopeProvider …and it calculates the very same stuff over and over again… For each cross reference the ScopeProvider gets asked… …cache the calculated stuff and invalidate it when necessary! The cache of the GlobalScope should be the index and nothing else!
  59. 59. Use the force of the Index
  60. 60. Use the force of the Index Holds all lightweight representations of referenceable elements and their resources
  61. 61. Use the force of the Index Holds all lightweight representations of referenceable elements and their resources It’s a HashMap… It’s super fast since Xtext 2.x and improved further
  62. 62. Holds all lightweight representations of referenceable elements and their resources Use the force of the Index It’s a HashMap… It’s super fast since Xtext 2.x and improved further It’s YOUR Index - you can put data in…!
  63. 63. Index - how to feed it
  64. 64. Index - how to feed it 1. Builder picks up DSL files and loads them one by one
  65. 65. Index - how to feed it 1. Builder picks up DSL files and loads them one by one 2. Creates ResourceDescriptions through ResourceDescriptionManager
  66. 66. Index - how to feed it 1. Builder picks up DSL files and loads them one by one 2. Creates ResourceDescriptions through ResourceDescriptionManager 3. ResourceDescriptionManager calls ResourceDescriptionsStrategy to create EObjectDescriptions
  67. 67. Index - how to feed it 1. Builder picks up DSL files and loads them one by one 2. Creates ResourceDescriptions through ResourceDescriptionManager 3. ResourceDescriptionManager calls ResourceDescriptionsStrategy to create EObjectDescriptions You have to bind a custom impl for the ResourceDescriptionsStrategy in the RuntimeModule
  68. 68. Index - how to feed it 1. Builder picks up DSL files and loads them one by one 2. Creates ResourceDescriptions through ResourceDescriptionManager 3. ResourceDescriptionManager calls ResourceDescriptionsStrategy to create EObjectDescriptions You have to bind a custom impl for the ResourceDescriptionsStrategy in the RuntimeModule The default creates a EObjectDescription for EVERY Element that has a name…
  69. 69. IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData) Information hiding and userData
  70. 70. IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData) Information hiding and userData
  71. 71. IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData) Information hiding and userData
  72. 72. IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData) Information hiding and userData Save memory & time
  73. 73. UserData - what for?
  74. 74. UserData - what for? Validation Don’t load the world to get informations - put them in the index
  75. 75. UserData - what for? Validation Don’t load the world to get informations - put them in the index Scoping Don’t resolve proxies for simple informations
  76. 76. Reference non Xtext models
  77. 77. Reference non Xtext models We have our own GlobalScopeProvider that does the trick…
  78. 78. Reference non Xtext models We have our own GlobalScopeProvider that does the trick… …we load everything and the GlobalScope contains the corresponding EObjectDescriptions…
  79. 79. Reference non Xtext models We have our own GlobalScopeProvider that does the trick… …we load everything and the GlobalScope contains the corresponding EObjectDescriptions… …but it’s slow and we cannot navigate those elements in the editor… You can do better…
  80. 80. Reuse the Xtext infrastructure
  81. 81. Reuse the Xtext infrastructure Bind a ResourceServiceProvider… …so that you can put the elements in the index and make them navigable!
  82. 82. Reuse the Xtext infrastructure Bind a ResourceServiceProvider… …so that you can put the elements in the index and make them navigable! GenericResourceServiceProvider Use It will put everything that has a name in the index… … introduce your own ResourceDescriptionStrategy!
  83. 83. But the builder picks them up… and it takes ages!
  84. 84. Put the index in the jar
  85. 85. Put the index in the jar Why calculating the index of a static set of files?
  86. 86. Put the index in the jar The index is serialisable… …put it in the jar and load it. Why calculating the index of a static set of files?
  87. 87. Index in Standalone It’s sooo slow…
  88. 88. Index in Standalone It’s sooo slow… …of course I have my custom Standalone impl…
  89. 89. Index in Standalone ResourceSetGlobalScopeProvider Long time the was the default.
  90. 90. Index in Standalone ResourceSetGlobalScopeProvider Long time the was the default. Today we can do better but you need to use it and know that there is something new… For Maven- and Gradleplugin it’s done.
  91. 91. Index in Standalone Fill the index and install it on the ResourceSet! Load each resource and ask the ResourceDescriptionManager to create a ResourceDescription…
  92. 92. Index in Standalone Fill the index and install it on the ResourceSet! Load each resource and ask the ResourceDescriptionManager to create a ResourceDescription… Install it on the ResourceSet
  93. 93. Make big things run again and save your ass! Up to 80% more faster in 10 minutes!
  94. 94. Codegenerators They are sooo slow…
  95. 95. Codegenerators They are sooo slow… … of course I am using mwe2 to invoke it…
  96. 96. Codegenerators They are sooo slow… … of course I am using mwe2 to invoke it… … even in the IDE!
  97. 97. Incremental generators
  98. 98. Incremental generators The builder triggers the generator for each resource…
  99. 99. Incremental generators The builder triggers the generator for each resource… …when a file changes the builder computes the impact and retriggers the generator for each affected file!
  100. 100. Incremental generators The builder triggers the generator for each resource… …when a file changes the builder computes the impact and retriggers the generator for each affected file! What about m:n scenarios? Solveable with a little effort - but it is worth the work!
  101. 101. Incremental generators The builder triggers the generator for each resource… …when a file changes the builder computes the impact and retriggers the generator for each affected file! What about m:n scenarios? Solveable with a little effort - but it is worth the work! There is a ParallelBuilderParticipant… …you have to bind it for your language… … make sure all proxies are already resolved!
  102. 102. Memory consumption
  103. 103. Memory consumption DisabledClusteringPolicy Do not unload resource…
  104. 104. Memory consumption DisabledClusteringPolicy DynamicResourceClusteringPolicy Do not unload resource… Unload resources when there is no free memory… …can be configured.
  105. 105. The NodeModel is huge Stores the syntax tree with text and positions…
  106. 106. The NodeModel is huge Stores the syntax tree with text and positions… …is used to get the position of a specific element or feature…
  107. 107. The NodeModel is huge Stores the syntax tree with text and positions… …is used to get the position of a specific element or feature… …produces a lot of Strings in memory…
  108. 108. The NodeModel is huge Stores the syntax tree with text and positions… …is used to get the position of a specific element or feature… …produces a lot of Strings in memory… …and during the builder runs you do not really need it.
  109. 109. Switch off the NodeModel
  110. 110. Switch off the NodeModel The parser creates it …
  111. 111. Switch off the NodeModel The parser creates it … …it is used to install proxies - so you have to do that differently…
  112. 112. Switch off the NodeModel The parser creates it … …it is used to install proxies - so you have to do that differently… You want to have it when the editor is used…
  113. 113. Switch off the NodeModel The parser creates it … …it is used to install proxies - so you have to do that differently… You want to have it when the editor is used… … the load options should be an indicator…
  114. 114. Switch off the NodeModel The parser creates it … …it is used to install proxies - so you have to do that differently… You want to have it when the editor is used… … the load options should be an indicator… …what are the implications?
  115. 115. Implications You cannot use the NodeModel in validations and scoping any more…
  116. 116. Implications You cannot use the NodeModel in validations and scoping any more… …Issues are marked at position 0,0… …an EditorCallback should revalidate the content.
  117. 117. Implications You cannot use the NodeModel in validations and scoping any more… …Issues are marked at position 0,0… …an EditorCallback should revalidate the content. THIS IS NOT A COMMON THING! DO IT ONLY WHEN IT IS REALLY NECESSARY!
  118. 118. Order makes a difference
  119. 119. Order makes a difference Files might belong together…
  120. 120. Order makes a difference Files might belong together… …and might reference each other.
  121. 121. Order makes a difference Files might belong together… …and might reference each other. Putting them in an logical order for the builder…
  122. 122. Order makes a difference Files might belong together… …and might reference each other. Putting them in an logical order for the builder… … and they do not have be loaded more than once.
  123. 123. Order makes a difference Files might belong together… …and might reference each other. Putting them in an logical order for the builder… … and they do not have be loaded more than once. Sometimes it makes sense to not unload them at all.
  124. 124. Now you know!
  125. 125. Professional Support

×