Skip to Content

Introduction

If you have been following the CRM space on SCN a little bit you might have noticed that there are quite often questions on how to create of update data using a certain function module or BAPI. Whenever these kinds of questions are asked I usually answer that in my opinion it is better to use the BOL to update or create data in CRM instead of the function modules. Also quite regularly Stephen Johannes and I disagree whether this is the right approach (cf. for example this discussion  Use CRM_ORDER_MAINTAIN FM to change CREATED_BY field into an order).

Basically Stephen argues (@Stephen: please correct me if I paraphrase your opinion incorrectly) that the function module based APIs have been around long before the BOL and that the BOL uses these function modules underneath. Consequently, the function modules should offer better performance than the BOL. Furthermore, as the function modules is the underlying API it is better to learn and use them in the first place. In contrast I usually argue that in my opinion the BOL is the cleaner API and that clean and succinct code should be a higher priority than performance in almost all scenarios.

After the last discussion I had with Stephen via private messages I decided to write a blog which tries to compare the two approaches side by side. Using two typical scenarios, the creation of business partner data and the creation of orders, this blog shows the difference in the resulting program code when using function modules in contrast to BOL. Furthermore, the performance of the two approaches in the context of a mass creation of the respective objects is compared. As a result of this blog I hope to provide a suitable basis for the decision between the different API options for different usage scenarios.

The blog is organized as follows. Firstly, a brief introduction to the function modules based APIs and the BOL, mainly providing references to existing documents, is given. Next, the mini-framework used to implement the different scenarios for performance comparison is introduced. The main part of the blog is the comparison of the business partner and order creation using function modules and BOL. The blog closes by providing a short summary of the results.

Introduction to the function module APIs and the BOL

In the context of these blog two different function module based APIs are used. To create business partner data the business partner BAPIs are used. According to the definition in the SAP Library a BAPI  is “A Business Application Programming Interface (BAPI) is a precisely defined interface providing access to processes and data in business application systems such as R/3.” While a BAPI is supposed to be a stable interface to some defined business process or data it is implemented using plain function modules. As an example consider the BAPI method ChangeAddress of the business object BusinessPartner. It is implemented by the function module BAPI_BUPA_ADDRESS_CHANGE (see screenshot of transaction BAPI below). Therefore, this blog will refer to function module based APIs to subsume BAPIs as well as function modules not available via BAPIs.


2016-01-07 13_50_33-ABAP - CFD_100_drumm_en - Eclipse.png

The nice feature of the BAPIs in contrast to some other function modules is that most of the BAPI function modules contain extensive documentation. This is quite helpful in understanding how to use them. Note also, that the BAPI are usually implemented using some internal function module. For example, the function module BAPI_BUPA_CREATE_FROM_DATA is implemented using the function module BUPA_CREATE_FROM_DATA.

The second function module based API used in this blog is CRM_ORDER_MAINTAIN. It is the function module to create and updates orders in SAP CRM. Unfortunately, it is not released for customer usage. But that usually doesn’t stop customer form using function modules ๐Ÿ˜‰ . In contrast to the  business partner BAPIs there is also no documentation available for this function module. This is most likely one of the reasons why there is such a large number of discussions on the topic in SCN. For an example of how to use CRM_ORDER_MAINTAIN see CREATE using CRM_ORDER_MAINTAIN simple example (for those new to CRM and/or ABAP) or the code examples below.

In contrast to the function module APIs the BOL is an object oriented programming and data model that “stores the data of the business objects together with a defined set of attributes and relationships during runtime of a CRM WebClient UI session.” (Business Object Layer – Web Services – SAP Library). In the BOL the relations between business objects are explicitly modelled. As an example consider the screen shot of the BP component in transaction GENIL_MODEL_BROWSER below. It shows the relation between a business partner header object and its addresses.

2016-03-04 16_43_03-_ABAP_ - CFD_100_drumm_en - Eclipse.png

The BOL programming model allows to work with all business objects in CRM using a unified API. A nice introduction if given in the following blog: http://www.abaplog.com/Icerik/27/introduction-to-bol-programming. For further details regarding the BOL programming model see How To Guide Business Object Layer Programming. The implementation of the BOL is based on existing APIs for the different business objects. The business partner BOL objects are implemented using the same function modules used to implement the business partner BAPIs. The same is true for the one order BOL objects. These are implemented using CRM_ORDER_MAINTAIN.

Note that for the purpose of this blog I omitted a discussion of the XIF interface (cf. e.g. External Data Loads for CRM 4.0 using XIF adapter | SCN). The reason is that the XIF interface is used to create BDocs CRM that are processes asynchronously. Therefore a direct comparison of the XIF interface and the other approaches would have been quite difficult.

Performance Comparison Framework

In order to compare the performance of the different programming model I created a simple performance testing framework (see UML diagram below, getting this created in SE80 would deserve a blog on it own ๐Ÿ˜ฅ ). It basically consists of two parts. A random test data generator consisting of the interface ZCD_IF_PERF_TEST_DATA_GEN and the two implementation ZCD_CL_PERFORMANCE_GEN_1O_DATA and ZCD_CL_PERFORMANCE_GEN_BP_DATA. This is used to generate random test data for the different performance tests. The second part consists of the interface ZCD_IF_PERFORMANCE_TEST and its implementations ZCD_CL_PERF_CREATE_BP_BAPI, ZCD_CL_PERF_CREATE_BP_BOL, ZCD_CL_PERF_CREATE_ORDER_BAPI and ZCD_CL_PERF_CREATE_ORDER_BOL. These are the implementation of the different test scenarios using the functions modules and the BOL respectively.

2016-02-03 21_49_41-ABAP - CFD_100_drumm_de_[CFD] UML_CLASS_DIAGRAM - Eclipse.png

In order to execute the different performance test I also implemented a small report that allows to select the different scenarios, the number of objects to create and whether or not to execute a commit after creation of an object.

2016-02-03 21_52_08-ABAP - CFD_100_drumm_de_[CFD] ZCD_BOL_PERFORMANCE - Eclipse.png

The main part of this report is shown in the following code snippet. In order to ensure that the performance measurement are not falsified by the need for compilation or uncached data a warm up is performed prior to the actual performance measurement (lines 64-68, full source code available at #10751306 – Pastie). Note, that in this warm up code single commits are executed to also ensure that the commit code and data is cached.

2016-03-07 20_44_28-ABAP - Programm ZCD_BOL_PERFORMANCE [CFD] - Aktiv, Gesperrt - CFD_100_drumm_en -.png

Scenario 1: Business Partner Creation

The first scenario to compare the performance of function module based APIs and the BOL is business partner creation. The scenario for this test is the creation of a business parter of type person with an standard address and an email as address independent communication data.

The implementation of this scenario using function module BAPI_BUPA_CREATE_FROM_DATA is given in the following code snippet (full source code available at #10751310 – Pastie).

2016-03-07 20_43_03-ABAP - Globale Klasse ZCD_CL_PERF_CREATE_BP_BAPI [CFD] - Aktiv - CFD_100_drumm_e.png

The same scenario implemented using the BOL is shown in the following snippet (#10751311 – Pastie)

2016-03-07 20_41_34-ABAP - Globale Klasse ZCD_CL_PERF_CREATE_BP_BOL [CFD] - Aktiv - CFD_100_drumm_en.png

Both implementations are similar in length. In my opinion the BOL implementation is a little cleaner as different “parts” (e.g. address, email) of the business partner are nicely separated into different objects.

In order to test this scenario the class ZCD_CL_PERFORMANCE_GEN_BP_DATA is implemented to return test data in the structure given in the below. First and last name consist of a fixed prefix concatenated with a timestamp. A random street and house number is selected in Aachen as the default address. Finally the email address is simply the concatenation of the first an last name followed by a constant.

FIRSTNAME LASTNAME CITY STREET HOUSE_NO E_MAIL
TestName201603071927261138 TestLastName20160307192726190 Aachen Wildbacher Mühle 1166 TestName201603071927261138.TestLastName20160307192726190@test.de
TestName20160307192726178 TestLastName201603071927261353 Aachen Wolfsacker 309 TestName20160307192726178.TestLastName201603071927261353@test.de

In order to compare the performance of the two APIs the following performance tests where performed:

  1. creation of 50 business partners without a commit
  2. creation of 50 business partners with a bulk commit after the creation.

Creation of 50 business partners without a commit

The results of executing the performance test without a commit a given in the following screen shots. The first screen shot shows the performance of the business partner creation using the using function module BAPI_BUPA_CREATE_FROM_DATA, the second using the BOL.The first call to ZCD_CL_PERF_CREATE_BP_BOL->ZCD_IF_PERFORMANCE_TEST~RUN in both traces is the creation of 10 business partners to warm up before the performance test, the second call is the actual performance test creating 50 business partners.

The surprising result of these test is that the BOL API is more the 5 times as fast (1.2s vs. 5.3s) as the function module based API when it comes to just creating objects in memory. I haven’t investigated the underlying reason for this behaviour yet.

2016-03-07 21_00_54-ABAP - CFD_100_drumm_en_20_30_50, 04.01.2016 ZCD_BOL_PERFORMANCE_BP_BAPI_NO_COMM.png2016-03-07 21_01_23-ABAP - CFD_100_drumm_en_20_52_52, 04.01.2016 ZCD_BOL_PERFORMANCE_BP_BOL_NO_COMMI.png

Creation of 50 business partners with a bulk commit after the creation.

The results of executing the performance test using a bulk commit is given in the following screen shots. Again, the first screen shot shows the performance of  BAPI_BUPA_CREATE_FROM_DATA, the second of the BOL. Like in the traces before the first call to ZCD_CL_PERF_CREATE_BP_BOL->ZCD_IF_PERFORMANCE_TEST~RUN in both traces is the creation of 10 business partners to warm up before the performance test, the second call is the actual performance test.

In this case the result are quite interesting. On first sight the BAPI implementation provides better performance then the BOL (10.9s vs. 12.4s). However, when viewed in detail the reason for this is that the war up phase is much faster in the BAPI compared to the BOL (2.1s vs 6.5s). In contrast the bulk creation of the 50 business partners is faster in the BOL (5.7s vs 8.6s). This again is a quite surprising result. There reason is, that in the warm up phase a single commit strategy was used (cf. previous section). It seems to be the case that the BAPI_BUPA_CREATE_FROM_DATA works very well in the single commit scenario. In contrast to that the BOL performs much better in the bulk commit scenario.

2016-03-07 21_02_17-ABAP - CFD_100_drumm_en_20_45_56, 04.01.2016 zcd_bol_performance_bp_bapi_bulk_co.png2016-03-07 21_02_55-ABAP - CFD_100_drumm_en_21_34_11, 04.01.2016 ZCD_BOL_PERFORMANCE_BP_BOL_BULK_COM.png

Scenario 2: One Order Creation

The second scenario to compare the performance of function module based APIs and the BOL is the creation of an order. The scenario for this test is the creation of an activity for a given business parter. For this activity the description, category code group and code are set.

An excerpt of the implementation of this scenario using the CRM_ORDER_MAINTAIN function module is give in the following code snippet. The actual implementation is about 150 lines of code and available at #10751374 – Pastie.2016-03-07 21_31_15-ABAP - Globale Klasse ZCD_CL_PERF_CREATE_ORDER_BAPI [CFD] - Aktiv - CFD_100_drum.png

In contrast to that the implementation of the same scenation using the BOL is very concise (available at #10751380 – Pastie).

2016-03-07 21_31_47-ABAP - Globale Klasse ZCD_CL_PERF_CREATE_ORDER_BOL [CFD] - Aktiv - CFD_100_drumm.png

It is obvious from these code snippets that the BOL API for creating orders in CRM is much easier to use. First, the code is much more readable. Only about 30 lines of code are required to create an activity using the BOL compare to 150 using the function module API. Second, the objects are again nicely structured (partner set, activity extension). Third, the is no need to fill input field tables or use magic constants.

In order to test this scenario the class ZCD_CL_PERFORMANCE_GEN_1O_DATA is implemented to return test data in the structure given in the below. The partner and process type are constants. The description consists of a fixed prefix concatenated with a timestamp. The category and code group are again constants. Finally, the code is selected at random from the code group.

PARTNER PROCESS_TYPE DESCRIPTION CATEGORY CODEGROUP CODE
11172404 ZA01 Test Activity 20160307203338.8610000815 202 ZK000007 Z005
11172404 ZA01 Test Activity 20160307203338.8610000136 202 ZK000007 Z001

In order to compare the performance of the two APIs the following performance tests where performed:

  1. creation of 50 orders without a commit
  2. creation of 50 orders with a bulk commit after the creation.

Creation of 50 orders without a commit

The results of executing the performance test without a commit a given in the following screen shots. The first screen shot shows the performance of the order creation using the using function module CRM_ORDER_MAINTAIN, the second using the BOL. As in the business partner scenario the first call to ZCD_CL_PERF_CREATE_BP_BOL->ZCD_IF_PERFORMANCE_TEST~RUN in both traces is the warm up before the performance test, the second call is the actual performance test. Again the result of this test is that the BOL API is faster hen function module based API when it comes to just creating objects in memory. However, with 14.6s vs. 13.6s the difference is not as big as in the business partner case.

2016-03-07 21_56_59-ABAP-Profiling - CFD_100_drumm_en_21_49_44, 04.01.2016 ZCD_BOL_PERFORMANCE_1O_BA.png2016-03-07 21_54_51-ABAP - CFD_100_drumm_en_21_57_55, 04.01.2016 ZCD_BOL_PERFORMANCE_1O_BOL_NO_COMMI.png

Creation of 50 orders with a bulk commit

The results of executing the performance test using a bulk commit is given in the following screen shots. Again, the first screen shot shows the performance of  CRM_ORDER_MAINTAIN, the second of the BOL. Also the first call to ZCD_CL_PERF_CREATE_BP_BOL->ZCD_IF_PERFORMANCE_TEST~RUN in both traces is the warm up before the performance test, the second call is the actual performance test.

The creation of 50 order using bulk commit is the first scenario in which the function module API (i.e. CRM_ORDER_MAINTAIN)outperforms the BOL API (13.1 vs. 14.5s).

2016-03-07 21_55_10-ABAP - CFD_100_drumm_en_21_51_21, 04.01.2016 ZCD_BOL_PERFORMANCE_1O_BAPI_BULK_CO.png2016-03-07 21_54_27-ABAP - CFD_100_drumm_en_22_02_06, 04.01.2016 ZCD_BOL_PERFORMANCE_1O_BOL_BULK_COM.png

Conclusion

So what is the conclusion of these test? First, it is save to say the the general assumption of the BOL being slower then the function module based APIs is wrong. In contrast, there are scenarios in which the BOL APIs significantly outperform the corresponding function module APIs. Second, in the scenarios in which the BOL APIs are slower, the margin is not very big. In contrast, the complexity of the code is in the case of CRM_ORDER_MAINTAIN much higher. Which also accounts to lower readability and reduce maintainability. So starting with the simpler and cleaner programming model of BOL should always be the first choice. Starting with the function module APIs is in my opinion a clear case of premature optimization. Or as Donald Knuth put it: premature optimization is the root of all evil (or at least most of it) in programming (https://en.wikiquote.org/wiki/Donald_Knuth). Third, if in the case of a data migration hundreds of thousands of objects need to be created using the XIF interface might be the better approach. The XIF interface creates BDocs. Using the standard CRM middleware features those can be processed in parallel, reprocessed and so on.

In summary, there are only very view scenarios in which using the function module based APIs make sense.

Christian

To report this post you need to login first.

10 Comments

You must be Logged on to comment or reply to a post.

  1. Luรญs Pรฉrez Grau

    Excellent job Christian, It’s true that we already have one analisys, but having another source is allways good, even better if we consider that you weren’t infuencied by the first one and both arrived to very similar conclusions.

    I agree in most of the points and I would like to add my 2 cents:

    – Huge load of data? XIF interface even better if you use SXDA and LSMW to take advantage of the parallel processing

    – WebUI development? Of course BOL programming

    – BADI enhancements? If is a badi placed on the WebClient, BOL, if is on the API level use the corresponding API, XIF only would be justified if you are using parallel updates (TRFC or QRFC)

    – Actions: I would use the APIs maybe XIF can be justified but as far as I know woulnd’t use BOL

    – Developments from scratch (none WebUI stuff)? BOL is a good option for the reasons alread state in the blog, I wouldn’t use BOL at least in one scenario, pricing conditions which is a pain as has it’s own interpretation of how model de APIs should fit in the BOL framework.

    Cheers!

    Luis

    (0) 
    1. Christian Drumm Post author

      Hi Luis,

      you are right. It is always important to use the API suitable to the layer in which you are working. It’s definitely no good idea to e.g. implement a BADI in CRM_ORDER_MAINTAIN using the BOL. Thanks for adding the clarification.

      Christian

      (0) 
  2. Stephen Johannes

    The only problem with the business partner comparison is that you are not using the SAP function module code sequence that SAP uses in implementing the BOL ๐Ÿ™‚ .  That could explain the differences.  The other issue is your sample size is too small.  N=50 is not large enough to prove or disprove exponential growth issues via actual testing.  I think if you set N at around 100K updates or more(perhaps even 1,000,000), we see the small amount of overhead that BOL introduces. 

    At the end of the day we know the BOL calls all the underlying function modules.  SAP has optimized it heavily so that overhead of the BOL does not add any unnecessary overhead.   The good news here is that if you follow either route with proper coding it should be fine.

    Yep you really need to learn what the function modules that the BOL are using, if you want to understand your SAP CRM system deeply.  BOL is a fine place to start learning and you can code against, but a deeper knowledge comes from learning the “timeless api” that has served as the foundation for SAP CRM for almost the last 15 years.

    That being said, a very nice write up and would love see your high-volume results after correcting your BP FM code ๐Ÿ™‚ .  Now I must go back outside the SAP universe again where I have been working.

    Take care,

    Stephen

    (0) 
    1. Christian Drumm Post author

      Hi Stephen,

      I agree that the results with very high volume of data might be different. I guess I’ll give it a try with 1000 BPs and orders and see what the results are. Will post them here of cause.

      What I don’t get is your comment about the wrong sequence of function module class to create a business partner. I’m only using one function module, BAPI_BUPA_CREATE_FROM_DATA, to create a BP. How could I call this in the wrong order? Or are you suggesting not to use the BAPIs but the underlying function modules?

      Christian

      (0) 
      1. Stephen Johannes

        Yes you need to code the function module identical to how SAP wrote the code beneath the BOL layer to fully understand how much, if any overhead the BOL abstraction adds to your issue.

        In addition the BAPI_BUPA_CREATE_FROM_DATA although being a public API is “heavy” which means it’s not fully optimized.  I also believe that SAP might be in the BOL layer calling some additional function modules which suppress validation calls during the update process.  I know these exist, because I had to adjust my load programs to turn off certain validations in order to improve insert performance.

        I do believe once you switch the from the BAPI to identical code that SAP uses and then switch to a larger dataset it will produce a more accurate picture of the performance results.

        Take care,

        Stephen

        (0) 
  3. Martin Steinberg

    Hi Christian,

    for a massive parallel in use mobile scenario (target scenario is about 100.000 users in parallel, not joking) we decided for building the customer APIs on top of the SAP CRM system using mainly the basic function modules and customer APIs which aren’t covered by BOL. I do not have any load information yet, but we abstracted everything using interfaces – so it would be easy to replace an implementation using FM API with a BOL access. Mainly one of our reasons to abstract everything using interfaces was also to be flexible in order to be able to test different approaches.

    In general I would also agree that there is no general “this or that direction”, my own experience says if there are a lot homegrown “APIs” available (like for Pricing, determinations and validations) then I would tend to go for FM API again.

    If just pure standard functionality is exposed then have a look at the delivered OData implementations ๐Ÿ™‚

    Great blog, by the way (this was want I wanted to say ๐Ÿ˜‰ )

    Best regards

    Martin

    (0) 
    1. Christian Drumm Post author

      Hi Martin

      for a massive parallel in use mobile scenario (target scenario is about 100.000 users in parallel, not joking) we decided for building the customer APIs on top of the SAP CRM system using mainly the basic function modules and customer APIs which aren’t covered by BOL.

      Sounds like an interesting scenario and an interesting approach.

      customer APIs which aren't covered by BOL. 

      You could still build a BOL implementation for this functionality if you decided to use the BOL approach in the future.

      Christian

      (0) 
    1. Christian Drumm Post author

      Hi Ibrahim,

      I also can’t access the pastie.org web site. It seems the service has unfortunately been discontinued. However, using the screenshots in the post you should be able to build the test functionality yourself.

      Let me know if you have any further questions.

      Christian

       

      (0) 

Leave a Reply