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_r366862873
########## 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; + + // setting stop running + currentProfiler.stopProfiling(); + find = true; + break; + } + } + + // decrease profile count + if (find) { + currentProfilingCount.addAndGet(-1); Review comment: Why don't move this into L118, then you don't need `find` flag and related codes. ---------------------------------------------------------------- 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