Uploaded image for project: 'TinkerPop'
  1. TinkerPop
  2. TINKERPOP-2899

SampleGlobalStep samples inefficiently with TraverserSet running into hash collisions

    XMLWordPrintableJSON

Details

    • Improvement
    • Status: Closed
    • Critical
    • Resolution: Fixed
    • 3.5.5
    • 3.7.0, 3.6.3, 3.5.6
    • process
    • None

    Description

      For some queries, the SampleGlobalStep can take a huge amount of time. For example, on a Gremlin variant of the LUBM dataset and the following query

      g.V().hasLabel('Course').sample(1000).in('teacherOf').path() 

      the sample step has 108000 traversers as input, but requires over 200 seconds. More precisely: Collecting all traversers from previous step with processAllStarts (see https://github.com/apache/tinkerpop/blob/master/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java#L83-L85) takes 108344 ms, thereby createProjectedTraverser: 1416 ms, traverserSet::add: 106238 ms. The barrierConsumer finished sampling in 121088 ms, whereby the loop was executed 53356191 times.
       
      There seem to be two issues:
       
      1. There are many hash collisions when adding the projected traverser to the map in the TraverserSet (see https://github.com/apache/tinkerpop/blob/master/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/traverser/util/TraverserSet.java#L91, called from the prcessAllStarts (https://github.com/apache/tinkerpop/blob/master/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java#L84).  For example, for v[http://www.Department0.University15.edu/Course0, we compute the hash code via super.hashCode() ^ this.path.hashCode(), which is -2056934079 - -2056934048 = 33 (basically the hash code of the id string XOR the hash code of the path, i.e., singleton list of the id string). This leads to many very similar hash codes, e.g.,

      33
      103
      33
      227
      33
      111
      33
      995
      33
      103
      33
      31
      481
      39
      97
      35
      225
      47
      97
      35
      993
      39
      225
      99
      33
      ... 

       
      2. The sampling algorithm seems to be extremely inefficient (often running the loop again without adding a new sample). It is not completely clear why it was written that way (lack of documentation), but it may have been necessary to correctly handling these “bulks”.
       
      The second issue could potentially be addressed by checking whether all traversers have the same weight (https://github.com/apache/tinkerpop/blob/master/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java#L96), which seems to be the case in this example, and then use a more efficient sampling approach that just samples a corresponding number of integers between 0 and the number of traversers in the sample set and store these numbers in a set (with count). With that we can iterate through the traverserSet and use the corresponding traversers if we have it sampled.
       
      For the first issue, we can probably just avoid putting them in the TraverserSet and use an ArrayList instead. Then we could also directly sample from this ArrayList, which may even make this bulk handling superfluous?
       
      There is however also an "efficient" rewrite of this query using fold, local sample and unfold:

      g.V().hasLabel('Course').fold().sample(Scope.local,1000).unfold().in('teacherOf').path() 

       
      The general question is, however, whether the TraverserSet can lead to hash collisions in other places. Maybe it makes sense to reevaluate the usage of this TraverserSet and, if useful/required, switch to something more efficient time-wise (which could then require a bit more memory).

      Attachments

        Activity

          People

            kenhuuu Ken Hu
            steigma steigma
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: