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

Question on stdlib cache? #19187

Closed
ramith opened this issue Sep 25, 2019 · 4 comments · Fixed by #21308
Closed

Question on stdlib cache? #19187

ramith opened this issue Sep 25, 2019 · 4 comments · Fixed by #21308
Assignees
Labels
Team/StandardLibs All Ballerina standard libraries Type/Improvement

Comments

@ramith
Copy link
Contributor

ramith commented Sep 25, 2019

Description:
So I was looking at the cache implementation at :
https://github.com/ballerina-platform/ballerina-lang/blob/release-1.0.1/stdlib/cache/src/main/ballerina/src/cache/cache.bal

I have following questions:

  1. I see there is synchronization in put() function but not in get function. is this intentional?
  2. Further, if you look at line 173 to 175 (following code fragment), I would argue there can be a put() operation which could happen in parallel busting the logic. e.g. think about a scenario where !self.hasKey(key) becomes true and a put() happens before the return ();
      // Check whether the requested cache is available.
        if (!self.hasKey(key)) {
            return ();
        }
  1. I suppose we can deduce a couple of more such scenarios just by looking at get() and put()

But I could be wrong given that I don't have a clear understanding of how ballerina's concurrency is handled.

Steps to reproduce:
N/A
Affected Versions:
v1.0, v 1.0.1
OS, DB, other environment details and versions:
MacOS, Jdk 1.8

Suggested Assignees (optional):
@wggihan @pubudu91 @a5anka

@a5anka
Copy link
Member

a5anka commented Sep 25, 2019

Another issue is that we are locking all the put() functions of multiple caches using the global object cacheMap. This adds an unnecessary performance overhead.

@hasithaa hasithaa added the Team/StandardLibs All Ballerina standard libraries label Sep 25, 2019
@wggihan
Copy link
Contributor

wggihan commented Sep 25, 2019

Description:
So I was looking at the cache implementation at :
https://github.com/ballerina-platform/ballerina-lang/blob/release-1.0.1/stdlib/cache/src/main/ballerina/src/cache/cache.bal

I have following questions:

  1. I see there is synchronization in put() function but not in get function. is this intentional?
    Yes, this is intentional. The main idea behind the reason is to improve cache performance. Basically get doesn't need any handling in term of concurrently accessing.
  1. Further, if you look at line 173 to 175 (following code fragment), I would argue there can be a put() operation which could happen in parallel busting the logic. e.g. think about a scenario where !self.hasKey(key) becomes true and a put() happens before the return ();
      // Check whether the requested cache is available.
        if (!self.hasKey(key)) {
            return ();
        }

IINM, cache misses can happen due to this. But since this is a simple cache. I believe that is acceptable.

  1. I suppose we can deduce a couple of more such scenarios just by looking at get() and put()

But I could be wrong given that I don't have a clear understanding of how ballerina's concurrency is handled.

Steps to reproduce:
N/A
Affected Versions:
v1.0, v 1.0.1
OS, DB, other environment details and versions:
MacOS, Jdk 1.8

Suggested Assignees (optional):
@wggihan @pubudu91 @a5anka

@wggihan
Copy link
Contributor

wggihan commented Sep 25, 2019

Another issue is that we are locking all the put() functions of multiple caches using the global object cacheMap. This adds an unnecessary performance overhead.

With the current implementation, we can't omit the global cache map.

@chethiya
Copy link

I assume original post is regarding data corruption that can occur due to race condition. But the given example there (i.e. hasKey) doesn't cause any such race conditions it seems. Ballerina map<> implementation seems to be thread safe (assuming it's implemented using MapValueImpl class)

But I think following line in get() of Cache can cause data races

            cacheEntry.lastAccessedTime = time:currentTime().time;

So this can cause cache to evict wrong keys in case the values in cacheEntry.lastAccessedTime get corrupted due to data races.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Team/StandardLibs All Ballerina standard libraries Type/Improvement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants