Skip to main content

Process Modes and Performance Optimization Guide

The IMLib SDK supports both single-process and multi-process modes, with multi-process being the default. In single-process mode, the IMLib SDK runs in the same process as the app; in multi-process mode, it operates in a separate process.

Characteristics of Single-Process Mode:

  • All components reside in the same process, allowing direct object references without serialization/deserialization, which facilitates debugging and tracing.
  • No inter-process communication overhead enables direct component calls with low latency.
  • Crashes, memory leaks, and ANRs affect the entire process, and memory limits are constrained by single-process restrictions.

Characteristics of Multi-Process Mode:

  • Component calls require serialization/deserialization, resulting in higher latency and less convenient debugging/tracing.
  • Components are isolated with independent memory spaces, so crashes, memory leaks, and ANRs have localized impact.
  • Can exceed single-process memory limits and better utilize multi-core CPU resources.

Tips: Most modern mobile devices have sufficient memory allocation for typical app usage scenarios, making single-process operation generally free from memory shortage issues.

Memory Usage Comparison

MetricSingle-ProcessMulti-Process
Base MemoryLowHigh
Memory IsolationNoYes
Memory Leak ImpactGlobalLocal
Memory Limit512MB-1GBExpandable

Performance Comparison

MetricSingle-ProcessMulti-Process
Startup SpeedFastSlow
Response LatencyLowMedium
Concurrent ProcessingPoorGood
Resource UtilizationMediumHigh

Stability Comparison

MetricSingle-ProcessMulti-Process
Crash ImpactGlobalLocal (main process unaffected)
ANR ImpactGlobalLocal
Memory LeakGlobalLocal
Process RecoverySimpleComplex

SDK Limitations When App Runs in Background

Connection State Restrictions

  • Network: Background network connections may be restricted or terminated by the system.
  • Heartbeat: Heartbeat packet frequency may be throttled, potentially causing connection timeouts.
  • Reconnection: Automatic reconnection tasks may be blocked or delayed by the system.

Battery Optimization Restrictions

  • Doze Mode: Deep sleep restricts network and CPU usage.
  • App Standby: Limits background activities.

Notifications and Push

When the app moves to the background, the system initially imposes no restrictions on active Socket connections. Messages received during this period trigger RC's online notifications. Typically within 30 seconds to 2 minutes, the app becomes fully restricted (some devices immediately suspend background processes or network access, causing Sockets to disconnect abruptly). Power-intensive Socket connections and related threads are suspended until the background process is killed, after which remote push notifications take over.

In summary, three background states exist:

  1. Initial background entry (messages trigger RC online notifications).
  2. Process suspension (messages trigger offline push).
  3. Process termination (messages trigger offline push).

Solutions for Memory Leaks When Calling IM SDK Interfaces

Using static inner classes prevents external class references, while WeakReference allows garbage collection of objects after Activity destruction, avoiding memory leaks.

Sample Code

public class TestActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);

// Use WeakReference to prevent memory leaks
WeakReference<AddFriendActivity> activityRef = new WeakReference<>(this);
RongCoreClient.getInstance().getConversation(Conversation.ConversationType.PRIVATE, "TargetId", new TestConversationCallback(activityRef));
}


/**
* Static inner class callback avoids holding external class references
*/
private static class TestConversationCallback extends IRongCoreCallback.ResultCallback<Conversation> {
private final WeakReference<AddFriendActivity> activityRef;

public ConversationCallback(WeakReference<AddFriendActivity> activityRef) {
this.activityRef = activityRef;
}

@Override
public void onSuccess(Conversation conversation) {
AddFriendActivity activity = activityRef.get();
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
// Handle success callback
// Add business logic here
}
}

@Override
public void onError(IRongCoreEnum.CoreErrorCode coreErrorCode) {
AddFriendActivity activity = activityRef.get();
if (activity != null && !activity.isFinishing() && !activity.isDestroyed()) {
// Handle error callback
// Add error handling logic here
}
}
}
}