Пример #1
0
        // Burst/Thread safe
        internal static unsafe string MarkerGetStringName(IntPtr markerPtr)
        {
            MarkerBucketNode *marker = (MarkerBucketNode *)markerPtr;
            int   charCount          = UTF8.GetCharCount(marker->nameUtf8, marker->nameBytes);
            char *chars = stackalloc char[charCount];

            UTF8.GetChars(marker->nameUtf8, marker->nameBytes, chars, charCount);
            return(new string(chars, 0, charCount));
        }
Пример #2
0
            internal MarkerBucketNode *next;  // offset 120

            internal static unsafe bool SearchFor(MarkerBucketNode *startNode, byte *nameUtf8, int nameBytes, ref MarkerBucketNode *bucketNode)
            {
                MarkerBucketNode *prev = startNode;

                while (startNode != null)
                {
                    if (startNode->nameBytes == nameBytes)
                    {
                        if (UnsafeUtility.MemCmp(nameUtf8, startNode->nameUtf8, nameBytes) == 0)
                        {
                            bucketNode = startNode;
                            return(true);
                        }
                    }

                    prev      = startNode;
                    startNode = startNode->next;
                }

                bucketNode = prev;
                return(false);
            }
Пример #3
0
        // Burst/thread safe
        internal static unsafe void *MarkerGetOrCreate(ushort categoryId, byte *name, int nameBytes, ushort flags)
        {
            if (nameBytes <= 0)
            {
                return(null);
            }

            MarkerBucketNode *marker = null;
            int bucket = (((nameBytes << 5) + (nameBytes >> 2)) ^ name[0]) & 255;

            if (markerHashTableHead != null)
            {
                // No need for locking yet - read operations on hash table are thread safe as long as we are careful about
                // modification during write and only allow one thread to write at a time.
                if (MarkerBucketNode.SearchFor(&markerHashTableHead->MarkersBuffer[bucket], name, nameBytes, ref marker))
                {
                    return(marker);
                }
            }

            // The marker didn't exist in hash table. Need to lock so only one thread can modify at a time.
            // This path will usually only be taken during startup - after which markers should be found in the
            // above loop instead of needing to be created. Even this is a worse-case scenario because correct ProfilerMarker
            // usage will create/get them once, and they will exist as an instance which only calls MarkerBegin() and MarkerEnd()
            // when needed.
            PlayerConnectionMt_LockProfilerHashTables();

            if (marker == null)
            {
                if (markerHashTableHead == null)
                {
                    markerHashTableHead = FastHashTableBufferNode.Allocate(sizeof(MarkerBucketNode));
                    markerHashTableTail = markerHashTableHead;
                }

                marker = &markerHashTableHead->MarkersBuffer[bucket];
            }

            // In case this bucket was added to while another thread had the lock, the end-of-bucket
            // pointer needs to be increased. Also, it's possible the same exact name appears now.
            if (MarkerBucketNode.SearchFor(marker, name, nameBytes, ref marker))
            {
                PlayerConnectionMt_UnlockProfilerHashTables();
                return(marker);
            }

            MarkerBucketNode *oldMarker = null;

            if (marker->nameBytes > 0)
            {
                // There is already a valid marker here at the end of the linked list - add a new one
                markerHashTableTail = markerHashTableTail->ExtendPoolIfFull(sizeof(MarkerBucketNode));

                MarkerBucketNode *newMarker = &markerHashTableTail->MarkersBuffer[markerHashTableTail->size];
                markerHashTableTail->size++;
                oldMarker = marker;
                marker    = newMarker;
            }

            marker->init       = false;
            marker->categoryId = categoryId;
            marker->flags      = flags;
            marker->markerId   = nextMarkerId++;
            marker->nameBytes  = nameBytes;

            // Todo: When Burst printing works we should warn the user if a name is too long and will be truncated
            UnsafeUtility.MemCpy(marker->nameUtf8, name, Math.Min(nameBytes, k_MaxMarkerNameLength));

            // Do this last so if we find the node before locking, we don't have access to it unless it is otherwise fully assigned
            if (oldMarker != null)
            {
                oldMarker->next = marker;
            }

            PlayerConnectionMt_UnlockProfilerHashTables();

            NeedsUpdate = true;

            return(marker);
        }
Пример #4
0
        // Burst/Thread safe
        internal static unsafe void MarkerEnd(void *markerPtr)
        {
            MarkerBucketNode *marker = (MarkerBucketNode *)markerPtr;

            ProfilerProtocolThread.SendEndSample(marker->markerId, GetProfilerTime());
        }
Пример #5
0
        // Burst/Thread safe
        internal static unsafe void MarkerBegin(void *markerPtr, void *metadata, int metadataBytes)
        {
            MarkerBucketNode *marker = (MarkerBucketNode *)markerPtr;

            ProfilerProtocolThread.SendBeginSample(marker->markerId, GetProfilerTime());
        }