1. ro.config.low_ram
Android go该属性将为true,app可以通过判断这个属性确定是否为低内存设备,从而采取一些省内存的操作。
# Set lowram options and enable traced by default
PRODUCT_VENDOR_PROPERTIES += \
ro.config.low_ram=true \
系统中针对该属性的操作主要如下:
1.1 logcat
根据文件system/logging/logd/README.property,
ro.config.low_ram bool false if true, logd.statistics,
ro.logd.kernel default false,
logd.size 64K instead of 256K.
- logd.statistics为false,"logd.statistics"默认为
svelte+
,功能为Enable logcat -S statistics
,统计log信息。 - ro.logd.kernel为false,不能使用logcat看kernel的log
- 将logd的size默认改小为64K
1.2 lmkd
1.2.1 low_ram_device & per_app_memcg
在lmkd的属性处理中,当为低内存设备时,per_app_config
的默认值为true.
并影响一些lmkd的参数,可参考:
属性 | 使用 | 默认(High performance) | 默认(low ram) |
---|---|---|---|
ro.lmk.psi_partial_stall_ms | 部分 PSI 失速阈值(以毫秒为单位),用于触发内存不足通知。 | 70 | 200 |
ro.lmk.psi_complete_stall_ms | 完全 PSI 失速阈值(以毫秒为单位),用于触发critical内存通知 | 700 | 700 |
ro.lmk.thrashing_limit | 工作集 refault 数量的上限 | 100 | 30 |
ro.lmk.thrashing_limit_decay | 抖动阈值衰减 | 10 | 50 |
ro.lmk.swap_util_max | 最大交换内存量 | 100 | 100 |
ro.lmk.swap_free_low_percentage | 可用交换水平, | 20 | 10 |
下面分析下当per_app_memcg
属性为true时主要做了什么?
libprocessgroup会根据'ro.config.per_app_memcg'属性判断使用使用per-app-memcg,如果未设置该属性。在低内存设备会默认使用per-app-memcg,否则为false.然后libprocessgroup会创建相关的节点.
cmd_procprio
的主要作用是更新进程的的adj,首先通过lmkd_pack_get_procprio
将packet解释为lmk_procprio
类型的数据,该数据类型包括pid,uid以及adj,接着检查需要设置的adj是否在范围以内,最后写入到/proc/[pid]/oom_score_adj
.至此如果是使用内核逻辑的话,就会返回.否则还会进行进一步处理.
假如是low_ram_device
,还会去更新soft_limit_mult
到/dev/memcg/apps/uid_%d/pid_%d/memory.soft_limit_in_byte
.最后还会通过调用pid_lookup在哈希表中是否存在该进程,假如不存在,则将进程加入到双向链表中,否则将该进程移出,并重新加入到双向链表中的头部.
memory.soft_limit_in_byte
具体有什么用下面会继续分析
static void cmd_procprio(LMKD_CTRL_PACKET packet, int field_count, struct ucred *cred) {
......
/* lmkd should not change soft limits for services */
if (params.ptype == PROC_TYPE_APP && per_app_memcg) {
if (params.oomadj >= 900) {
soft_limit_mult = 0;
} else if (params.oomadj >= 800) {
soft_limit_mult = 0;
} else if (params.oomadj >= 700) {
soft_limit_mult = 0;
} else if (params.oomadj >= 600) {
// Launcher should be perceptible, don't kill it.
params.oomadj = 200;
soft_limit_mult = 1;
} else if (params.oomadj >= 500) {
soft_limit_mult = 0;
} else if (params.oomadj >= 400) {
soft_limit_mult = 0;
} else if (params.oomadj >= 300) {
soft_limit_mult = 1;
} else if (params.oomadj >= 200) {
soft_limit_mult = 8;
} else if (params.oomadj >= 100) {
soft_limit_mult = 10;
} else if (params.oomadj >= 0) {
soft_limit_mult = 20;
} else {
// Persistent processes will have a large
// soft limit 512MB.
soft_limit_mult = 64;
}
snprintf(path, sizeof(path), MEMCG_SYSFS_PATH
"apps/uid_%d/pid_%d/memory.soft_limit_in_bytes",
params.uid, params.pid);
snprintf(val, sizeof(val), "%d", soft_limit_mult * EIGHT_MEGA);
/*
* system_server process has no memcg under /dev/memcg/apps but should be
* registered with lmkd. This is the best way so far to identify it.
*/
is_system_server = (params.oomadj == SYSTEM_ADJ &&
(pwdrec = getpwnam("system")) != NULL &&
params.uid == pwdrec->pw_uid);
writefilestring(path, val, !is_system_server);
}
......
}
设置ro.config.per_app_memcg
属性为false,将不会使用per_app_memcg。
1.2.2 art
如果ro.config.low_ram
属性为true,此时会在虚拟机启动的时候添加LowMemoryMode参数。
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
......
property_get("ro.config.low_ram", propBuf, "");
if (strcmp(propBuf, "true") == 0) {
addOption("-XX:LowMemoryMode");
}
......
}
在下面的函数中会解析出来,如果是低内存设备,background_collector_type_
为kCollectorTypeSS。
// art/runtime/parsed_options.cc
bool ParsedOptions::DoParse(const RuntimeOptions& options,
bool ignore_unrecognized,
RuntimeArgumentMap* runtime_options) {
......
if (background_collector_type_ == gc::kCollectorTypeNone) {
background_collector_type_ = low_memory_mode_ ?
gc::kCollectorTypeSS : gc::kCollectorTypeHomogeneousSpaceCompact;
}
......
}
还有下面的影响,不太清楚
// art/runtime/runtime.cc
static constexpr double kLowMemoryMinLoadFactor = 0.5;
static constexpr double kLowMemoryMaxLoadFactor = 0.8;
static constexpr double kNormalMinLoadFactor = 0.4;
static constexpr double kNormalMaxLoadFactor = 0.7;
bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) {
float foreground_heap_growth_multiplier;
if (is_low_memory_mode_ && !runtime_options.Exists(Opt::ForegroundHeapGrowthMultiplier)) {
// If low memory mode, use 1.0 as the multiplier by default.
foreground_heap_growth_multiplier = 1.0f;
} else {
foreground_heap_growth_multiplier =
runtime_options.GetOrDefault(Opt::ForegroundHeapGrowthMultiplier) +
kExtraDefaultHeapGrowthMultiplier;
}
}
double Runtime::GetHashTableMinLoadFactor() const {
return is_low_memory_mode_ ? kLowMemoryMinLoadFactor : kNormalMinLoadFactor;
}
double Runtime::GetHashTableMaxLoadFactor() const {
return is_low_memory_mode_ ? kLowMemoryMaxLoadFactor : kNormalMaxLoadFactor;
}
2. speed-profile
# Speed profile services and wifi-service to reduce RAM and storage.
PRODUCT_SYSTEM_SERVER_COMPILER_FILTER := speed-profile
根据https://source.android.com/devices/tech/dalvik/configure
dalvik.vm.systemservercompilerfilter: the compiler filter that the device will use when recompiling system server
默认会使用speed(运行 DEX 代码验证,并对所有方法进行 AOT 编译),这里使用speed-profile(行 DEX 代码验证,并对配置文件中列出的方法进行 AOT 编译),可以节省点内存。
# build/make/core/main.mk
# Add the system server compiler filter if they are specified for the product.
ifneq (,$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER))
ADDITIONAL_PRODUCT_PROPERTIES += dalvik.vm.systemservercompilerfilter=$(PRODUCT_SYSTEM_SERVER_COMPILER_FILTER)
endif
3. PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK
总是预先选择提取的apk,以防止从gms模块的APK中提取.防止执行apk导致占用内存变多?
# Always preopt extracted APKs to prevent extracting out of the APK for gms
# modules.
PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := true
设置该属性后,my_preopt_for_extracted_apk=true,
# build/core/app_prebuilt_internal.mk
ifeq ($(PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK),true)
# If the product property is set, always preopt for extracted modules to prevent executing out of
# the APK.
my_preopt_for_extracted_apk := true
endif
# build/make/core/dex_preopt_odex_install.mk
# if WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY=true and module is not in boot class path skip
# Also preopt system server jars since selinux prevents system server from loading anything from
# /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
# or performance. If my_preopt_for_extracted_apk is true, we ignore the only preopt boot image
# options.
system_server_jars := $(foreach m,$(PRODUCT_SYSTEM_SERVER_JARS),$(call word-colon,2,$(m)))
ifneq (true,$(my_preopt_for_extracted_apk))
ifeq (true,$(WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY))
ifeq ($(filter $(system_server_jars) $(DEXPREOPT_BOOT_JARS_MODULES),$(LOCAL_MODULE)),)
LOCAL_DEX_PREOPT :=
endif
endif
endif
4. boot_image_profile
根据注释这里并没有针对Android go做特别的优化。不过如果有需要应该可以在这里做优化。
# Use a profile based boot image for this device. Note that this is currently a
# generic profile and not Android Go optimized.
PRODUCT_USE_PROFILE_FOR_BOOT_IMAGE := true
PRODUCT_DEX_PREOPT_BOOT_IMAGE_PROFILE_LOCATION := frameworks/base/config/boot-image-profile.txt
5. libartd
不生成libaard,属于节省内存的操作了,可能影响debug.
# Do not generate libartd.
PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD := false
6. in-process APK
属于省内存操作?
# Do not spin up a separate process for the network stack on go devices, use an in-process APK.
PRODUCT_PACKAGES += InProcessNetworkStack
PRODUCT_PACKAGES += CellBroadcastAppPlatform
PRODUCT_PACKAGES += CellBroadcastServiceModulePlatform
PRODUCT_PACKAGES += com.android.tethering.inprocess
7. JAVA DEBUG INFO
省内存操作,影响调试。
# Strip the local variable table and the local variable type table to reduce
# the size of the system image. This has no bearing on stack traces, but will
# leave less information available via JDWP.
PRODUCT_MINIMIZE_JAVA_DEBUG_INFO := true
8. scudo
在eng版本中不使用scudo,scudo为了安全会多使用点内存
# Disable Scudo outside of eng builds to save RAM.
ifneq (,$(filter eng, $(TARGET_BUILD_VARIANT)))
PRODUCT_DISABLE_SCUDO := true
endif
9. 一些系统属性
# 下面四个属性对使用psi策略的Android11&12是无用的
ro.lmk.critical_upgrade=true
ro.lmk.upgrade_pressure=40
ro.lmk.downgrade_pressure=60
ro.lmk.kill_heaviest_task=false
# set threshold to filter unused apps
pm.dexopt.downgrade_after_inactive_days=10
# set the compiler filter for shared apks to quicken.
# Rationale: speed has a lot of dex code expansion, it uses more ram and space
# compared to quicken. Using quicken for shared APKs on Go devices may save RAM.
# Note that this is a trade-off: here we trade clean pages for dirty pages,
# extra cpu and battery. That's because the quicken files will be jit-ed in all
# the processes that load of shared apk and the code cache is not shared.
# Some notable apps that will be affected by this are gms and chrome.
# b/65591595.
# 默认是speed
pm.dexopt.shared=quicken
# Default heap sizes. Allow up to 256m for large heaps to make sure a single app
# doesn't take all of the RAM.
# 开发板这里默认dalvik.vm.heapgrowthlimit=128m,dalvik.vm.heapsize=174m,下面俩设置似乎也没什么用
dalvik.vm.heapgrowthlimit=128m
dalvik.vm.heapsize=256m
10. handheld_core_hardware.xml
这个文件包含系统的核心硬件模块配置文件.CTS测试时会使用,Android go的这个文件内容相对少一点,对机器要求低点。
# use the go specific handheld_core_hardware.xml from frameworks
PRODUCT_COPY_FILES += \
frameworks/native/data/etc/go_handheld_core_hardware.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/handheld_core_hardware.xml
简单看了下,go_handheld_core_hardware.xml里差异如下
// go 里多的
<!-- Indicate support for the Android security model per the CDD. -->
<feature name="android.hardware.security.model.compatible" />
// go里没有
<feature name="android.software.app_widgets" />
<feature name="android.software.voice_recognizers" notLowRam="true" />
<feature name="android.software.picture_in_picture" notLowRam="true" />
<feature name="android.software.activities_on_secondary_displays" notLowRam="true" />
<feature name="android.software.managed_users" notLowRam="true"/>
11. TARGET_VNDK_USE_CORE_VARIANT
对vndk的影响,删除具有相同核心变体的重复数据删除VNDK库
# Dedupe VNDK libraries with identical core variants.
TARGET_VNDK_USE_CORE_VARIANT := true
评论 (0)