-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Factor out object converter from event buffer
- Loading branch information
Showing
6 changed files
with
170 additions
and
130 deletions.
There are no files selected for viewing
77 changes: 77 additions & 0 deletions
77
ulyp-agent-core/src/main/java/com/ulyp/agent/ByTypeRecordedObjectConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package com.ulyp.agent; | ||
|
||
import com.ulyp.core.Type; | ||
import com.ulyp.core.TypeResolver; | ||
import com.ulyp.core.bytes.BufferBytesOut; | ||
import com.ulyp.core.recorders.*; | ||
import com.ulyp.core.util.LoggingSettings; | ||
import com.ulyp.core.util.SystemPropertyUtil; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.agrona.concurrent.UnsafeBuffer; | ||
|
||
|
||
@Slf4j | ||
public class ByTypeRecordedObjectConverter implements RecordedObjectConverter { | ||
|
||
private static final int TMP_BUFFER_SIZE = SystemPropertyUtil.getInt("ulyp.recording.tmp-buffer.size", 16 * 1024); | ||
|
||
private final TypeResolver typeResolver; | ||
private byte[] tmpBuffer; | ||
|
||
public ByTypeRecordedObjectConverter(TypeResolver typeResolver) { | ||
this.typeResolver = typeResolver; | ||
} | ||
|
||
@Override | ||
public Object[] prepare(Object[] args) { | ||
if (args == null) { | ||
return null; | ||
} | ||
for (int i = 0; i < args.length; i++) { | ||
args[i] = prepare(args[i]); | ||
} | ||
return args; | ||
} | ||
|
||
/** | ||
* Resolves type for an object, then checks if it can be recorded asynchronously in a background thread. Most objects | ||
* have only their identity hash code and type id recorded, so it can be safely done concurrently in some other thread. | ||
* Collections have a few of their items recorded (if enabled), so the recording must happen here. | ||
*/ | ||
public Object prepare(Object value) { | ||
if (value == null) { | ||
return null; | ||
} | ||
Type type = typeResolver.get(value); | ||
ObjectRecorder recorder = type.getRecorderHint(); | ||
if (recorder == null) { | ||
recorder = RecorderChooser.getInstance().chooseForType(value.getClass()); | ||
type.setRecorderHint(recorder); | ||
} | ||
if (recorder.supportsAsyncRecording()) { | ||
if (recorder instanceof IdentityRecorder) { | ||
return new QueuedIdentityObject(type.getId(), value); | ||
} else { | ||
return value; | ||
} | ||
} else { | ||
BufferBytesOut output = new BufferBytesOut(new UnsafeBuffer(getTmpBuffer())); | ||
try { | ||
recorder.write(value, output, typeResolver); | ||
return new QueuedRecordedObject(type, recorder.getId(), output.copy()); | ||
} catch (Exception e) { | ||
if (LoggingSettings.DEBUG_ENABLED) { | ||
log.debug("Error while recording object", e); | ||
} | ||
return new QueuedIdentityObject(type.getId(), value); | ||
} | ||
} | ||
} | ||
|
||
private byte[] getTmpBuffer() { | ||
if (tmpBuffer == null) { | ||
tmpBuffer = new byte[TMP_BUFFER_SIZE]; | ||
} | ||
return tmpBuffer; | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
ulyp-agent-core/src/main/java/com/ulyp/agent/PassByRefRecordedObjectConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.ulyp.agent; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* Passes all objects to the background thread by reference. Can only be enabled if collections and arrays recording | ||
* is turned off. | ||
*/ | ||
@Slf4j | ||
public class PassByRefRecordedObjectConverter implements RecordedObjectConverter { | ||
|
||
public static final RecordedObjectConverter INSTANCE = new PassByRefRecordedObjectConverter(); | ||
|
||
public Object prepare(Object arg) { | ||
return arg; | ||
} | ||
|
||
public Object[] prepare(Object[] args) { | ||
return args; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
ulyp-agent-core/src/main/java/com/ulyp/agent/RecordedObjectConverter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package com.ulyp.agent; | ||
|
||
/** | ||
* Prepares (and possibly converts) object for sending to the background thread. The background thread does actual recording using the recorders. | ||
* Most of the time we just pass reference to an object to the background thread which calls recorders. This allows us to | ||
* offload some work from the client app threads to the background thread. | ||
* This works since most objects are either: | ||
* 1) immutable | ||
* 2) we only record their type id and identity hash code. | ||
* So, we can record their values (i.e. access their fields) in some other threads. | ||
* All other objects like collections and arrays must be recorded immediately in the client app thread. | ||
*/ | ||
public interface RecordedObjectConverter { | ||
|
||
Object prepare(Object arg); | ||
|
||
Object[] prepare(Object[] args); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.