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

Phase 1 of refactoring pgo data pipeline #46638

Merged
merged 22 commits into from
Jan 13, 2021

Conversation

davidwrighton
Copy link
Member

Phase 1 of replacing existing infrastructure around handling of pgo data with more flexible schema based approach.

The schema based approach allows the JIT to define the form of data needed for instrumentation.

  • The schema associates 4 32bit integers with each data collection point (ILOffset, InstrumentationKind, Count, and Other)
    • Rich meaning is attached to InstrumentationKind, and Count
      • InstrumentationKind defines the size and layout of individual instrumentation data items
      • Count allows a single schema item to be repeated
    • ILOffset and Other are not processed in any specific way by the infrastructure

Changes part of this phase

  • PgoManager holds arbitrary amount of pgo data instead of a slab
    • Aware of collectible assemblies
    • Match with pgo data utilizes hash of IL body in addition to IL size information for greater accuracy in match
  • JIT no longer uses block count apis, and instead uses schema based apis
    • JIT now explicitly defines the shape of data collected for both basic block and type probes
    • The rest of the system handles that without deep knowledge of what those formats are
  • Text file format for pgo data updated
  • Existing IBC infrastructure adjusted to speak in terms of schema concept
  • Uncompressed and binary encoded implementation of Pgo schema handling
  • Update SuperPMI to handle new apis

Future Changes for static Pgo

  • Move Pgo type handle histogram processing into JIT
  • Extract Pgo data from process using Event infrastructure
  • Triggers for controlling Pgo data extraction
  • Instrumented Pgo processing as part of dotnet-pgo tool
  • Pgo data flow in crossgen2

Improve stable hash to match the other R2R hashes

Use method IL body hash to replace token in pgo data

Reworked data storage for pgo to allow for more efficient lookup

Checkin before rebase

Jit no longer uses block count apis
- Handle large integers correctly
@davidwrighton davidwrighton added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jan 6, 2021
Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

Overall this looks really good.

Left a few notes.

src/coreclr/jit/compiler.cpp Show resolved Hide resolved
src/coreclr/jit/flowgraph.cpp Show resolved Hide resolved
// 4. Each data entry shall be laid out without extra padding.
//
// The intention here is that it becomes possible to describe a C data structure with the alignment for ease of use with
// inst5rumentation helper functions
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// inst5rumentation helper functions
// instrumentation helper functions

return HRESULT.E_NOTIMPL;
}

// Only allocation of PGO data for the current method is supported.
Copy link
Member

Choose a reason for hiding this comment

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

We will want to support this for inlinees, eventually (#44372).

Copy link
Member Author

Choose a reason for hiding this comment

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

That limitation will remain only be for IBC style instrumentation in R2R dlls. The general purpose instrumentation support will only be present in the runtime. If we drop support for IBC style R2R instrumentation as we will likely do, this code will be removed entirely from crossgen2.

#include "shash.h"


enum class PgoInstrumentationKind
Copy link
Member

Choose a reason for hiding this comment

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

Is there some way this can be shared with the version in corjit.h?

Copy link
Member Author

Choose a reason for hiding this comment

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

My original thought was that this one would only have the minimal number of enum values describing marshalling so that it was clear that the JIT defined the meanings of stuff, but honestly, that's not a major benefit. I'll merge the two.

}

return Compiler::WALK_CONTINUE;
// Restore the stub address \on call, whether instrumenting or not.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// Restore the stub address \on call, whether instrumenting or not.
// Restore the stub address on the call, whether instrumenting or not.

@@ -270,7 +307,7 @@ void PgoManager::ReadPgoData()
return;
}

char buffer[256];
char buffer[16384];
Copy link
Member

Choose a reason for hiding this comment

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

Is there any symbolic constant we can use here?

HeaderList *currentHeaderList = m_pgoHeaders;
if (currentHeaderList != NULL)
{
if (!ComparePgoSchemaEquals(currentHeaderList->header.GetData(), currentHeaderList->header.countsOffset, pSchema, countSchemaItems))
Copy link
Member

Choose a reason for hiding this comment

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

Does this need to tie into the IL versioning scheme? I don't think the jit knows which IL version is active for a jit request, but presumably the jit interface does (or could know).

Copy link
Member Author

Choose a reason for hiding this comment

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

I wouldn't expect so. The pgo instrumentation data structures will be the same if the schema's match up, and the JIT already must tolerate data which isn't completely accurate.

Copy link
Member Author

Choose a reason for hiding this comment

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

Now, the reading side may be more interesting, but again, that gets into the question of how bad is it to present incorrectly structured data, if that's really bad we could easily add the IL code hash into the schema to allow for the JIT to check it for correctness or something.

*pBlockCounts = &s_PgoData[index + 2];
*pCount = header->recordCount - 2;
*pNumRuns = 1;
if (!ComparePgoSchemaEquals(existingData->header.GetData(), existingData->header.countsOffset, pSchema, countSchemaItems))
Copy link
Member

Choose a reason for hiding this comment

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

Ditto here, do we need to make sure we're looking at the same IL version the jit is compiling?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wouldn't expect so. The pgo instrumentation data structures will be the same if the schema's match up, and the JIT already must tolerate data which isn't completely accurate.

index += header->recordCount;
methodsChecked++;
AllocMemTracker loaderHeapAllocation;
pHeaderList = (HeaderList*)loaderHeapAllocation.Track(pMD->GetLoaderAllocator()->GetHighFrequencyHeap()->AllocMem(allocationSize));
Copy link
Member

Choose a reason for hiding this comment

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

Seems like the schema could go in the low frequency heap but maybe that's more trouble than it's worth.

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, the jit interface api allows for doing things like that (which is why the Offset field is a full size_t), but for now, it would cause problems for the superpmi implementation I've come up with, and its not super clear how valuable the high vs low frequency heap actually is.

Copy link
Member

@AndyAyersMS AndyAyersMS left a comment

Choose a reason for hiding this comment

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

Thanks for the updates.

The code in zapinfo still looks wrong to me, it won't build a proper schema.

Would be good to run the jit-experimental CI leg, and maybe also a jitstress leg.

src/coreclr/jit/compiler.cpp Show resolved Hide resolved
@davidwrighton
Copy link
Member Author

@AndyAyersMS I've fixed the ZapInfo issues, and verified that traditional IBC continues to work. I've also scheduled the jit-experimental and jitstress runs as requested.

@AndyAyersMS
Copy link
Member

In case you haven't yet looked at the experimental failures -- they seem to be related.

@davidwrighton davidwrighton merged commit 6ded57b into dotnet:master Jan 13, 2021
@BruceForstall
Copy link
Member

@davidwrighton You didn't update the JIT-EE GUID with this. Can you please follow-up with a GUID change ASAP?

@ghost ghost locked as resolved and limited conversation to collaborators Feb 13, 2021
@davidwrighton davidwrighton deleted the pgo_prototype branch April 20, 2021 17:45
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI area-crossgen2-coreclr
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants