• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ArrayBuffer Object
2
3An ArrayBuffer consists of two components: the underlying native memory area that stores data, and the JS object wrapper that encapsulates operations. This JS object wrapper is allocated on the virtual machine's local heap. When passed across threads, the JS object wrapper needs to be serialized and deserialized for pass-by-copy, whereas the native memory area can be transferred in two ways: pass-by-copy and pass-by-transfer.
4
5When pass-by-copy (recursive traversal) is used for the native memory area, both threads can independently access the ArrayBuffer object after the transmission. This transmission mode not only requires rebuilding the JS wrapper but also involves copying the native memory, resulting in lower transfer efficiency. The following figure shows the communication process.
6
7![copy_transfer](figures/copy_transfer.png)
8
9If pass-by-transfer is used for the native memory area, the original thread can no longer use the ArrayBuffer object. During inter-thread communication, only the JS wrapper needs to be reconstructed, and the native memory does not need to be copied, resulting in higher efficiency. The following figure shows the communication process.
10
11![transfer](figures/transfer.png)
12
13ArrayBuffer objects can be used to represent resources such as images. In application development, processing images (such as adjusting brightness, saturation, and size) can be time-consuming. To avoid blocking the UI main thread for extended periods, images can be passed to a child thread for processing. Passing ArrayBuffer objects by transfer results in higher transmission performance, but the original thread can no longer access the ArrayBuffer objects. If both threads need to access the objects, pass-by-copy is the only option. Otherwise, pass-by-transfer is recommended for better performance.
14
15The following sections describe how to transfer images across ArkTS threads using both methods.
16
17## Pass-by-Copy
18
19In ArkTS, TaskPool defaults to passing ArrayBuffer data by transfer. By calling the **setTransferList()** interface, you can specify which parts of the data should be passed by transfer, while the rest can be switched to pass-by-copy.
20
21First, implement an interface for processing the ArrayBuffer. The interface will be executed in the Task.
22
23Then, pass the ArrayBuffer data to the Task by copy and process it.
24
25Finally, the UI main thread receives the ArrayBuffer data returned after the Task execution and concatenates the data for display.
26
27```ts
28// Index.ets
29import { taskpool } from '@kit.ArkTS';
30import { BusinessError } from '@kit.BasicServicesKit';
31
32@Concurrent
33function adjustImageValue(arrayBuffer: ArrayBuffer): ArrayBuffer {
34  // Perform operations on the ArrayBuffer.
35  return arrayBuffer;  // The return value is passed by transfer by default.
36}
37
38function createImageTask(arrayBuffer: ArrayBuffer, isParamsByTransfer: boolean): taskpool.Task {
39  let task: taskpool.Task = new taskpool.Task(adjustImageValue, arrayBuffer);
40  if (!isParamsByTransfer) { // Whether to use pass-by-transfer.
41    // Pass an empty array [] to indicate that all ArrayBuffer parameters should be passed by copy.
42    task.setTransferList([]);
43  }
44  return task;
45}
46
47@Entry
48@Component
49struct Index {
50  @State message: string = 'Hello World';
51
52  build() {
53    RelativeContainer() {
54      Text(this.message)
55        .id('HelloWorld')
56        .fontSize(50)
57        .fontWeight(FontWeight.Bold)
58        .alignRules({
59          center: { anchor: '__container__', align: VerticalAlign.Center },
60          middle: { anchor: '__container__', align: HorizontalAlign.Center }
61        })
62        .onClick(() => {
63          let taskNum = 4;
64          let arrayBuffer = new ArrayBuffer(1024 * 1024);
65          let taskPoolGroup = new taskpool.TaskGroup();
66          // Create taskNum tasks.
67          for (let i: number = 0; i < taskNum; i++) {
68            let arrayBufferSlice: ArrayBuffer = arrayBuffer.slice(arrayBuffer.byteLength / taskNum * i, arrayBuffer.byteLength / taskNum * (i + 1));
69            // To pass the ArrayBuffer object by copy, set isParamsByTransfer to false.
70            taskPoolGroup.addTask(createImageTask(arrayBufferSlice, false));
71          }
72          // Execute the tasks.
73          taskpool.execute(taskPoolGroup).then((data) => {
74            // Concatenate the results to obtain the final result.
75          }).catch((e: BusinessError) => {
76            console.error(e.message);
77          })
78        })
79    }
80    .height('100%')
81    .width('100%')
82  }
83}
84```
85<!-- @[copy_arraybuffer_transfer](https://gitee.com/openharmony/applications_app_samples/blob/master/code/DocsSample/ArkTs/ArkTsConcurrent/ConcurrentThreadCommunication/InterThreadCommunicationObjects/CommunicationObjects/entry/src/main/ets/managers/ArrayBufferObject.ets) -->
86
87## Pass-by-Transfer
88
89TaskPool defaults to passing ArrayBuffer data by transfer, and the original thread can no longer use the ArrayBuffer passed to the child thread. To achieve this, simply remove the **task.setTransferList** interface call in the preceding code, meaning the second parameter of **createImageTask** should be **true**.
90
91<!--no_check-->