Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Xtext beyond the defaults
How to tackle performance problems
Who is that guy?
Xtext defaults are a good start!
But one size does not fit all!
Xtext defaults are a good start!
But one size does not fit all!
Amount of DSLs increases
Xtext defaults are a good start!
But one size does not fit all!
Amount of DSLs increases
Files get bigger
Xtext defaults are a good start!
But one size does not fit all!
Amount of DSLs increases
Files get bigger
Amount of files ...
Xtext defaults are a good start!
But one size does not fit all!
Amount of DSLs increases
Files get bigger
Amount of files ...
Xtext defaults are a good start!
But one size does not fit all!
Amount of DSLs increases
Files get bigger
Amount of files ...
Look what we have build!
Look what we have build!
More than 20 DSLs…
Look what we have build!
More than 20 DSLs…
and 200.000 lines in one file…
Look what we have build!
More than 20 DSLs…
and 200.000 lines in one file…
and we can check in broken models…
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 gener...
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 gener...
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 ...
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 ...
Everything is sooo slow!!!
Xtext sucks!!!
Finally think about improving the situation!
Update to newest Xtext Version
2.10.x
Update to newest Xtext Version
2.10.x
Xtext 2.11
released
early
2017
Why should I update???
Because…we killed bugs…
Because…we killed bugs…
Let workarounds
not last forever!
…Speed…
…Speed…
Resolving
cross-
references
has
never
been
faster…
…new features…
…new features…
Make
Xtext work
with
other
platform
s
…let’s work together.
…let’s work together.
It was
never
easier
to
contribute!
We
are
on
G
ithub
:-D
What about Performance…
Most problems happen in…
…Index and scoping…
…Memory consumption.
Validations…
… Complex generators…
I need Xbase in every language…
I need Xbase in every language…
… because my language is
complicated…
I need Xbase in every language…
… because my language is
complicated…
… no I can’t explain why…
I need Xbase in every language…
… because my language is
complicated…
… no I can’t explain why…
… but there is this small ...
Is a FAST validation really fast…
Is a FAST validation really fast…
… it’s triggered every time I stop typing
Scoping is sooo complicated…
Scoping is sooo complicated…
… I heard that in nearly every project…
Scoping is sooo complicated…
… I heard that in nearly every project…
…and people stop improving things when
it work’s for ...
Scoping is sooo complicated…
… I heard that in nearly every project…
…and people stop improving things when
it work’s for ...
Scoping is sooo complicated…
… I heard that in nearly every project…
…and people stop improving things when
it work’s for ...
What’s the problem?
LocalScope
GlobalScope
ImportScopeTypeScope
Caches everywhere
The Index
Lazylinking
EcoreUtils.resolve...
Scoping API
scope_Element_feature(Element element ,EReference ref)
Scoping API
scope_Element_feature(Element element ,EReference ref)
Scoping API
scope_Element_feature(Element element ,EReference ref)
Scoping API
scope_Element_feature(Element element ,EReference ref)
Scoping API
scope_Element_feature(Element element ,EReference ref)
Called by the PolymorphicDispatcher…
Scoping API
scope_Element_feature(Element element ,EReference ref)
Called by the PolymorphicDispatcher…
…in a reflective w...
Scoping API
scope_Element_feature(Element element ,EReference ref)
Called by the PolymorphicDispatcher…
and if grammar cha...
Scoping API
scope_Element_feature(Element element ,EReference ref)
Called by the PolymorphicDispatcher…
and if grammar cha...
Scoping API
scope_Element_feature(Element element ,EReference ref)
Called by the PolymorphicDispatcher…
and if grammar cha...
Scoping API
scope_Element_feature(Element element ,EReference ref)
Called by the PolymorphicDispatcher…
and if grammar cha...
Use caches in the ScopeProvider
Use caches in the ScopeProvider
For each cross reference the ScopeProvider gets asked…
Use caches in the ScopeProvider
…and it calculates the very same stuff
over and over again…
For each cross reference the S...
Use caches in the ScopeProvider
…and it calculates the very same stuff
over and over again…
For each cross reference the S...
Use caches in the ScopeProvider
…and it calculates the very same stuff
over and over again…
For each cross reference the S...
Use the force of the Index
Use the force of the Index
Holds all lightweight representations of
referenceable elements and their resources
Use the force of the Index
Holds all lightweight representations of
referenceable elements and their resources
It’s a Hash...
Holds all lightweight representations of
referenceable elements and their resources
Use the force of the Index
It’s a Hash...
Index - how to feed it
Index - how to feed it
1. Builder picks up DSL files and loads them one by one
Index - how to feed it
1. Builder picks up DSL files and loads them one by one
2. Creates ResourceDescriptions through Res...
Index - how to feed it
1. Builder picks up DSL files and loads them one by one
2. Creates ResourceDescriptions through Res...
Index - how to feed it
1. Builder picks up DSL files and loads them one by one
2. Creates ResourceDescriptions through Res...
Index - how to feed it
1. Builder picks up DSL files and loads them one by one
2. Creates ResourceDescriptions through Res...
IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData)
Information hiding and userDa...
IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData)
Information hiding and userDa...
IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData)
Information hiding and userDa...
IEObjectDescription create(String simpleName, EObject element, Map<String, String> userData)
Information hiding and userDa...
UserData - what for?
UserData - what for?
Validation
Don’t load the world to get informations - put
them in the index
UserData - what for?
Validation
Don’t load the world to get informations - put
them in the index
Scoping
Don’t resolve pro...
Reference non Xtext models
Reference non Xtext models
We have our own GlobalScopeProvider that does the trick…
Reference non Xtext models
We have our own GlobalScopeProvider that does the trick…
…we load everything and the GlobalScop...
Reference non Xtext models
We have our own GlobalScopeProvider that does the trick…
…we load everything and the GlobalScop...
Reuse the Xtext infrastructure
Reuse the Xtext infrastructure
Bind a ResourceServiceProvider…
…so that you can put the elements in the index and make
the...
Reuse the Xtext infrastructure
Bind a ResourceServiceProvider…
…so that you can put the elements in the index and make
the...
But the builder picks them up…
and it takes ages!
Put the index in the jar
Put the index in the jar
Why calculating the index of a static set of files?
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 ...
Index in Standalone
It’s sooo slow…
Index in Standalone
It’s sooo slow…
…of course I have my custom Standalone impl…
Index in Standalone
ResourceSetGlobalScopeProvider
Long time the
was the default.
Index in Standalone
ResourceSetGlobalScopeProvider
Long time the
was the default.
Today we can do better but you need to u...
Index in Standalone
Fill the index and install it on the ResourceSet!
Load each resource and ask the ResourceDescriptionMa...
Index in Standalone
Fill the index and install it on the ResourceSet!
Load each resource and ask the ResourceDescriptionMa...
Make big things run again and save your ass!
Up to 80% more faster in 10 minutes!
Codegenerators
They are sooo slow…
Codegenerators
They are sooo slow…
… of course I am using mwe2 to invoke it…
Codegenerators
They are sooo slow…
… of course I am using mwe2 to invoke it…
… even in the IDE!
Incremental generators
Incremental generators
The builder triggers the generator for each resource…
Incremental generators
The builder triggers the generator for each resource…
…when a file changes the builder computes the...
Incremental generators
The builder triggers the generator for each resource…
…when a file changes the builder computes the...
Incremental generators
The builder triggers the generator for each resource…
…when a file changes the builder computes the...
Memory consumption
Memory consumption
DisabledClusteringPolicy
Do not unload resource…
Memory consumption
DisabledClusteringPolicy
DynamicResourceClusteringPolicy
Do not unload resource…
Unload resources when ...
The NodeModel is huge
Stores the syntax tree with text and positions…
The NodeModel is huge
Stores the syntax tree with text and positions…
…is used to get the position of a specific element o...
The NodeModel is huge
Stores the syntax tree with text and positions…
…is used to get the position of a specific element o...
The NodeModel is huge
Stores the syntax tree with text and positions…
…is used to get the position of a specific element o...
Switch off the NodeModel
Switch off the NodeModel
The parser creates it …
Switch off the NodeModel
The parser creates it …
…it is used to install proxies - so you have to do that
differently…
Switch off the NodeModel
The parser creates it …
…it is used to install proxies - so you have to do that
differently…
You ...
Switch off the NodeModel
The parser creates it …
…it is used to install proxies - so you have to do that
differently…
You ...
Switch off the NodeModel
The parser creates it …
…it is used to install proxies - so you have to do that
differently…
You ...
Implications
You cannot use the NodeModel in validations and
scoping any more…
Implications
You cannot use the NodeModel in validations and
scoping any more…
…Issues are marked at position 0,0…
…an Edi...
Implications
You cannot use the NodeModel in validations and
scoping any more…
…Issues are marked at position 0,0…
…an Edi...
Order makes a difference
Order makes a difference
Files might belong together…
Order makes a difference
Files might belong together…
…and might reference each other.
Order makes a difference
Files might belong together…
…and might reference each other.
Putting them in an logical order fo...
Order makes a difference
Files might belong together…
…and might reference each other.
Putting them in an logical order fo...
Order makes a difference
Files might belong together…
…and might reference each other.
Putting them in an logical order fo...
Now you know!
Professional Support
Xtext beyond the defaults -  how to tackle performance problems
Xtext beyond the defaults -  how to tackle performance problems
Xtext beyond the defaults -  how to tackle performance problems
Xtext beyond the defaults -  how to tackle performance problems
Xtext beyond the defaults -  how to tackle performance problems
Prochain SlideShare
Chargement dans…5
×

Xtext beyond the defaults - how to tackle performance problems

1 284 vues

Publié le

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.

Publié dans : Ingénierie
  • Soyez le premier à commenter

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

×