wu-sheng commented on a change in pull request #4220: sniffer processing 
profile task and report status and snapshot
URL: https://github.com/apache/skywalking/pull/4220#discussion_r366864228
 
 

 ##########
 File path: 
apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/profile/ProfileTaskExecutionContext.java
 ##########
 @@ -30,20 +37,101 @@
     // task data
     private final ProfileTask task;
 
-    // task real start time
-    private final long startTime;
+    // record current profiling count, use this to check has available profile 
slot
+    private final AtomicInteger currentProfilingCount = new AtomicInteger(0);
+
+    // profiling segment slot
+    private final ThreadProfiler[] profilingSegmentSlot = new 
ThreadProfiler[Config.Profile.MAX_PARALLEL];
+
+    // current profiling execution future
+    private volatile Future profilingFuture;
 
-    public ProfileTaskExecutionContext(ProfileTask task, long startTime) {
+    public ProfileTaskExecutionContext(ProfileTask task) {
         this.task = task;
-        this.startTime = startTime;
+    }
+
+    /**
+     * start profiling this task
+     * @param executorService
+     */
+    public void startProfiling(ExecutorService executorService) {
+        profilingFuture = executorService.submit(new ProfileThread(this));
+    }
+
+    /**
+     * stop profiling
+     */
+    public void stopProfiling() {
+        if (profilingFuture != null) {
+            profilingFuture.cancel(true);
+        }
+    }
+
+    /**
+     * check have available slot to profile and add it
+     * @param tracingContext
+     * @param firstSpanOPName
+     * @return
+     */
+    public boolean attemptProfiling(TracingContext tracingContext, ID 
traceSegmentId, String firstSpanOPName) {
+        // check has available slot
+        final int usingSlotCount = currentProfilingCount.get();
+        if (usingSlotCount >= Config.Profile.MAX_PARALLEL) {
+            return false;
+        }
+
+        // check first operation name matches
+        if (!Objects.equals(task.getFistSpanOPName(), firstSpanOPName)) {
+            return false;
+        }
+
+        // try to occupy slot
+        if (!currentProfilingCount.compareAndSet(usingSlotCount, 
usingSlotCount + 1)) {
+            return false;
+        }
+
+        final ThreadProfiler segmentContext = new 
ThreadProfiler(tracingContext, traceSegmentId, Thread.currentThread(), this);
+        for (int slot = 0; slot < profilingSegmentSlot.length; slot++) {
+            if (profilingSegmentSlot[slot] == null) {
+                profilingSegmentSlot[slot] = segmentContext;
+                break;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * find tracing context and clear on slot
+     *
+     * @param tracingContext
+     */
+    public void stopTracingProfile(TracingContext tracingContext) {
+        // find current tracingContext and clear it
+        boolean find = false;
+        for (int slot = 0; slot < profilingSegmentSlot.length; slot++) {
+            ThreadProfiler currentProfiler = profilingSegmentSlot[slot];
+            if (currentProfiler != null && 
currentProfiler.matches(tracingContext)) {
+                profilingSegmentSlot[slot] = null;
 
 Review comment:
   As this method could be called in another thread, you need to set the whole 
array again, and add `volatile`, read solution 2, 
https://www.javamex.com/tutorials/volatile_arrays.shtml

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to