Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-7977

Refine the implementation of LRUCache

    Details

    • Type: Improvement
    • Status: Resolved
    • Priority: Minor
    • Resolution: Fixed
    • Affects Version/s: 2.4.7
    • Fix Version/s: 2.6.0-alpha-1
    • Component/s: None
    • Labels:
      None

      Description

      I found the LRUCache that Groovy is using is not efficient enough because it is based on Collections.synchronizedMap, the LRUCache is used by some important classes(e.g. ProxyGenerator, Closure), so it can impact the performance somehow.

      I propose to replace the implementation with Caffeine(https://github.com/ben-manes/caffeine), which is a high performance caching library for Java 8 and licensed under APL2.

      1. text.html
        4 kB
        Daniel.Sun
      2. text.html
        4 kB
        Daniel.Sun
      3. text.html
        4 kB
        Daniel.Sun
      4. text.html
        3 kB
        Daniel.Sun
      5. text.html
        5 kB
        Daniel.Sun
      6. text.html
        5 kB
        Daniel.Sun
      7. text.html
        4 kB
        Daniel.Sun
      8. text.html
        3 kB
        Daniel.Sun

        Activity

        Hide
        blackdrag Jochen Theodorou added a comment -

        The negatives:
        946k library size, which is quite big to jarjar, and we probably would have
        requires java8, so cannot be used in 2.4 or 2.5

        maybe if we take out only the parts we actually need, but then we would have to see what is left and since I know that this comes from guava, there might be still a big bunch of classes

        Show
        blackdrag Jochen Theodorou added a comment - The negatives: 946k library size, which is quite big to jarjar, and we probably would have requires java8, so cannot be used in 2.4 or 2.5 maybe if we take out only the parts we actually need, but then we would have to see what is left and since I know that this comes from guava, there might be still a big bunch of classes
        Hide
        jwagenleitner John Wagenleitner added a comment -

        I didn't look in great detail, but it seems the LRUCache is used in Closure to support a some bounded (atmost/between) memoize functions. The ProxyGenerator appears to use for caching proxies for asType calls. I am not sure that putting a more high performance LRU cache would have a significant impact on general performance that would make it worth taking on a new dependency or porting over classes from a 3rd party library to include in core. As I think was suggested on the mailing list, having some basic performance numbers showing the benefit would be useful information to have.

        Show
        jwagenleitner John Wagenleitner added a comment - I didn't look in great detail, but it seems the LRUCache is used in Closure to support a some bounded (atmost/between) memoize functions. The ProxyGenerator appears to use for caching proxies for asType calls. I am not sure that putting a more high performance LRU cache would have a significant impact on general performance that would make it worth taking on a new dependency or porting over classes from a 3rd party library to include in core. As I think was suggested on the mailing list, having some basic performance numbers showing the benefit would be useful information to have.
        Hide
        danielsun1106 Daniel.Sun added a comment -

        OK. Maybe we can look for some other smaller lib

        在 "Jochen Theodorou (JIRA)" <jira@apache.org>,2016年10月28日 上午12:55写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15612483#comment-15612483 ]

        Jochen Theodorou commented on GROOVY-7977:
        ------------------------------------------

        The negatives:
        946k library size, which is quite big to jarjar, and we probably would have
        requires java8, so cannot be used in 2.4 or 2.5

        maybe if we take out only the parts we actually need, but then we would have to see what is left and since I know that this comes from guava, there might be still a big bunch of classes


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - OK. Maybe we can look for some other smaller lib 在 "Jochen Theodorou (JIRA)" <jira@apache.org>,2016年10月28日 上午12:55写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15612483#comment-15612483 ] Jochen Theodorou commented on GROOVY-7977 : ------------------------------------------ The negatives: 946k library size, which is quite big to jarjar, and we probably would have requires java8, so cannot be used in 2.4 or 2.5 maybe if we take out only the parts we actually need, but then we would have to see what is left and since I know that this comes from guava, there might be still a big bunch of classes – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        danielsun1106 Daniel.Sun added a comment -

        I'm not sure how much performance can be improved, it depends on specific senario, so this is just a minor proposal.

        在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月28日 上午1:32写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15612577#comment-15612577 ]

        John Wagenleitner commented on GROOVY-7977:
        -------------------------------------------

        I didn't look in great detail, but it seems the LRUCache is used in Closure to support a some bounded (atmost/between) memoize functions. The ProxyGenerator appears to use for caching proxies for asType calls. I am not sure that putting a more high performance LRU cache would have a significant impact on general performance that would make it worth taking on a new dependency or porting over classes from a 3rd party library to include in core. As I think was suggested on the mailing list, having some basic performance numbers showing the benefit would be useful information to have.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - I'm not sure how much performance can be improved, it depends on specific senario, so this is just a minor proposal. 在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月28日 上午1:32写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15612577#comment-15612577 ] John Wagenleitner commented on GROOVY-7977 : ------------------------------------------- I didn't look in great detail, but it seems the LRUCache is used in Closure to support a some bounded (atmost/between) memoize functions. The ProxyGenerator appears to use for caching proxies for asType calls. I am not sure that putting a more high performance LRU cache would have a significant impact on general performance that would make it worth taking on a new dependency or porting over classes from a 3rd party library to include in core. As I think was suggested on the mailing list, having some basic performance numbers showing the benefit would be useful information to have. – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        danielsun1106 Daniel.Sun added a comment -

        Grails supports outputing JOSN via render airport as JSON, if the code is executed concurrently in some big site, the concurrency will reduce to some extent.

        在 "Daniel.Sun (JIRA)" <jira@apache.org>,2016年10月28日 上午3:47写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

        Daniel.Sun updated GROOVY-7977:
        -------------------------------
        Attachment: text.html

        I'm not sure how much performance can be improved, it depends on specific senario, so this is just a minor proposal.

        在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月28日 上午1:32写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15612577#comment-15612577 ]

        John Wagenleitner commented on GROOVY-7977:
        -------------------------------------------

        I didn't look in great detail, but it seems the LRUCache is used in Closure to support a some bounded (atmost/between) memoize functions. The ProxyGenerator appears to use for caching proxies for asType calls. I am not sure that putting a more high performance LRU cache would have a significant impact on general performance that would make it worth taking on a new dependency or porting over classes from a 3rd party library to include in core. As I think was suggested on the mailing list, having some basic performance numbers showing the benefit would be useful information to have.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - Grails supports outputing JOSN via render airport as JSON , if the code is executed concurrently in some big site, the concurrency will reduce to some extent. 在 "Daniel.Sun (JIRA)" <jira@apache.org>,2016年10月28日 上午3:47写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ] Daniel.Sun updated GROOVY-7977 : ------------------------------- Attachment: text.html I'm not sure how much performance can be improved, it depends on specific senario, so this is just a minor proposal. 在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月28日 上午1:32写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15612577#comment-15612577 ] John Wagenleitner commented on GROOVY-7977 : ------------------------------------------- I didn't look in great detail, but it seems the LRUCache is used in Closure to support a some bounded (atmost/between) memoize functions. The ProxyGenerator appears to use for caching proxies for asType calls. I am not sure that putting a more high performance LRU cache would have a significant impact on general performance that would make it worth taking on a new dependency or porting over classes from a 3rd party library to include in core. As I think was suggested on the mailing list, having some basic performance numbers showing the benefit would be useful information to have. – This message was sent by Atlassian JIRA (v6.3.4#6332) – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        ben.manes Ben Manes added a comment -

        ConcurrentLinkedHashMap is a 115 kb jar, but could be trimmed to 55 kb by removing the JDK8 ConcurrentHashMap backport. Note that Grails uses the library, as have many projects such as Cassandra, but all are gradually transitioning to Caffeine.

        ConcurrentLinkedHashMap was project to investigate how to design a concurrent LRU cache, so its feature bare but very fast. In parallel Guava was working on MapMaker to be feature rich, but designed around soft references as the caching scheme. That of course leads to poor GC effects, so CLHM's ideas were scaffolded on and became CacheBuilder. Unfortunately in the process a lot of performance was lost and I left before being able to fix that.

        Caffeine tries to push the boundaries further performance wise, feature wise, and policy wise. That leads to a more complex library, which is large due to code generation to reduce the runtime footprint.

        ConcurrentLinkedHashMap is Java 6 based, easy to shade, and pretty straightforward. However its in maintenance mode and lacks richer features like memoization. It is a drop-in replacement for a synchronized LinkedHashMap based LRU cache, so its probably the easier fit.

        Show
        ben.manes Ben Manes added a comment - ConcurrentLinkedHashMap is a 115 kb jar, but could be trimmed to 55 kb by removing the JDK8 ConcurrentHashMap backport. Note that Grails uses the library, as have many projects such as Cassandra, but all are gradually transitioning to Caffeine. ConcurrentLinkedHashMap was project to investigate how to design a concurrent LRU cache, so its feature bare but very fast. In parallel Guava was working on MapMaker to be feature rich, but designed around soft references as the caching scheme. That of course leads to poor GC effects, so CLHM's ideas were scaffolded on and became CacheBuilder. Unfortunately in the process a lot of performance was lost and I left before being able to fix that. Caffeine tries to push the boundaries further performance wise, feature wise, and policy wise. That leads to a more complex library, which is large due to code generation to reduce the runtime footprint. ConcurrentLinkedHashMap is Java 6 based, easy to shade, and pretty straightforward. However its in maintenance mode and lacks richer features like memoization. It is a drop-in replacement for a synchronized LinkedHashMap based LRU cache, so its probably the easier fit.
        Hide
        danielsun1106 Daniel.Sun added a comment -

        Hi Ben,

        Thanks for your suggestion. Because the lib will be included in the core jar, we wish the size of the lib could be as small as possible and the lib was independent. I find ConcurrentLinkedHashMap uses javax annotations, can we remove it simply?

        {{
        import javax.annotation.concurrent.GuardedBy;
        import javax.annotation.concurrent.Immutable;
        import javax.annotation.concurrent.ThreadSafe;
        }}

        在 "Ben Manes (JIRA)" <jira@apache.org>,2016年10月29日 下午12:12写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15617386#comment-15617386 ]

        Ben Manes commented on GROOVY-7977:
        -----------------------------------

        ConcurrentLinkedHashMap is a 115 kb jar, but could be trimmed to 55 kb by removing the JDK8 ConcurrentHashMap backport. Note that Grails uses the library, as have many projects such as Cassandra, but all are gradually transitioning to Caffeine.

        ConcurrentLinkedHashMap was project to investigate how to design a concurrent LRU cache, so its feature bare but very fast. In parallel Guava was working on MapMaker to be feature rich, but designed around soft references as the caching scheme. That of course leads to poor GC effects, so CLHM's ideas were scaffolded on and became CacheBuilder. Unfortunately in the process a lot of performance was lost and I left before being able to fix that.

        Caffeine tries to push the boundaries further performance wise, feature wise, and policy wise. That leads to a more complex library, which is large due to code generation to reduce the runtime footprint.

        ConcurrentLinkedHashMap is Java 6 based, easy to shade, and pretty straightforward. However its in maintenance mode and lacks richer features like memoization. It is a drop-in replacement for a synchronized LinkedHashMap based LRU cache, so its probably the easier fit.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - Hi Ben, Thanks for your suggestion. Because the lib will be included in the core jar, we wish the size of the lib could be as small as possible and the lib was independent. I find ConcurrentLinkedHashMap uses javax annotations, can we remove it simply? {{ import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.Immutable; import javax.annotation.concurrent.ThreadSafe; }} 在 "Ben Manes (JIRA)" <jira@apache.org>,2016年10月29日 下午12:12写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15617386#comment-15617386 ] Ben Manes commented on GROOVY-7977 : ----------------------------------- ConcurrentLinkedHashMap is a 115 kb jar, but could be trimmed to 55 kb by removing the JDK8 ConcurrentHashMap backport. Note that Grails uses the library, as have many projects such as Cassandra, but all are gradually transitioning to Caffeine. ConcurrentLinkedHashMap was project to investigate how to design a concurrent LRU cache, so its feature bare but very fast. In parallel Guava was working on MapMaker to be feature rich, but designed around soft references as the caching scheme. That of course leads to poor GC effects, so CLHM's ideas were scaffolded on and became CacheBuilder. Unfortunately in the process a lot of performance was lost and I left before being able to fix that. Caffeine tries to push the boundaries further performance wise, feature wise, and policy wise. That leads to a more complex library, which is large due to code generation to reduce the runtime footprint. ConcurrentLinkedHashMap is Java 6 based, easy to shade, and pretty straightforward. However its in maintenance mode and lacks richer features like memoization. It is a drop-in replacement for a synchronized LinkedHashMap based LRU cache, so its probably the easier fit. – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        ben.manes Ben Manes added a comment -

        Yes, I used that for documentation purposes only so it can be striped. Its marked as provided scoped as the dependency isn't necessary.

        Show
        ben.manes Ben Manes added a comment - Yes, I used that for documentation purposes only so it can be striped. Its marked as provided scoped as the dependency isn't necessary.
        Hide
        danielsun1106 Daniel.Sun added a comment -

        I see. Thanks for your explanation in details

        在 "Ben Manes (JIRA)" <jira@apache.org>,2016年10月29日 下午12:49写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15617436#comment-15617436 ]

        Ben Manes commented on GROOVY-7977:
        -----------------------------------

        Yes, I used that for documentation purposes only so it can be striped. Its marked as provided scoped as the dependency isn't necessary.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - I see. Thanks for your explanation in details 在 "Ben Manes (JIRA)" <jira@apache.org>,2016年10月29日 下午12:49写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15617436#comment-15617436 ] Ben Manes commented on GROOVY-7977 : ----------------------------------- Yes, I used that for documentation purposes only so it can be striped. Its marked as provided scoped as the dependency isn't necessary. – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        jwagenleitner John Wagenleitner added a comment -

        The current LRUCache implementation is based on a synchronizedMap LRUProtectionStorage which extends LinkedHashMap and implements access order by doing a remove/put on calls to and overriden get. One minor improvement, if the class is not replaced entirely, may be to call super(maxSize, 1.0f, true) in the constructor and let LinkedHashMap main access order, then the overriden get could be removed and touch could be done with a call to get.

        Show
        jwagenleitner John Wagenleitner added a comment - The current LRUCache implementation is based on a synchronizedMap LRUProtectionStorage which extends LinkedHashMap and implements access order by doing a remove / put on calls to and overriden get . One minor improvement, if the class is not replaced entirely, may be to call super(maxSize, 1.0f, true) in the constructor and let LinkedHashMap main access order, then the overriden get could be removed and touch could be done with a call to get .
        Hide
        danielsun1106 Daniel.Sun added a comment -

        Hi John,

        The synchronizedMap use single lock to synchronize all methods of wrapped map, so even if only "get" method is accessed, the requests are still processed one by one, which is not efficient too.

        Cheers,
        Daniel.Sun

        在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月30日 下午10:12写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15620005#comment-15620005 ]

        John Wagenleitner commented on GROOVY-7977:
        -------------------------------------------

        The current LRUCache implementation is based on a synchronizedMap LRUProtectionStorage which extends LinkedHashMap and implements access order by doing a remove/put on calls to and overriden get. One minor improvement, if the class is not replaced entirely, may be to call super(maxSize, 1.0f, true) in the constructor and let LinkedHashMap main access order, then the overriden get could be removed and touch could be done with a call to get.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - Hi John, The synchronizedMap use single lock to synchronize all methods of wrapped map, so even if only "get" method is accessed, the requests are still processed one by one, which is not efficient too. Cheers, Daniel.Sun 在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月30日 下午10:12写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15620005#comment-15620005 ] John Wagenleitner commented on GROOVY-7977 : ------------------------------------------- The current LRUCache implementation is based on a synchronizedMap LRUProtectionStorage which extends LinkedHashMap and implements access order by doing a remove / put on calls to and overriden get . One minor improvement, if the class is not replaced entirely, may be to call super(maxSize, 1.0f, true) in the constructor and let LinkedHashMap main access order, then the overriden get could be removed and touch could be done with a call to get . – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        jwagenleitner John Wagenleitner added a comment -

        Hi Daniel.Sun

        The synchronizedMap use single lock to synchronize all methods of wrapped map, so even if only "get" method is accessed, the requests are still processed one by one, which is not efficient too.

        I understand how the synchronized map works and you're exactly right. So the more efficient the code in the sync block the better. I was just mentioning a possible refinement to the current implementation and that's why I said it would be a minor improvement in case the class was not replace entirely with a new dependency.

        Show
        jwagenleitner John Wagenleitner added a comment - Hi Daniel.Sun The synchronizedMap use single lock to synchronize all methods of wrapped map, so even if only "get" method is accessed, the requests are still processed one by one, which is not efficient too. I understand how the synchronized map works and you're exactly right. So the more efficient the code in the sync block the better. I was just mentioning a possible refinement to the current implementation and that's why I said it would be a minor improvement in case the class was not replace entirely with a new dependency.
        Hide
        danielsun1106 Daniel.Sun added a comment -

        Hi John,

        You can call me Daniel
        The size of ConcurrentLinkedHashMap relatedcode is very small, about 55k. Its stability has been verified by Grails. How about including its code with renaming its package name(e.g. org.apache.groovy.util)?

        Cheers,
        Daniel.Sun

        在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月31日 上午11:39写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15621109#comment-15621109 ]

        John Wagenleitner commented on GROOVY-7977:
        -------------------------------------------

        Hi Daniel.Sun

        The synchronizedMap use single lock to synchronize all methods of wrapped map, so even if only "get" method is accessed, the requests are still processed one by one, which is not efficient too.

        I understand how the synchronized map works and you're exactly right. So the more efficient the code in the sync block the better. I was just mentioning a possible refinement to the current implementation and that's why I said it would be a minor improvement in case the class was not replace entirely with a new dependency.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - Hi John, You can call me Daniel The size of ConcurrentLinkedHashMap relatedcode is very small, about 55k. Its stability has been verified by Grails. How about including its code with renaming its package name(e.g. org.apache.groovy.util)? Cheers, Daniel.Sun 在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年10月31日 上午11:39写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15621109#comment-15621109 ] John Wagenleitner commented on GROOVY-7977 : ------------------------------------------- Hi Daniel.Sun The synchronizedMap use single lock to synchronize all methods of wrapped map, so even if only "get" method is accessed, the requests are still processed one by one, which is not efficient too. I understand how the synchronized map works and you're exactly right. So the more efficient the code in the sync block the better. I was just mentioning a possible refinement to the current implementation and that's why I said it would be a minor improvement in case the class was not replace entirely with a new dependency. – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        jwagenleitner John Wagenleitner added a comment -

        Hi Daniel,

        My initial reaction is that it would be good to keep the classes/interface together in a separate org.apache.groovy.util.concurrentlinkedhashmap package and not mix with potential future util classes. If at some point in the future it would become better to move them up into o.a.g.util then it could be done at that time. But initially keeping them cleanly separated seems good to me, just my opinion.

        Show
        jwagenleitner John Wagenleitner added a comment - Hi Daniel, My initial reaction is that it would be good to keep the classes/interface together in a separate org.apache.groovy.util.concurrentlinkedhashmap package and not mix with potential future util classes. If at some point in the future it would become better to move them up into o.a.g.util then it could be done at that time. But initially keeping them cleanly separated seems good to me, just my opinion.
        Hide
        danielsun1106 Daniel.Sun added a comment -

        Hi John,

        I agree with you

        Cheers,
        Daniel.Sun

        在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年11月1日 上午12:48写道:

        [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15622693#comment-15622693 ]

        John Wagenleitner commented on GROOVY-7977:
        -------------------------------------------

        Hi Daniel,

        My initial reaction is that it would be good to keep the classes/interface together in a separate org.apache.groovy.util.concurrentlinkedhashmap package and not mix with potential future util classes. If at some point in the future it would become better to move them up into o.a.g.util then it could be done at that time. But initially keeping them cleanly separated seems good to me, just my opinion.


        This message was sent by Atlassian JIRA
        (v6.3.4#6332)

        Show
        danielsun1106 Daniel.Sun added a comment - Hi John, I agree with you Cheers, Daniel.Sun 在 "John Wagenleitner (JIRA)" <jira@apache.org>,2016年11月1日 上午12:48写道: [ https://issues.apache.org/jira/browse/GROOVY-7977?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15622693#comment-15622693 ] John Wagenleitner commented on GROOVY-7977 : ------------------------------------------- Hi Daniel, My initial reaction is that it would be good to keep the classes/interface together in a separate org.apache.groovy.util.concurrentlinkedhashmap package and not mix with potential future util classes. If at some point in the future it would become better to move them up into o.a.g.util then it could be done at that time. But initially keeping them cleanly separated seems good to me, just my opinion. – This message was sent by Atlassian JIRA (v6.3.4#6332)
        Hide
        daniel_sun Daniel Sun added a comment - - edited

        According to the above discussion, the issue is fixed on parrot branch: https://github.com/apache/groovy/commit/d30f059bf6dff6d7badb328d8595cee41d56ce25

        Show
        daniel_sun Daniel Sun added a comment - - edited According to the above discussion, the issue is fixed on parrot branch: https://github.com/apache/groovy/commit/d30f059bf6dff6d7badb328d8595cee41d56ce25
        Hide
        daniel_sun Daniel Sun added a comment -

        Fixed in the parrot branch

        Show
        daniel_sun Daniel Sun added a comment - Fixed in the parrot branch

          People

          • Assignee:
            daniel_sun Daniel Sun
            Reporter:
            daniel_sun Daniel Sun
          • Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development