Skip to content

Reduce the GitClient instances creation for CI Visibility pipelines#240

Merged
drodriguezhdez merged 21 commits into
masterfrom
drodriguezhdez/fix_perf_issues
Sep 3, 2021
Merged

Reduce the GitClient instances creation for CI Visibility pipelines#240
drodriguezhdez merged 21 commits into
masterfrom
drodriguezhdez/fix_perf_issues

Conversation

@drodriguezhdez

@drodriguezhdez drodriguezhdez commented Aug 12, 2021

Copy link
Copy Markdown
Collaborator

Requirements for Contributing to this repository

  • Fill out the template below. Any pull request that does not include enough information to be reviewed in a timely manner may be closed at the maintainers' discretion.
  • The pull request must only fix one issue at the time.
  • The pull request must update the test suite to demonstrate the changed functionality.
  • After you create the pull request, all status checks must be pass before a maintainer reviews your contribution. For more details, please see CONTRIBUTING.

What does this PR do?

This PR adds performance improvements, especially related to GitClient instances:

  • The DatadogStepListener logic now is only executed if CI Visibility is enabled.
  • Optimizations about the number of times that a GitClient instance is created.
    • If there is no valid GIT_URL or GIT_COMMIT, no GitClient is created.
    • If the Git information was calculated for a certain GIT_URL and GIT_COMMIT, no new GitClient instance is created after.
  • A new class called DatadogAudit is used to send logs with the duration of certain methods. This can be opt-in by the user in the Jenkins log manager.

Context
We use the GitClient instance to extract the details about a commit (author, message, etc) and the default branch.
The creation of the GitClient instance is a very expensive operation.

Description of the Change

Alternate Designs

Possible Drawbacks

Verification Process

Additional Notes

Release Notes

Review checklist (to be filled by reviewers)

  • Feature or bug fix MUST have appropriate tests (unit, integration, etc...)
  • PR title must be written as a CHANGELOG entry (see why)
  • Files changes must correspond to the primary purpose of the PR as described in the title (small unrelated changes should have their own PR)
  • PR must have one changelog/ label attached. If applicable it should have the backward-incompatible label attached.
  • PR should not have do-not-merge/ label attached.
  • If Applicable, issue must have kind/ and severity/ labels attached at least.

@drodriguezhdez
drodriguezhdez marked this pull request as ready for review September 1, 2021 14:28
@drodriguezhdez drodriguezhdez added the changelog/Fixed Fixed features results into a bug fix version bump label Sep 1, 2021
Comment on lines +314 to +320
this.gitMessage = gitCommitAction.getMessage();
this.gitAuthorName = gitCommitAction.getAuthorName();
this.gitAuthorEmail = gitCommitAction.getAuthorEmail();
this.gitAuthorDate = gitCommitAction.getAuthorDate();
this.gitCommitterName = gitCommitAction.getCommitterName();
this.gitCommitterEmail = gitCommitAction.getCommitterEmail();
this.gitCommitterDate = gitCommitAction.getCommitterDate();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This code is duplicated here and in lines 286-294. I would extract it to a function.

Comment on lines +304 to +309
GitClient gitClient = null;
if(isValidCommit(gitCommit) || isValidRepositoryURL(this.gitUrl)) {
// Create a new Git client is a very expensive operation.
// Avoid creating Git clients as much as possible.
gitClient = GitUtils.newGitClient(run, listener, envVars, this.nodeName, this.workspace);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
GitClient gitClient = null;
if(isValidCommit(gitCommit) || isValidRepositoryURL(this.gitUrl)) {
// Create a new Git client is a very expensive operation.
// Avoid creating Git clients as much as possible.
gitClient = GitUtils.newGitClient(run, listener, envVars, this.nodeName, this.workspace);
}
if(!isValidCommit(gitCommit) && !isValidRepositoryURL(this.gitUrl)) {
return;
}
GitClient gitClient = GitUtils.newGitClient(run, listener, envVars, this.nodeName, this.workspace);

Comment on lines +610 to +611
final boolean commitInfoAlreadyCreated = commitAction != null && commitAction.getCommit() != null && commitAction.getCommit().equals(gitCommit);
final boolean repoInfoAlreadyCreated = repositoryAction != null && repositoryAction.getRepositoryURL() != null && repositoryAction.getRepositoryURL().equals(gitUrl);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There boolean conditions are duplicated here and in BuildData. It might be worth extracting to a method.

} catch (Exception e) {
LOGGER.fine("Unable to build RepositoryInfo. Error: " + e);
LOGGER.info("Unable to build RepositoryInfo. Error: " + e);
return null;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why aren't you returning RepositoryInfo.EMPTY_REPOSITORY_INFO here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

For errors, we return null to trigger again the logic in case the repository info was calculated again. By other hand, the case where we actually know that the info could be calculated but there is no valid info for us, we return the empty repository info.

Comment on lines +271 to +272
GitCommitAction gitCommitAction = run.getAction(GitCommitAction.class);
GitRepositoryAction gitRepositoryAction = run.getAction(GitRepositoryAction.class);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I understand the strategy here, but I don't understand where's the code that calls .addAction with the git client. Can you point me to that place?

@drodriguezhdez drodriguezhdez Sep 3, 2021

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Comment on lines +27 to +38
public static long currentTimeMillis() {
if(!LOGGER.isLoggable(Level.FINE)){
return -1L;
}

return System.currentTimeMillis();
}

public static void log(String msg, long start, long end) {
if(start == -1L || end == -1L){
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think the interface of this class can be improved. It's a bit weird having to rely on a wrapped version of curentTimeMillis that returns a sentinel value. What about something like this?

public class DatadogAudit {
  public static void log(String msg);
  public static DatadogAuditStopwatch startWatch();
}

public class DatadogAuditStopwatch {
  public void stop(String msg) {
        long duration = System.currentTimeMillis() - this.start;
        if(duration > 10){
            DatadogAudit.logFine(msg +" [duration: "+duration+" ms, start: " + start + ", end: " + end+"]");
        }
  }
}

Or something like this:

    public static void log(String msg, long start, long end) {
        if(!LOGGER.isLoggable(Level.FINE)){
            return;
        }
[...]

@drodriguezhdez
drodriguezhdez merged commit 76e5441 into master Sep 3, 2021
@drodriguezhdez
drodriguezhdez deleted the drodriguezhdez/fix_perf_issues branch September 3, 2021 08:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog/Fixed Fixed features results into a bug fix version bump

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants