salesforce零基础学习(一百二十一)Limitation篇之Heap Size Limitation

salesforce,基础,学习,一百,二十一,limitation,heap,size · 浏览次数 : 339

小编点评

**CPU Limit** CPU limit 是 Salesforce 中用于控制对象创建和运行时间的一个限制值。在 Apex 中,`Limits.getHeapSize()` 和 `Limits.getLimitHeapSize()` 方法可用于获取当前对象的 heap size 和可使用的最大 heap size。 **Heap Size Limit** Heap size 限制了在内存中存储的最高数量,默认值为 6MB。当对象或变量创建或分配内存时,系统会给它分配内存。当内存使用超过限制时,会触发 Apex 异常。 **Best Practices** * 不要使用类级别变量去存储大量数据。 * 使用 `transient` 关键字声明变量,用于存储只用于执行代码的变量。 * 使用短的变量和 Field API 变量名称。 * 在运行时环境下,从集合中移除不必要的项来减小堆大小。 * 避免使用无效的临时变量。 * 缩短的代码并使用更短的变量名称。

正文

 本篇参考:

https://help.salesforce.com/s/articleView?id=000384468&type=1

https://help.salesforce.com/s/articleView?id=000385712&type=1

此前讲过CPU limitation:salesforce零基础学习(一百零二)Limitation篇之 CPU Limit
本篇说一下项目中也经常用到的 heap size limitation以及best practice.
首先先说一下 salesforce中的 heap size简单概念, salesforce中的heap size和java中的heap size概念基本相同,当对象或者变量创建时,就会给分配内存,当运行时基于逻辑动态分配内存。salesforce限制同步最大的 apex heap size是6MB,异步的场景最多的是12MB. 当transaction执行时,太多数据存储在内存中的情况下,可能触发 The "Apex heap size too large" 的错误。

如果去调查某一个功能逻辑的heap size情况,可以通过以下的步骤来分析:

  • 通过debug log查看当前的 heap size情况。
  • 在debug log中通过HEAP_ALLOCATE来确定对象或者变量的分配内存的情况。
  • 通过最后的Maximum heap size: 了解当前的执行的transaction所使用的heap size情况。
  • 针对heap size limit拥有两个方法可以查询:
    1. Limits.getHeapSize():返回已用于堆的大致内存量(单位为:字节)。
    2. Limits.getLimitHeapSize(): 返回堆中还可以使用的大致的内存量(单位为:字节)

Best practice
1. 不使用class级别的变量去存储大量数据(也不一定局限于 class级别的变量,list尽量别存储大量数据)
错误案例: 下面的demo中: baseList,SampleMap的value以及tempt list都指向了同一个内存地址,执行以后,这个内存地址便会超限,从而触发The "Apex heap size too large" 的limitation

String tStr = 'aaaaa bbbbb ccccc ddddd eeeeee fffff ggggg 11111 22222 33333 44444';
List<String> baseList = tStr.split(' ');
List<String> bigList = baseList;
Map<integer, List<String>> SampleMap = new Map<integer, List<String>>();
SampleMap.put(1, bigList);

for (integer i=0; i<50; i++) {
    List<String> tempList = new List<String>();
    tempList = SampleMap.get(1);
    bigList.addAll(tempList);
}
system.debug('FINAL LIST SIZE IS '+bigList.size());

简单的改动就是声明一个新的 list,避免之前的内存倍速增长。

String tStr = 'aaaaa bbbbb ccccc ddddd eeeeee fffff ggggg 11111 22222 33333 44444';
List<String> baseList = tStr.split(' ');
Map<integer, List<String>> Sample = new Map<integer, List<String>>();
List<String> bigList = baseList;

Sample.put(1, bigList);
List<string> myList = new list<string>(); //Declare a new list

for (integer i=0; i<50; i++) {
    List<String> tempList = new List<String>();
    tempList = Sample.get(1);
    system.debug('templist: ' + tempList.size());
    system.debug(' bigList: ' + bigList.size());

    myList.addall(tempList); //original code is bigList.addall(tempList);
}

system.debug('FINAL LIST SIZE OF bigList IS '+ bigList.size());
system.debug('myList IS '+mylist.size());

2. 使用SOQL for loop从大量查询的数据中迭代和处理数据,官方也介绍了很多的 SOQL for loop的demo。详情可查看:

https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_loops_for_SOQL.htm
未改进前的简单的demo如下:

List<Account> accs = [SELECT Id, Name FROM Account LIMIT 50000];

针对 heap size修改的情况下,官方给出的建议,此种情况下,每200条执行一次数据,大量的减少了 heap size的使用。

SOQL for loop通过调用SOAP API的query和queryMore方法,使用高效的分块来检索所有sObjects(每次处理200条数据)。开发人员可以通过使用SOQL for loop处理返回多条记录的查询结果来避免堆大小的限制。

for(Account a : [SELECT Id, Name FROM Account LIMIT 50000]){
//TODO custom logic
}

当然,在多租户环境下,我们的limitation也不止 heap size,上述方法是否是最优解需要具体情况具体分析。当我们使用 SOQL for loop并且数据量大的情况下,这种方法可能会导致使用更多的CPU周期,逻辑执行时间也变得多了。除了官方上面的链接介绍以外,也可以看一下下面的邱老板的demo

https://blog.keal.us/salesforce/soql-for-loop%e7%9a%84%e6%95%88%e7%8e%87%e9%97%ae%e9%a2%98/
3.
变量使用 'transient'关键字,用于声明不需要被保存的变量,并且在VF page情况下也不会计入view state

salesforce 零基础学习(四十二)简单文件上传下载

4. 在运行时环境下,通过在迭代list / set / map时从集合中移除不必要的item来减小堆大小。

除此以外的几点优化点作为参考:
1. 避免使用无效的临时变量。比如代码中的临时变量后续没有调用,造成了额外的花销,这种没有用的代码尽量删除。
2. 更短的命名以及Field api 名称: 诚然使用好的命名规范有更强的可读性,不过短的名字确实可以省一些 heap size
移除不必要的debug log语句,特别是生产环境。

总结:heap size和CPU limitation的优化相辅相成,不要为了某一个优化而特意放弃另外一个,彼此形成一下平衡。篇中有错误地方欢迎指出,有不懂欢迎留言。

与salesforce零基础学习(一百二十一)Limitation篇之Heap Size Limitation相似的内容:

salesforce零基础学习(一百二十一)Limitation篇之Heap Size Limitation

本篇参考: https://help.salesforce.com/s/articleView?id=000384468&type=1 https://help.salesforce.com/s/articleView?id=000385712&type=1 此前讲过CPU limitation:s

salesforce零基础学习(一百二十四)Postman 使用

本篇参考: Salesforce 集成篇零基础学习(一)Connected App salesforce 零基础学习(三十三)通过REST方式访问外部数据以及JAVA通过rest方式访问salesforce 我们在项目中也经常遇见下游系统去和我们进行交互的情况,针对 salesforce可以提供 标

salesforce零基础学习(一百三十一)Validation 一次的bypass设计

本篇参考: https://admin.salesforce.com/blog/2022/how-i-solved-it-bypass-validation-rules-in-flows 背景:作为系统的全局考虑,我们在设计validation rule / flow / trigger时,往往会使

salesforce零基础学习(一百二十七)Custom Metadata Type 篇二

本篇参考: salesforce零基础学习(一百一十一)custom metadata type数据获取方式更新 https://developer.salesforce.com/docs/atlas.en-us.apexref.meta/apexref/apex_methods_system_cu

salesforce零基础学习(一百二十)快去迁移你的代码中的 Alert / Confirm 以及 Prompt吧

本篇参考: https://developer.salesforce.com/blogs/2022/01/preparing-your-components-for-the-removal-of-alert-confirm-prompt https://help.salesforce.com/s/a

salesforce零基础学习(一百二十二)通过 excel / csv创建 object

本篇参考: https://help.salesforce.com/s/articleView?id=sf.dev_objectcreate_task_lex_from_spreadsheet.htm&type=5 背景:当客户给我们N个表的数据,告诉我们需要创建一些新表,然后导入这些数据的时候,我

salesforce零基础学习(一百二十三)Transaction Security 浅入浅出

本篇参考: https://help.salesforce.com/s/articleView?id=sf.enhanced_transaction_security_policy_types.htm&type=5 https://developer.salesforce.com/docs/atla

salesforce零基础学习(一百二十六) Picklist Value Set 优缺点和使用探讨

本篇参考:https://help.salesforce.com/s/articleView?id=sf.fields_creating_global_picklists.htm&type=5 当我们创建Picklist 字段时,比如很多表很多字段都会用到同样的 picklist value时,我们

salesforce零基础学习(一百二十八)Durable Id获取以及相关概念浅入浅出

本篇参考: salesforce 零基础开发入门学习(十一)sObject及Schema深入 https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_enti

salesforce零基础学习(一百二十九)Lead Conversion 有趣的经历

本篇参考:https://help.salesforce.com/s/articleView?id=000382564&type=1 Lead Conversion 是salesforce中sales cloud的一个很好用的功能。sales cloud流程可以简单的理解成 lead to cash