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

ASF GitHub Bot commented on MARMOTTA-620:
-----------------------------------------

Github user wastl commented on a diff in the pull request:

    https://github.com/apache/marmotta/pull/15#discussion_r44345877
  
    --- Diff: 
libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java
 ---
    @@ -575,13 +577,29 @@ public Statement createStatement(Resource subject, 
URI predicate, Value object,
                         registry.registerKey(cacheKey, 
connection.getTransactionId(), result.getId());
                     } else {
                         // not found in registry, try loading from database
    -                    
result.setId(connection.getTripleId(ksubject,kpredicate,kobject,kcontext));
    +                    needsDBLookup = true;
                     }
    +            }
    +
    +            if(needsDBLookup) {
    +                
result.setId(connection.getTripleId(ksubject,kpredicate,kobject,kcontext));
    +            }
     
    -                // triple has no id from registry or database, so we 
create one and flag it for reasoning
    -                if(result.getId() < 0) {
    -                    result.setId(connection.getNextSequence());
    -                    result.setNewTriple(true);
    +            // triple has no id from registry or database, so we create 
one and flag it for reasoning
    +            if(result.getId() < 0) {
    +                synchronized (registry) {
    +                    // It's possible a concurrent thread might have 
created this
    +                    // triple while we were blocked.  Check the registry 
again.
    +                    long tripleId = registry.lookupKey(cacheKey);
    +
    +                    if(tripleId >= 0) {
    +                        // A concurrent thread got in first.  Take the one 
it created.
    +                        result.setId(tripleId);
    --- End diff --
    
    I guess in this case the call to registerKey below is not needed (it came 
from the registry).


> Lock contention with multiple writers hitting the LDP service
> -------------------------------------------------------------
>
>                 Key: MARMOTTA-620
>                 URL: https://issues.apache.org/jira/browse/MARMOTTA-620
>             Project: Marmotta
>          Issue Type: Improvement
>          Components: KiWi Triple Store
>    Affects Versions: 3.3.0
>            Reporter: Mark Triggs
>         Attachments: marmotta-coarse-locking-all-responses.png, 
> marmotta-fine-locking-all-responses.png
>
>
> This issue references the following mailing list post:
> http://mail-archives.apache.org/mod_mbox/marmotta-users/201511.mbox/%3C87pozjwzp4.fsf%40dishevelled.net%3E
> -----
> I've been doing some performance tuning work with Tom Johnson and Mark 
> Breedlove of the DPLA (who have both posted recently), and have noticed a 
> possible improvement for performance when multiple writers are PUTing records 
> concurrently.
> While running a benchmark where multiple workers PUT records via Marmotta's 
> LDP interface, I noticed that all but one of the threads were waiting on a 
> lock inside the JVM. The code in question was this `synchronized` block in 
> KiWiValueFactory.createStatement:
> https://github.com/dpla/marmotta/blob/master/libraries/kiwi/kiwi-triplestore/ 
> src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java#L567
> This code takes a lock on the `registry` object (shared by all connections), 
> and holds it while calling connection.getTripleId(). That query is generally 
> pretty fast, but it's called frequently enough that the cost of the locking 
> can still be quite high.
> I ran a test where 5 concurrent writers each PUT random records via 
> Marmotta's LDP interface. I ran 6 test rounds, with each round adding an 
> extra millisecond delay to the getTripleId() call (simulating between 0 and 5 
> milliseconds of network/database latency). As that query gets slower, the 
> effect of the Java locking becomes more dramatic, as you can see from the 
> response times here:
> http://dishevelled.net/marmotta-coarse-locking-all-responses.png
> With no added delay (and Postgres running on the same machine as Marmotta), 
> most PUT requests complete within about 500ms. With 5 milliseconds of delay, 
> the same PUT requests take between 2.5 and 3 seconds.
> I reworked the code to reduce the time that lock was held, and reran my test. 
>  You can see the response times are much better, even with 5ms of latency:
> http://dishevelled.net/marmotta-fine-locking-all-responses.png
> I've got a patch for this that I'm happy to send along. I drop the lock prior 
> to running the getTripleId() query (allowing multiple connections to run the 
> query at once), then only take it again if I need to write a new triple ID to 
> the registry:
> https://github.com/marktriggs/marmotta/blob/mst-perf/libraries/kiwi/kiwi-triplestore/src/main/java/org/apache/marmotta/kiwi/sail/KiWiValueFactory.java#L578



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

Reply via email to