Skip to content

Conversation

@jose-torres
Copy link
Contributor

What changes were proposed in this pull request?

Write HDFSBackedStateStoreProvider.loadMap non-recursively. This prevents stack overflow if too many deltas stack up in a low memory environment.

How was this patch tested?

existing unit tests for functional equivalence, new unit test to check for stack overflow

Copy link
Member

@srowen srowen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few initial style comments

var lastAvailableVersion = version
var lastAvailableMap: Option[MapType] = None
while (lastAvailableMap.isEmpty) {
lastAvailableVersion = lastAvailableVersion - 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: -= 1?

// Shortcut if the map for this version is already there to avoid a redundant put.
val currentVersionMap =
synchronized { loadedMaps.get(version) }.orElse(readSnapshotFile(version))
if (currentVersionMap.isDefined) return currentVersionMap.get
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd unroll this onto two lines with braces for consistency


// Load all the deltas from the version after the last available one up to the target version.
// The last available version is the one with a full snapshot, so it doesn't need deltas.
var resultMap = lastAvailableMap.get
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

val?

}

loadedMaps.put(version, resultMap)
return resultMap
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need return

@jose-torres
Copy link
Contributor Author

One issue I want to explicitly bring up: this new unit test takes very long, almost 2 minutes on my computer. Creating 10k files isn't going to be super fast no matter what we do, but is there something that can mitigate the problem? Maybe it'd be better in a different suite or something; I don't know what the typical practice is.

@zsxwing
Copy link
Member

zsxwing commented Oct 30, 2017

I think we can remove the unit test. It's obviously that loadMap is not recursive and will not cause StackOverflowError.

@SparkQA
Copy link

SparkQA commented Oct 30, 2017

Test build #83225 has started for PR 19611 at commit e81d142.

@SparkQA
Copy link

SparkQA commented Oct 30, 2017

Test build #83217 has finished for PR 19611 at commit 33ea2fb.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@SparkQA
Copy link

SparkQA commented Oct 30, 2017

Test build #83220 has finished for PR 19611 at commit 70df407.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

Copy link
Member

@zsxwing zsxwing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good. Left some comments

if (currentVersionMap.isDefined) {
return currentVersionMap.get
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: extra empty line


// Load all the deltas from the version after the last available one up to the target version.
// The last available version is the one with a full snapshot, so it doesn't need deltas.
val resultMap = lastAvailableMap.get
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should create a new map here to not change the previous map in case the maintenance task is using it.


// Shortcut if the map for this version is already there to avoid a redundant put.
val currentVersionMap =
synchronized { loadedMaps.get(version) }.orElse(readSnapshotFile(version))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should put the map read from snapshot file into loadedMaps.

updateFromDeltaFile(deltaVersion, resultMap)
}

loadedMaps.put(version, resultMap)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loadedMaps.put(version, resultMap) -> synchronized { loadedMaps.put(version, resultMap) }

This is a different issue but since you are touching this, it's better to fix it as well.

@zsxwing
Copy link
Member

zsxwing commented Oct 30, 2017

LGTM pending tests

@SparkQA
Copy link

SparkQA commented Oct 31, 2017

Test build #83229 has finished for PR 19611 at commit d98ce9e.

  • This patch passes all tests.
  • This patch merges cleanly.
  • This patch adds no public classes.

@zsxwing
Copy link
Member

zsxwing commented Oct 31, 2017

Thanks! Merging to master.

@asfgit asfgit closed this in 7323186 Oct 31, 2017
@subourbonite
Copy link

Is there any chance of this change getting merged into 2.2.1?

@zsxwing
Copy link
Member

zsxwing commented Nov 6, 2017

@BriggsW This is pretty hard to hit. I could not make it happen in a real query. So I think it's not worth to backport it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants