--- /dev/null
+* @ws77-cho @leee-lee @dheon-jung @j-h-choi
--- /dev/null
+[profile.Tizen-Unified]
+repos = repo.Unified_base, repo.Unified_main
+buildroot = .GBS-ROOT/launcher-Unified
+
+[profile.Tizen-Unified-X]
+repos = repo.Unified_x_base, repo.Unified_x_main
+buildroot = .GBS-ROOT/launcher-Unified-X
+
+[profile.VD-PontusM]
+repos = repo.VD_base, repo.VD_PontusM_main
+buildroot = .GBS-ROOT/launcher-PontusM
+
+[profile.VD-KantSU2e]
+repos = repo.VD_base, repo.VD_KantSU2e_main
+buildroot = .GBS-ROOT/launcher-KantSU2e
+
+[profile.da]
+repos = repo.DA_base, repo.DA_main
+
+
+[repo.Unified_base]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Base/latest/repos/standard/packages/
+[repo.Unified_main]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Unified/latest/repos/standard/packages/
+
+[repo.Unified_x_base]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Base-X/latest/repos/standard/packages/
+[repo.Unified_x_main]
+url = http://download.tizen.org/snapshots/TIZEN/Tizen/Tizen-Unified-X/latest/repos/standard/packages/
+
+[repo.VD_base]
+url = http://168.219.244.109/base/current/standard/latest/repos/base/armv7l/packages/
+[repo.VD_PontusM_main]
+url = http://168.219.244.109/products/tv/official/2025/ONEMAIN/PontusM_ATSC/latest/repos/product/armv7l/packages/
+[repo.VD_KantSU2e_main]
+url = http://168.219.244.109/products/tv/official/2025/ONEMAIN/KantSU2e_ATSC/latest/repos/product/armv7l/packages/
+
+[repo.DA_base]
+url = http://10.113.136.26/snapshots/DA/Tizen-7.0/Tizen-7.0-DA-Base/latest/repos/standard/packages/
+[repo.DA_main]
+url = http://10.113.136.26/snapshots/DA/Tizen-7.0/Tizen-7.0-DA-Unified/latest/repos/MESON64/packages/
+
--- /dev/null
+name: "GBS build"
+
+on:
+ pull_request_target:
+ branches:
+ - tizen
+
+jobs:
+ Tizen_Unified_armv7l_GBS_Build:
+ runs-on: [ code-linux, code-large ]
+ container:
+ image: actions-docker.bart.sec.samsung.net/docker-gbs-base:ubuntu-20.04
+ options: --user root --privileged
+ steps:
+ - name: Setup .NET
+ uses: code-actions/setup-dotnet@v1
+ with:
+ dotnet-version: '6.0.310'
+
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Build
+ run: |
+ gbs -c .github/gbs.conf build -A armv7l --include-all --clean -P Tizen-Unified
+ if: success()
+
+ - name: Upload artifacts
+ uses: code-actions/upload-artifact@v3
+ with:
+ name: launcher-rpm-Tizen-Unified-armv7l
+ path: .GBS-ROOT/launcher-Unified/local/repos/Tizen_Unified/armv7l/RPMS/*.rpm
+ if: success()
+
+ - name: Leave comment
+ if: failure()
+ uses: code-actions/github-script@v5
+ with:
+ script: |
+ github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: 'Please check the build status of Tizen_Unified_armv7l.'
+ })
+
+ Tizen_Unified_X_armv7l_GBS_Build:
+ runs-on: [ code-linux, code-large ]
+ container:
+ image: actions-docker.bart.sec.samsung.net/docker-gbs-base:ubuntu-20.04
+ options: --user root --privileged
+ steps:
+ - name: Setup .NET
+ uses: code-actions/setup-dotnet@v1
+ with:
+ dotnet-version: '6.0.310'
+
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Build
+ run: |
+ gbs -c .github/gbs.conf build -A armv7l --include-all --clean -P Tizen-Unified-X
+ if: success()
+
+ - name: Upload artifacts
+ uses: code-actions/upload-artifact@v3
+ with:
+ name: launcher-rpm-Tizen-Unified-X-RPI4-armv7l
+ path: .GBS-ROOT/launcher-Unified-X/local/repos/Tizen_Unified_X/armv7l/RPMS/*.rpm
+ if: success()
+
+ - name: Leave comment
+ if: failure()
+ uses: code-actions/github-script@v5
+ with:
+ script: |
+ github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: 'Please check the build status of Tizen_Unified_X_armv7l.'
+ })
+
+ Tizen_Unified_X_riscv64_GBS_Build:
+ runs-on: [ code-linux, code-large ]
+ container:
+ image: actions-docker.bart.sec.samsung.net/docker-gbs-base:ubuntu-20.04
+ options: --user root --privileged
+ steps:
+ - name: Setup .NET
+ uses: code-actions/setup-dotnet@v1
+ with:
+ dotnet-version: '6.0.310'
+
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Build
+ run: |
+ gbs -c .github/gbs.conf build -A riscv64 --include-all --clean -P Tizen-Unified-X
+ if: success()
+
+ - name: Upload artifacts
+ uses: code-actions/upload-artifact@v3
+ with:
+ name: launcher-rpm-Tizen-Unified-X-VF2-riscv64
+ path: .GBS-ROOT/launcher-Unified-X/local/repos/Tizen_Unified_X/riscv64/RPMS/*.rpm
+ if: success()
+
+ - name: Leave comment
+ if: failure()
+ uses: code-actions/github-script@v5
+ with:
+ script: |
+ github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: 'Please check the build status of Tizen_Unified_X_riscv64.'
+ })
+
+# VD_PontusM_armv7l_GBS_Build:
+# runs-on: [ code-linux, code-large ]
+# container:
+# image: actions-docker.bart.sec.samsung.net/docker-gbs-base:ubuntu-20.04
+# options: --user root --privileged
+# steps:
+# - name: Setup .NET
+# uses: code-actions/setup-dotnet@v1
+# with:
+# dotnet-version: '6.0.310'
+
+# - name: Checkout
+# uses: code-actions/checkout@v3
+# with:
+# ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+# - name: Build
+# run: |
+# gbs -c .github/gbs.conf build -A armv7l --include-all --clean -P VD-PontusM
+# if: success()
+
+# - name: Upload artifacts
+# uses: code-actions/upload-artifact@v3
+# with:
+# name: launcher-rpm-VD-PontusM-armv7l
+# path: .GBS-ROOT/launcher-PontusM/local/repos/VD_PontusM/armv7l/RPMS/*.rpm
+# if: success()
+
+# - name: Leave comment
+# if: failure()
+# uses: code-actions/github-script@v5
+# with:
+# script: |
+# github.rest.issues.createComment({
+# owner: context.repo.owner,
+# repo: context.repo.repo,
+# issue_number: context.issue.number,
+# body: 'Please check the build status of VD_PontusM_armv7l.'
+# })
+
+# VD_KantSU2e_armv7l_GBS_build:
+# runs-on: [ code-linux, code-large ]
+# container:
+# image: actions-docker.bart.sec.samsung.net/docker-gbs-base:ubuntu-20.04
+# options: --user root --privileged
+# steps:
+# - name: Setup .NET
+# uses: code-actions/setup-dotnet@v1
+# with:
+# dotnet-version: '6.0.310'
+
+# - name: Checkout
+# uses: code-actions/checkout@v3
+# with:
+# ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+# - name: Build
+# run: |
+# gbs -c .github/gbs.conf build -A armv7l --include-all -P VD-KantSU2e
+# if: success()
+
+# - name: Upload artifacts
+# uses: code-actions/upload-artifact@v3
+# with:
+# name: launcher-rpm-VD-KantSU2e-armv7l
+# path: .GBS-ROOT/launcher-KantSU2e/local/repos/VD_KantSU2e/armv7l/RPMS/*.rpm
+# if: success()
+
+# - name: Leave comment
+# if: failure()
+# uses: code-actions/github-script@v5
+# with:
+# script: |
+# github.rest.issues.createComment({
+# owner: context.repo.owner,
+# repo: context.repo.repo,
+# issue_number: context.issue.number,
+# body: 'Please check the build status of VD_KantSU2e_armv7l.'
+# })
--- /dev/null
+name: "Launcher Action"
+
+on:
+ pull_request_target:
+ branches:
+ - tizen
+
+jobs:
+ Tizen_RPI4_Flash:
+ runs-on: [ self-hosted ]
+ steps:
+ - name: RPI4_Flash
+ shell: bash
+ run: |
+ dude download -k > ./dude.log
+ sleep 60
+ sdb devices
+ if: success()
+
+ Tizen_Unified_armv7l_GBS_Build:
+ runs-on: [ code-linux, code-large ]
+ container:
+ image: actions-docker.bart.sec.samsung.net/docker-gbs-base:ubuntu-20.04
+ options: --user root --privileged
+ steps:
+ - name: Setup .NET
+ uses: code-actions/setup-dotnet@v1
+ with:
+ dotnet-version: '6.0.310'
+
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Build
+ run: |
+ gbs -c .github/gbs.conf build -A armv7l --include-all --clean -P Tizen-Unified
+ if: success()
+
+ - name: Upload artifacts
+ uses: code-actions/upload-artifact@v3
+ with:
+ name: launcher-rpm-Tizen-Unified-armv7l
+ path: .GBS-ROOT/launcher-Unified/local/repos/Tizen_Unified/armv7l/RPMS/*.rpm
+ if: success()
+
+ - name: Leave comment
+ if: failure()
+ uses: code-actions/github-script@v5
+ with:
+ script: |
+ github.rest.issues.createComment({
+ owner: context.repo.owner,
+ repo: context.repo.repo,
+ issue_number: context.issue.number,
+ body: 'Please check the build status of Tizen_Unified_armv7l.'
+ })
+
+ Tizen_Unified_launcher_performance:
+ runs-on: [ self-hosted ]
+ needs: [Tizen_RPI4_Flash, Tizen_Unified_armv7l_GBS_Build]
+ steps:
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Connect RPI4
+ shell: bash
+ run: |
+ sdb devices
+ sdb -d root on
+ sdb -d shell mount -o remount,rw /
+ sdb -d shell osu --resize
+ echo "device 10000000d15e1aff is ready."
+ if: success()
+
+ - name: Download artifacts
+ uses: code-actions/download-artifact@v3
+ with:
+ name: launcher-rpm-Tizen-Unified-armv7l
+ path: ./
+ if: success()
+
+ - name: Install App
+ shell: bash
+ run: |
+ sdb -d install ./tests/Performance/org.tizen.example.AppCommon.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.ApplicationControl.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.Puzzle.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.Settings.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.System_info.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.Xamarin.Hello.F_HUB.Tizen-1.0.0.tpk
+ if: success()
+
+ - name: Run Performance Before PR
+ shell: bash
+ run: |
+ ./tests/Performance/measure -o ./tests/Performance/result_before.log
+ if: success()
+
+ - name: Install RPM
+ shell: bash
+ run: |
+ ls ./
+ sdb -d shell rm /root/dotnet-launcher-*.rpm
+ sdb -d push ./dotnet-launcher-[0-9]*.armv7l.rpm /root
+ sdb -d shell rpm -Uvh --force /root/dotnet-launcher-[0-9]*.armv7l.rpm
+ sdb -d shell "setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet && setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-loader && setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-launcher && setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-hydra-loader"
+ sdb -d shell "killall -9 dotnet-loader"
+ sleep 30
+ if: success()
+
+ - name: Install App
+ shell: bash
+ run: |
+ sdb -d install ./tests/Performance/org.tizen.example.AppCommon.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.ApplicationControl.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.Puzzle.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.Settings.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.System_info.Tizen.Mobile-1.0.0.tpk
+ sdb -d install ./tests/Performance/org.tizen.example.Xamarin.Hello.F_HUB.Tizen-1.0.0.tpk
+ if: success()
+
+ - name: Run Performance After PR
+ shell: bash
+ run: |
+ ./tests/Performance/measure -o ./tests/Performance/result_after.log
+ if: success()
+
+ - name: Compare Performance
+ shell: bash
+ run: |
+ echo "### Before Performance Result ###" > ./tests/Performance/result.log
+ ./tests/Performance/measure -f ./tests/Performance/result_before.log >> ./tests/Performance/result.log
+ echo -e "\n### After Performance Result ###" >> ./tests/Performance/result.log
+ ./tests/Performance/measure -f ./tests/Performance/result_after.log >> ./tests/Performance/result.log
+ echo -e "\n### Compare Performance Result ###" >> ./tests/Performance/result.log
+ ./tests/Performance/measure --compare ./tests/Performance/result_before.log ./tests/Performance/result_after.log >> ./tests/Performance/result.log
+ if: success()
+
+ - name: Result Performance
+ shell: bash
+ run: |
+ cat ./tests/Performance/result.log
+ sed -i '1s/^/\`\`\`\n/' ./tests/Performance/result.log
+ echo -e "\n" >> ./tests/Performance/result.log
+ sdb -d shell "cat /etc/info.ini" >> ./tests/Performance/result.log
+ echo "\`\`\`" >> ./tests/Performance/result.log
+ if: success()
+
+ - name: Comment Result
+ run: |
+ ./scripts/github-comment.sh ${{github.event.pull_request.number}} ./tests/Performance/result.log
+ if: success()
+
+ Tizen_Unified_launcher_tc:
+ runs-on: [ self-hosted ]
+ needs: Tizen_Unified_launcher_performance
+ steps:
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Build TC
+ shell: bash
+ run: |
+ ./tests/Apps/BuildTPK.py
+ if: success()
+
+ - name: Connect RPI4
+ shell: bash
+ run: |
+ sdb devices
+ sdb -d root on
+ sdb -d shell mount -o remount,rw /
+ sdb -d shell osu --resize
+ echo "device 10000000d15e1aff is ready."
+ if: success()
+
+ - name: Download artifacts
+ uses: code-actions/download-artifact@v3
+ with:
+ name: launcher-rpm-Tizen-Unified-armv7l
+ path: ./
+ if: success()
+
+ - name: Install RPM
+ shell: bash
+ run: |
+ ls ./
+ sdb -d shell rm /root/dotnet-launcher-*.rpm
+ sdb -d push ./dotnet-launcher-[0-9]*.armv7l.rpm /root
+ sdb -d shell rpm -Uvh --force /root/dotnet-launcher-[0-9]*.armv7l.rpm
+ sdb -d shell "setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet && setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-loader && setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-launcher && setcap cap_setgid,cap_sys_admin+ei /usr/bin/dotnet-hydra-loader"
+ sdb -d shell "killall -9 dotnet-loader"
+ sdb -d shell "cat /etc/info.ini" >> ./tests/TCs/device.info
+ sleep 30
+ if: success()
+
+ - name: Run TC
+ shell: bash
+ run: |
+ ./tests/TCs/ALL.py
+ if: success()
+
+ - name: Result TC
+ shell: bash
+ run: |
+ cat ./tests/TCs/result.log
+ sed -i '1s/^/\`\`\`\n/' ./tests/TCs/result.log
+ echo -e "\n" >> ./tests/TCs/result.log
+ cat ./tests/TCs/device.info >> ./tests/TCs/result.log
+ echo "\`\`\`" >> ./tests/TCs/result.log
+ if: success()
+
+ - name: Comment Result
+ run: |
+ ./scripts/github-comment.sh ${{github.event.pull_request.number}} ./tests/TCs/result.log
+ if: success()
+
+ Tizen_Dotnet_Benchmark:
+ runs-on: [ self-hosted ]
+ needs: Tizen_Unified_launcher_tc
+ steps:
+ - name: Checkout
+ uses: code-actions/checkout@v3
+ with:
+ ref: refs/pull/${{ github.event.pull_request.number }}/head
+
+ - name: Connect RPI4
+ shell: bash
+ run: |
+ sleep 60
+ sdb devices
+ sdb -d root on
+ sdb -d shell mount -o remount,rw /
+ echo "device 10000000d15e1aff is ready."
+ if: success()
+
+ - name: Install App
+ shell: bash
+ run: |
+ sdb -d install ./tests/Benchmark/org.tizen.dotnet.TizenBenchmark-1.0.0.tpk
+ if: success()
+
+ - name: Run Benchmark
+ shell: bash
+ run: |
+ sdb -d shell "rm /tmp/BenchmarkDotnet/*.log"
+ sdb -d shell "app_launcher -k org.tizen.dotnet.TizenBenchmark"
+ sdb -d shell "app_launcher -s org.tizen.dotnet.TizenBenchmark"
+ if: success()
+
+ - name: Print&Pull Log
+ shell: bash
+ run: |
+ sdb shell "dlogutil -c"
+ sdb shell "dlogutil -v time STDOUT" > stdout.log &
+ DLOG_STREAMER_PID=$!
+ echo $DLOG_STREAMER_PID
+ while inotifywait -qqre modify stdout.log;
+ do
+ GET_LOG="$(tail -1 stdout.log)"
+ echo $GET_LOG
+ if [[ $GET_LOG =~ "##### Tizen.NET Benchmark END #####" ]]; then
+ sdb -d pull /tmp/BenchmarkDotnet ./tests/Benchmark/
+ kill -9 $DLOG_STREAMER_PID > /dev/null 2>&1
+ break
+ fi
+ done
+ if: success()
+
+ - name: Result Benchmark
+ run: |
+ echo "\`\`\`" > ./tests/Benchmark/benchmark.result
+ for file in ./tests/Benchmark/*.log; do if [[ $file =~ "BenchmarkRun-" ]]; then continue; fi; echo $file; sed -n '/ Summary /,/ Legends /p' $file | grep -v '*'; done >> ./tests/Benchmark/benchmark.result
+ echo -e "\n" >> ./tests/Benchmark/benchmark.result
+ sdb -d shell "cat /etc/info.ini" >> ./tests/Benchmark/benchmark.result
+ echo "\`\`\`" >> ./tests/Benchmark/benchmark.result
+ cat ./tests/Benchmark/benchmark.result
+ if: success()
+
+ - name: Comment Result
+ run: |
+ ./scripts/github-comment.sh ${{github.event.pull_request.number}} ./tests/Benchmark/benchmark.result
+ if: success()
+
.vs/
[Bb]in/
[Oo]bj/
-
+.vscode/
SET(EXTRA_CFLAGS_COMMON "${EXTRA_CFLAGS_COMMON} -DREAD_ONLY_APP_UPDATE_DIR=${READ_ONLY_APP_UPDATE_DIR}")
ENDIF(DEFINED READ_ONLY_APP_UPDATE_DIR)
+IF(DEFINED READ_ONLY_TAC_DIR)
+ SET(EXTRA_CFLAGS_COMMON "${EXTRA_CFLAGS_COMMON} -DREAD_ONLY_TAC_DIR=${READ_ONLY_TAC_DIR}")
+ENDIF(DEFINED READ_ONLY_TAC_DIR)
+
IF(DEFINED USE_DEFAULT_BASE_ADDR)
SET(EXTRA_CFLAGS_COMMON "${EXTRA_CFLAGS_COMMON} -DUSE_DEFAULT_BASE_ADDR")
ENDIF(DEFINED USE_DEFAULT_BASE_ADDR)
DEFAULT_OPT --
DEFAULT_OPT /home/owner/share/tmp/sdk_tools/netcoredbg/netcoredbg
EXTRA_KEY __DLP_DEBUG_ARG__
+
+[DEBUGGER]
+NAME MEMORYPROFILER
+EXE /home/owner/share/tmp/sdk_tools/profiler/profctl/profctl
+APP_TYPE dotnet|dotnet-nui
+DEFAULT_OPT -v
+DEFAULT_OPT -f
+DEFAULT_OPT -p
+DEFAULT_OPT /home/owner/share/tmp/sdk_tools/profiler/heaptrack/heaptrack_fifo
+DEFAULT_OPT -w
+DEFAULT_OPT -e
+DEFAULT_OPT /home/owner/share/tmp/sdk_tools/profiler/heaptrack/heaptrack_interpret
+DEFAULT_OPT -o
+DEFAULT_OPT /home/owner/share/tmp/sdk_tools/profiler/profctl/profctl_heaptrack.log
+DEFAULT_OPT -E
+DEFAULT_OPT DUMP_HEAPTRACK_OUTPUT=/home/owner/share/tmp/sdk_tools/profiler/heaptrack/heaptrack_fifo
+DEFAULT_OPT CORECLR_PROFILER={C7BAD323-25F0-4C0B-B354-566390B215CA}
+DEFAULT_OPT CORECLR_PROFILER_PATH=/home/owner/share/tmp/sdk_tools/profiler/heaptrack/libprofiler.so
+DEFAULT_OPT PROF_CONFIG_FILENAME=/home/owner/share/tmp/sdk_tools/profiler/heaptrack/profiler.config
+DEFAULT_OPT CORECLR_ENABLE_PROFILING=1
+DEFAULT_OPT COMPlus_LogEnable=1
+DEFAULT_OPT UNW_ARM_UNWIND_METHOD=4
+DEFAULT_OPT HEAPTRACK_NATIVE_ENABLE=1
+DEFAULT_OPT -c
+DEFAULT_OPT 6005
+DEFAULT_OPT -d
+DEFAULT_OPT 6006
+DEFAULT_OPT --
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_type != DT_DIR) {
// Make sure that the file name follows naming conventions.
- if (dp->d_name &&
- isdigit(dp->d_name[0]) &&
+ if (isdigit(dp->d_name[0]) &&
isdigit(dp->d_name[1]) &&
(dp->d_name[2] == '.')) {
preloadFiles.insert(preloadDir + dp->d_name);
#define APP_NI_SUB_TMP_DIR ".native_image_tmp"
#define TAC_SYMLINK_SUB_DIR ".tac_symlink"
#define TAC_SHA_256_INFO ".SHA256.info"
-#define TAC_APP_LIST_DB "/opt/usr/dotnet/.TAC.App.list.db"
-#define TAC_APP_LIST_RESTORE_DB "/opt/usr/dotnet/.TAC.App.list.restore.db"
-#define TLC_APP_LIST_DB "/opt/usr/dotnet/.TLC.App.list.db"
-#define TLC_APP_LIST_RESTORE_DB "/opt/usr/dotnet/.TLC.App.list.restore.db"
-#define TLC_LIBRARIES_DIR "/opt/usr/dotnet/Libraries"
+#define TAC_APP_LIST_DB ".TAC.App.list.db"
+#define TAC_APP_LIST_RESTORE_DB ".TAC.App.list.restore.db"
+#define TLC_APP_LIST_DB ".TLC.App.list.db"
+#define TLC_APP_LIST_RESTORE_DB ".TLC.App.list.restore.db"
+#define TLC_LIBRARIES_DIR "Libraries"
#define TIZEN_DOTNET_NUGET "Tizen.NET"
#define TIZEN_DOTNET_SDK_NUGET "Tizen.NET.Sdk"
#define NET_STANDARD_LIBRARY_NUGET "NETStandard.Library"
#define PRE_COMPILED_PACKAGE_FILE "._TIZEN_DOTNET_PRE_COMPILED_PACKAGE"
#if defined (__aarch64__)
-#define ARCHITECTURE_IDENTIFIER "arm64"
+#define ARCHITECTURE_IDENTIFIER "arm64"
+#define ARCHITECTURE_IDENTIFIER_GENERAL ARCHITECTURE_IDENTIFIER
#elif defined (__arm__)
-#define ARCHITECTURE_IDENTIFIER "armel"
+#define ARCHITECTURE_IDENTIFIER "armel"
+#define ARCHITECTURE_IDENTIFIER_GENERAL "arm"
#elif defined (__x86_64__)
-#define ARCHITECTURE_IDENTIFIER "x64"
+#define ARCHITECTURE_IDENTIFIER "x64"
+#define ARCHITECTURE_IDENTIFIER_GENERAL ARCHITECTURE_IDENTIFIER
#elif defined (__i386__)
-#define ARCHITECTURE_IDENTIFIER "x86"
+#define ARCHITECTURE_IDENTIFIER "x86"
+#define ARCHITECTURE_IDENTIFIER_GENERAL ARCHITECTURE_IDENTIFIER
#elif defined (__riscv)
-#define ARCHITECTURE_IDENTIFIER "riscv64"
+#define ARCHITECTURE_IDENTIFIER "riscv64"
+#define ARCHITECTURE_IDENTIFIER_GENERAL ARCHITECTURE_IDENTIFIER
#else
-#error "Unknown target"
+#error "Unknown target"
#endif
#endif //__LAUNCHER_ENV_H_
ni_error_e createNIUnderPkgRoot(const std::string& pkgId, NIOption* opt);
/**
+ * @brief create native images for all DLLs in a package with specified path.
+ * @param[in] rootPath path of package
+ * @param[in] flags additional flags for the image generator
+ * @parma[in] rpk if true, generate RPK native image (default value is false)
+ * @return ni_error_e
+ */
+ni_error_e createNIUnderPkgRootWithPath(const std::string& rootPath, NIOption* opt, bool rpk = false);
+
+/**
* @brief remove platform native images (.NETCore + TizenFX)
*/
void removeNIPlatform();
/**
* @brief regenerate native images of all installed packages (tpk, rpk)
* @param[in] flags additional flags for the image generator
+ * @param[in] removeOnly if it is set true, ni creation is skipped (default : false)
* @return ni_error_e
*/
-ni_error_e regeneratePkgNI(NIOption* opt);
+ni_error_e regeneratePkgNI(NIOption* opt, bool removeOnly = false);
/**
* @brief regenerate native image of TAC for all shared assembly.
* @param[in] flags additional flags for the image generator
+ * @param[in] removeOnly if it is set true, ni creation is skipped. (default : false)
* @return ni_error_e
*/
-ni_error_e regenerateTACNI(NIOption* opt);
+ni_error_e regenerateTACNI(NIOption* opt, bool removeOnly = false);
/**
* @brief Sets the priority of the process to the specified values from -20 to 19.(default : 0)
const std::string& getAppNIPaths();
/**
+ * @brief Get the list of directories for using as a value for CLR APP_PATHS key
+ * @return the list(":" seperated) of paths to probe in
+ */
+ const std::string& getAppCLRPaths();
+
+ /**
* @brief Set addtional dll searching path for App.
* @param[in] paths path
*/
std::string tizenfxPath;
std::string appPaths;
std::string appNIPaths;
+ std::string appCLRPaths;
std::string nativeDllSearchingPaths;
std::string appTacPath;
std::string extraDllPaths;
/**
* @brief restore database of TAC
+ * @param[in] tac readonly flag
* @return tac_error_e
*/
-tac_error_e tac_restoreDB();
+tac_error_e tac_restoreDB(bool isReadonly);
/**
* @brief disable tac feature.
/**
* @brief restore database of TLC
+ * @param[in] tlc readonly flag
* @return tac_error_e
*/
-tac_error_e tlc_restoreDB();
+tac_error_e tlc_restoreDB(bool isReadonly);
#endif /* __TAC_COMMON_H__ */
/* TAC related DB functions */
-int tac_createDB();
+int tac_createDB(bool isReadonly);
-int tac_openDB();
+int tac_openDB(bool isReadonly);
int tac_insertDB(const std::string& pkgId, const std::string& np, const std::string& tac_name, const std::string& tac_version);
/* TAC related DB functions */
-int tlc_createDB();
+int tlc_createDB(bool isReadonly);
-int tlc_openDB();
+int tlc_openDB(bool isReadonly);
int tlc_insertDB(const std::string& pkgId, const std::string& fileSha);
bool isReadOnlyArea(const std::string& path);
/**
+ * @brief check the package is 'readonly' or not
+ * @param[in] package ID
+ * @return bool package readonly value
+ */
+bool isReadOnlyPkg(const std::string& pkgId);
+
+/**
+ * @brief get db path of tac
+ * @param[in] tac readonly flag
+ * @param[in] db file name
+ * @return tac db path
+ */
+std::string tacDBPath(bool isReadonly, const std::string& dbName);
+
+/**
+ * @brief get library path of tlc
+ * @param[in] tlac readonly flag
+ * @return tlc library path
+ */
+std::string tlcLBPath(bool isReadonly);
+
+/**
* @brief split path with ":" delimiter and put that in the vector
* @param[in] source path
* @param[out] string vector
bool isManagedAssembly(const std::string& fileName);
/**
+ * @brief check the file is native image or not.
+ * @param[in] file path
+ * @return return true when the file is native image.
+ */
+bool isNativeImage(const std::string& filePath);
+
+/**
* @brief Resolve assembly files from directories and append their paths to the given list.
* @remark If a native image exists for an assembly in the same directory, it will be used.
* If multiple assemblies of the same name exist, the first one will be used.
iter = g_list_next(iter);
}
+ // if package contains native image, skip AOT.
+ std::string rootPath = getRootPath(pkgId);
+ if (!rootPath.empty()) {
+ if (exist(concatPath(rootPath, concatPath("bin", APP_NI_SUB_DIR)))) {
+ _INFO("Package already contains native images. Skip native image generation");
+ doAOT = false;
+ }
+ }
+
if (doAOT) {
_DBG("Prefer dotnet application AOT set TRUE");
const char *propertyValues[] = {
tpa.c_str(),
- pm->getAppPaths().c_str(),
+ pm->getAppCLRPaths().c_str(),
pm->getAppNIPaths().c_str(),
pm->getNativeDllSearchingPaths().c_str(),
"UseLatestBehaviorWhenTFMNotSpecified",
return -1;
}
- // checkInjection checks dotnet-launcher run mode
+ // checkProfilerInjection checks dotnet-launcher run mode
// At the moment, this mechanism is used only when the Memory Profiler is started.
- int res = checkInjection();
+ int res = checkProfilerInjection();
if (res != 0) {
_ERR("Failed to initnialize Memory Profiler");
return -1;
// Disable config cache to set environment after coreclr_initialize()
putenv(const_cast<char *>("COMPlus_DisableConfigCache=1"));
+ // Disable debugger for loader
+ if (launchMode == LaunchMode::loader) {
+ putenv(const_cast<char *>("DOTNET_EnableDiagnostics_Debugger=0"));
+ }
+
// Set environment variable for System.Environment.SpecialFolder
initEnvForSpecialFolder();
return -1;
}
+ std::string newPath = path;
pluginSetAppInfo(appId, path);
// temporal root path is overrided to real application root path
setSwitch("Switch.System.Diagnostics.StackTrace.ShowILOffsets", true);
+ std::string exec = replaceAll(path, "/bin/", "/bin/.native_image/");
+ if (exist(exec)) {
+ newPath = exec;
+ }
+
pluginBeforeExecute();
- _INFO("execute assembly : %s", path);
+ _INFO("execute assembly : %s", newPath.c_str());
unsigned int ret = 0;
- int st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, path, &ret);
+ int st = executeAssembly(__hostHandle, __domainId, argc, (const char**)argv, newPath.c_str(), &ret);
if (st < 0)
- _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
+ _ERR("Failed to Execute Assembly %s (0x%08x)", newPath.c_str(), st);
return ret;
}
*/
#include "log.h"
-
+#include "utils.h"
#include <cstdlib>
#include <cstring>
-
+#include <string>
#include <dlfcn.h>
-#define HT_PATH "/home/owner/share/tmp/sdk_tools/heaptrack/"
-#define HT_LIB_PATH HT_PATH "libprofiler.so"
-#define HT_INJECTION_LIB_PATH HT_PATH "libheaptrack_inject.so"
+#define SDK_TOOLS_PATH "/home/owner/share/tmp/sdk_tools/"
+#define LIB_INJECTION "libheaptrack_inject.so"
+#define CORPROF_LIB_PATH SDK_TOOLS_PATH "coreprofiler/libcoreprof.so"
-static int injectLibrary(const char path[])
+static int injectHeaptrackLibrary(const char path[])
{
typedef int inject_func();
-
- int res = -1;
void *lib = nullptr;
inject_func *inject = nullptr;
const char *inject_sym = "dotnet_launcher_inject";
lib = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
if (lib == nullptr) {
_ERR("%s", dlerror());
- return res;
+ return -1;
}
inject = reinterpret_cast<inject_func*>(dlsym(lib, inject_sym));
if (inject == nullptr) {
_ERR("%s is not found in the %s", inject_sym, path);
- return res;
+ return -1;
}
- res = inject();
- return res;
+ return inject();
}
-int checkInjection()
+int checkProfilerInjection()
{
char *env = nullptr;
-
env = getenv("CORECLR_PROFILER_PATH");
if (env == nullptr) {
return 0;
}
- // At the moment, this mechanism is used only when the Memory Profiler is started.
- if (strcmp(env, HT_LIB_PATH) != 0) {
- return 0;
+ if (!exist(env)) {
+ return -1;
}
- _INFO("##### Perform injection #########");
+ if (strcmp(env, CORPROF_LIB_PATH) == 0) {
+ return 0;
+ }
+
+
+ if (strstr(env, SDK_TOOLS_PATH) == NULL) {
+ return -1;
+ }
+
+ _INFO("##### Perform profiler injection #########");
+
+ std::string path = concatPath(getBaseName(env), LIB_INJECTION);
+ if (!exist(path)) {
+ return -1;
+ }
- if (injectLibrary(HT_INJECTION_LIB_PATH) != 0) {
- _INFO("##### Injection failed #########");
+ if (injectHeaptrackLibrary(path.c_str()) != 0) {
+ _ERR("##### Heaptrack injection failed #########");
return -1;
}
- _INFO("##### Injection finished #########");
+ _INFO("##### Profiler injection finished #########");
return 0;
}
#ifndef __INJETION_INTERFACE_H__
#define __INJETION_INTERFACE_H__
-int checkInjection();
+int checkProfilerInjection();
#endif // __INJETION_INTERFACE_H__
" --ni-dll - Create NI for DLL\n"
" --ni-pkg - Create NI for package\n"
" (If package is installed under RO area, NI files are generated under RW area)\n"
+ " --ni-pkg-with-path - Create NI for package with root path\n"
+ " (If package is installed under RO area, NI files are generated under RW area)\n"
" --ni-dir - Create NI for directory\n"
" --ni-reset-system - Remove System NI files\n"
+ " --ni-reset-all-app - Remove All App NI files\n"
" --ni-reset-pkg - Remove App NI files\n"
" --ni-reset-dir - Remove NI for directory\n"
" --ni-regen-all-app - Re-generate All App NI files\n"
+ " --tac-reset-all - Remove All TAC NI files\n"
" --tac-regen-all - Re-generate All TAC files\n"
" --tac-restore-db - Restore TAC Database\n"
" --tac-disable-pkg - Disable TAC for package\n"
" # dotnettool --rm-app-profile org.tizen.FormsGallery\n"
"\n");
}
+static std::vector<std::string> args;
+static std::vector<std::string>::iterator it;
+
+//sh-3.2# dotnettool --ni-system [AssemblyDirectory] [AssemblyDirectory] ...
+static void dotnettool_ni_system(NIOption* opt)
+{
+ std::string inputs;
+ while (it != args.end()) {
+ std::string dir = std::string(*it);
+ inputs = inputs + ":" + dir;
+ it = args.erase(it);
+ }
+ if (createNIPlatform(inputs, opt) != NI_ERROR_NONE) {
+ _SERR("Failed to generate system NI");
+ }
+}
+
+//sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
+static void dotnettool_ni_dll(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("DLL path is missing");
+ }
+ std::vector<std::string> inputs;
+ while (it != args.end()) {
+ std::string dll = std::string(*it);
+ inputs.push_back(dll);
+ opt->refFiles.push_back(dll);
+ if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
+ opt->inputBubbleRefFiles.push_back(dll);
+ }
+ it = args.erase(it);
+ }
+ for (auto &dll : inputs) {
+ int ret = createNIDll(dll, opt);
+ if (ret != NI_ERROR_NONE && ret != NI_ERROR_ALREADY_EXIST) {
+ _SERR("Failed to generate NI file [%s]", dll.c_str());
+ break;
+ }
+ }
+}
+
+//sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
+static void dotnettool_ni_pkg(NIOption* opt)
+{
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return;
+ }
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ if (createNIUnderPkgRoot(pkg, opt) != NI_ERROR_NONE) {
+ _SERR("Failed to generate app NI [%s]", pkg.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
+}
+
+//sh-3.2# dotnettool --ni-pkg-with-path [path] [path] ...
+static void dotnettool_ni_pkg_with_path(NIOption* opt)
+{
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return;
+ }
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string path = std::string(*it);
+ if (createNIUnderPkgRootWithPath(path, opt) != NI_ERROR_NONE) {
+ _SERR("Failed to generate app NI from path[%s]", path.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
+}
+
+//sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
+static void dotnettool_ni_dir(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("Directory path is missing");
+ }
+ std::string dir;
+ while (it != args.end()) {
+ if (!dir.empty()) {
+ dir += std::string(":");
+ }
+ dir += std::string(*it);
+ it = args.erase(it);
+ }
+ if (createNIUnderDirs(dir, opt) != NI_ERROR_NONE) {
+ _SERR("Failed to generate NI directory");
+ }
+}
+
+//sh-3.2# dotnettool --ni-reset-all-app
+static void dotnettool_ni_reset_all_app(NIOption* opt)
+{
+ if (regeneratePkgNI(opt, true) != NI_ERROR_NONE) {
+ _SERR("Failed to reseet all app NI");
+ }
+}
+
+//sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
+static void dotnettool_ni_reset_pkg(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ if (removeNIUnderPkgRoot(pkg) != NI_ERROR_NONE) {
+ _SERR("Failed to remove dlls for given package [%s]", pkg.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
+}
+
+//sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
+static void dotnettool_ni_reset_dir(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("Directory path is missing");
+ }
+ while (it != args.end()) {
+ std::string dir = std::string(*it);
+ removeNIUnderDirs(dir);
+ it = args.erase(it);
+ }
+}
+
+//sh-3.2# dotnettool --ni-regen-all-app
+static void dotnettool_ni_regen_all_app(NIOption* opt)
+{
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return;
+ }
+ if (regeneratePkgNI(opt) != NI_ERROR_NONE) {
+ _SERR("Failed to regenerate all app NI");
+ }
+}
+
+//sh-3.2# dotnettool --tac-reset-all
+static void dotnettool_tac_reset_all(NIOption* opt)
+{
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return;
+ }
+ if (regenerateTACNI(opt, true) != NI_ERROR_NONE) {
+ _SERR("Failed to remove all TAC NI files");
+ }
+}
+
+//sh-3.2# dotnettool --tac-regen-all
+static void dotnettool_tac_regen_all(NIOption* opt)
+{
+ if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
+ _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
+ DisplayUsage();
+ return;
+ }
+ if (regenerateTACNI(opt) != NI_ERROR_NONE) {
+ _SERR("Failed to regenerate all TAC");
+ }
+}
+
+//sh-3.2# dotnettool --tac-restore-db
+static void dotnettool_tac_restore_db(NIOption* opt)
+{
+ if (tac_restoreDB(false) != TAC_ERROR_NONE) {
+ _SERR("Failed to restore TAC db of RW");
+ }
+ if (tlc_restoreDB(false) != TAC_ERROR_NONE) {
+ _SERR("Failed to restore TLC db of RW");
+ }
+ if (tac_restoreDB(true) != TAC_ERROR_NONE) {
+ _SERR("Failed to restore TAC db of RO");
+ }
+ if (tlc_restoreDB(true) != TAC_ERROR_NONE) {
+ _SERR("Failed to restore TLC db of RO");
+ }
+}
+
+//sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
+static void dotnettool_tac_enable_pkg(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ if (enableTACPackage(pkg) != TAC_ERROR_NONE) {
+ _SERR("Failed to enable tac [%s]", pkg.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
+}
+
+//sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
+static void dotnettool_tac_disable_pkg(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ if (disableTACPackage(pkg) != TAC_ERROR_NONE) {
+ _SERR("Failed to disable tac [%s]", pkg.c_str());
+ break;
+ }
+ it = args.erase(it);
+ }
+}
+
+//sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
+static void dotnettool_rm_app_profile(NIOption* opt)
+{
+ if (args.size() < 1) {
+ _SERR("Package name is missing");
+ }
+ while (it != args.end()) {
+ std::string pkg = std::string(*it);
+ if (removeAppProfileData(pkg) != PROFILE_ERROR_NONE) {
+ _SERR("Failed to remove [%s] profile data", pkg.c_str());
+ }
+ it = args.erase(it);
+ }
+}
int main(int argc, char* argv[])
{
return -1;
}
- std::vector<std::string> args;
for (int i = 0; i < argc; ++i) {
std::string arg = argv[i];
if ((arg == "-?") || (arg == "-h") || (arg == "--h")) {
DisplayUsage();
- return 0;
+ return -1;
} else if (arg == "--verbose") {
opt->flags |= NI_FLAGS_VERBOSE;
} else if (arg == "--inputbubble") {
if (i >= argc) {
_SOUT("Priority value(-20 ~ 19) should be followed for --set-priority option");
DisplayUsage();
- return 0;
+ return -1;
}
opt->flags |= NI_FLAGS_SET_PRIORITY;
} catch (...) {
_SERR("Invalid argument: %s", argv[i]);
DisplayUsage();
- return 0;
+ return -1;
}
} else if (arg == "--mibc") {
++i;
if (i >= argc) {
_SOUT("File path containing Mibc files should be followed for --mibc option");
DisplayUsage();
- return 0;
+ return -1;
}
opt->flags |= NI_FLAGS_MIBC;
for (const auto &path : paths) {
if (!isFile(path) || isDirectory(path)) {
_SERR("Mibc file path is missing or does not exist");
+ DisplayUsage();
return -1;
}
opt->mibcPath.push_back(path);
if (i >= argc) {
_SOUT("Path for references should be followed for --inputbubbleref option");
DisplayUsage();
- return 0;
+ return -1;
}
opt->flags |= NI_FLAGS_INPUT_BUBBLE_REF;
if (i >= argc) {
_SOUT("Path for references should be followed for --ref option");
DisplayUsage();
- return 0;
+ return -1;
}
std::vector<std::string> files;
return -1;
}
- std::vector<std::string>::iterator it = args.begin();
+ it = args.begin();
std::string cmd = std::string(*it);
it = args.erase(it);
- //sh-3.2# dotnettool --ni-system [AssemblyDirectory] [AssemblyDirectory] ...
if (cmd == "--ni-system") {
- std::string inputs;
- while (it != args.end()) {
- const std::string dir = std::string(*it);
- inputs = inputs + ":" + dir;
- it = args.erase(it);
- }
- int ret = createNIPlatform(inputs, opt);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to generate system NI");
- }
+ dotnettool_ni_system(opt);
}
- //sh-3.2# dotnettool --ni-dll [assemblyPath] [assemblyPath] ...
else if (cmd == "--ni-dll") {
- if (args.size() < 1) {
- _SERR("DLL path is missing");
- }
- std::vector<std::string> inputs;
- while (it != args.end()) {
- std::string dll = std::string(*it);
- inputs.push_back(dll);
- opt->refFiles.push_back(dll);
- if (opt->flags & NI_FLAGS_INPUT_BUBBLE) {
- opt->inputBubbleRefFiles.push_back(dll);
- }
- it = args.erase(it);
- }
-
- for (auto &dll : inputs) {
- int ret = createNIDll(dll, opt);
- if (ret != NI_ERROR_NONE && ret != NI_ERROR_ALREADY_EXIST) {
- _SERR("Failed to generate NI file [%s]", dll.c_str());
- break;
- }
- }
+ dotnettool_ni_dll(opt);
}
- //sh-3.2# dotnettool --ni-pkg [pkgId] [pkgId] ...
else if (cmd == "--ni-pkg") {
- if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
- _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
- DisplayUsage();
- return -1;
- }
-
- if (args.size() < 1) {
- _SERR("Package name is missing");
- }
- while (it != args.end()) {
- std::string pkg = std::string(*it);
- int ret = createNIUnderPkgRoot(pkg, opt);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to generate app NI [%s]", pkg.c_str());
- break;
- }
- it = args.erase(it);
- }
+ dotnettool_ni_pkg(opt);
+ }
+ else if (cmd == "--ni-pkg-with-path") {
+ dotnettool_ni_pkg_with_path(opt);
}
- //sh-3.2# dotnettool --ni-dir [AssemblyDirectory] [AssemblyDirectory] ...
else if (cmd == "--ni-dir") {
- if (args.size() < 1) {
- _SERR("Directory path is missing");
- }
- std::string dir;
- while (it != args.end()) {
- if (!dir.empty()) {
- dir += std::string(":");
- }
- dir += std::string(*it);
- it = args.erase(it);
- }
- if (createNIUnderDirs(dir, opt) != NI_ERROR_NONE) {
- _SERR("Failed to generate NI directory");
- }
+ dotnettool_ni_dir(opt);
}
- //sh-3.2# dotnettool --ni-reset-system
else if (cmd == "--ni-reset-system") {
removeNIPlatform();
}
- //sh-3.2# dotnettool --ni-reset-pkg [pkgId] [pkgId] ...
+ else if (cmd == "--ni-reset-all-app") {
+ dotnettool_ni_reset_all_app(opt);
+ }
else if (cmd == "--ni-reset-pkg") {
- if (args.size() < 1) {
- _SERR("Package name is missing");
- }
- while (it != args.end()) {
- std::string pkg = std::string(*it);
- int ret = removeNIUnderPkgRoot(pkg);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to remove dlls for given package [%s]", pkg.c_str());
- break;
- }
- it = args.erase(it);
- }
+ dotnettool_ni_reset_pkg(opt);
}
- //sh-3.2# dotnettool --ni-reset-dir [AssemblyDirectory] [AssemblyDirectory] ...
else if (cmd == "--ni-reset-dir") {
- if (args.size() < 1) {
- _SERR("Directory path is missing");
- }
- while (it != args.end()) {
- const std::string dir = std::string(*it);
- removeNIUnderDirs(dir);
- it = args.erase(it);
- }
+ dotnettool_ni_reset_dir(opt);
}
- //sh-3.2# dotnettool --ni-regen-all-app
else if (cmd == "--ni-regen-all-app") {
- if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
- _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
- DisplayUsage();
- return -1;
- }
-
- int ret = regeneratePkgNI(opt);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to regenerate all app NI");
- }
+ dotnettool_ni_regen_all_app(opt);
+ }
+ else if (cmd == "--tac-reset-all") {
+ dotnettool_tac_reset_all(opt);
}
- //sh-3.2# dotnettool --tac-regen-all
else if (cmd == "--tac-regen-all") {
- if (opt->flags & NI_FLAGS_RM_ORIGIN_AFTER_NI) {
- _SERR("App AOTC options cannot be used with --rm-origin-after-ni option");
- DisplayUsage();
- return -1;
- }
-
- int ret = regenerateTACNI(opt);
- if (ret != NI_ERROR_NONE) {
- _SERR("Failed to regenerate all TAC");
- }
+ dotnettool_tac_regen_all(opt);
}
- //sh-3.2# dotnettool --tac-restore-db
else if (cmd == "--tac-restore-db") {
- int ret = tac_restoreDB();
- if (ret != TAC_ERROR_NONE) {
- _SERR("Failed to restore TAC db");
- }
- ret = tlc_restoreDB();
- if (ret != TAC_ERROR_NONE) {
- _SERR("Failed to restore TLC db");
- }
+ dotnettool_tac_restore_db(opt);
}
- //sh-3.2# dotnettool --tac-enable-pkg [pkgId] [pkgId] ...
else if (cmd == "--tac-enable-pkg") {
- if (args.size() < 1) {
- _SERR("Package name is missing");
- }
- while (it != args.end()) {
- std::string pkg = std::string(*it);
- int ret = enableTACPackage(pkg);
- if (ret != TAC_ERROR_NONE) {
- _SERR("Failed to enable tac [%s]", pkg.c_str());
- break;
- }
- it = args.erase(it);
- }
+ dotnettool_tac_enable_pkg(opt);
}
- //sh-3.2# dotnettool --tac-disable-pkg [pkgId] [pkgId] ...
else if (cmd == "--tac-disable-pkg") {
- if (args.size() < 1) {
- _SERR("Package name is missing");
- }
- while (it != args.end()) {
- std::string pkg = std::string(*it);
- int ret = disableTACPackage(pkg);
- if (ret != TAC_ERROR_NONE) {
- _SERR("Failed to disable tac [%s]", pkg.c_str());
- break;
- }
- it = args.erase(it);
- }
+ dotnettool_tac_disable_pkg(opt);
}
- //sh-3.2# dotnettool --resolve-all-app
else if (cmd == "--resolve-all-app") {
resolveAllApps();
}
- //sh-3.2# dotnettool --rm-app-profile [pkgId] [pkgId] ...
else if (cmd == "--rm-app-profile") {
- if (args.size() < 1) {
- _SERR("Package name is missing");
- }
- while (it != args.end()) {
- std::string pkg = std::string(*it);
- if (removeAppProfileData(pkg) != PROFILE_ERROR_NONE) {
- _SERR("Failed to remove [%s] profile data", pkg.c_str());
- }
- it = args.erase(it);
- }
+ dotnettool_rm_app_profile(opt);
}
- //sh-3.2# dotnettool --rm-all-app-profile
else if (cmd == "--rm-all-app-profile") {
removeAllAppProfileData();
}
- //sh-3.2# dotnettool --check-all-app-privilege
else if (cmd == "--check-all-app-privilege") {
checkAllAppPrivilege();
}
int resolvePlatformSpecificFiles(const std::string& rootPath)
{
std::string appBinPath = concatPath(rootPath, "bin");
+ std::string appLibPath = concatPath(rootPath, "lib");
std::string runtimesPath = concatPath(appBinPath, "runtimes");
+ // remove unused arch directory
+ std::vector<std::string> archList = {"x86", "x64", "arm", "armel", "arm64", "aarch64", "riscv32", "riscv64"};
+ archList.erase(find(archList.begin(), archList.end(), ARCHITECTURE_IDENTIFIER));
+ if (!strncmp(ARCHITECTURE_IDENTIFIER, "armel", 5)) {
+ archList.erase(find(archList.begin(), archList.end(), "arm"));
+ } else if (!strncmp(ARCHITECTURE_IDENTIFIER, "arm64", 5)) {
+ archList.erase(find(archList.begin(), archList.end(), "aarch64"));
+ }
+
+ for (const auto &arch : archList) {
+ std::string archPath = concatPath(appLibPath, arch);
+ if (exist(archPath)) {
+ if (!removeAll(archPath)) {
+ _ERR("Failed to remove %s directory", archPath.c_str());
+ }
+ }
+ }
+
// if runtimes directory doesnot exist, return 0
if (!isDirectory(runtimesPath)) {
return 0;
#define __XSTR(x) #x
#define __STR(x) __XSTR(x)
-#if defined(__arm__) || defined(__aarch64__)
static const char* __NATIVE_LIB_DIR = __STR(NATIVE_LIB_DIR);
-#endif
static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
+static const char* __RUNTIME_DIR = __STR(RUNTIME_DIR);
static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_DIR);
#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
size_t index = dllPath.find_last_of(".");
if (index == std::string::npos) {
- _SERR("File doesnot contain extension. fail to get NI file name");
+ _SERR("File does not contain extension. fail to get NI file name");
return "";
}
std::string fName = dllPath.substr(0, index);
}
auto func = [&fileList, opt](const std::string& f_path, const std::string& f_name) {
- if (isManagedAssembly(f_name) && !checkNIExistence(f_path, opt)) {
+ if (isManagedAssembly(f_name) && !isR2RImage(f_path) && !checkNIExistence(f_path, opt)) {
fileList.push_back(getAbsolutePath(f_path));
}
};
if (exist(pdbPath)) {
std::string targetPDBPath = changeExtension(niPath, ".ni.dll", ".pdb");
if (!exist(targetPDBPath)) {
- bf::create_symlink(pdbPath, targetPDBPath);
+ bf::create_symlink(concatPath("..", getFileName(pdbPath)), targetPDBPath);
copySmackAndOwnership(pdbPath, targetPDBPath, true);
}
}
_SERR("Fail to rename from .native_image_tmp to .native_image");
} else {
_SOUT("Success to rename from %s to %s", niTmpPath.c_str(), niPath.c_str());
+ try {
+ for (auto& ni : bf::recursive_directory_iterator(niPath)) {
+ std::string niFile = ni.path().string();
+ if (isNativeImage(niFile)) {
+ std::string dllFile = changeExtension(niFile, ".ni.dll", ".dll");
+ bf::create_symlink(getFileName(niFile), dllFile);
+ copySmackAndOwnership(niFile, dllFile, true);
+ }
+ }
+ } catch (const bf::filesystem_error& error) {
+ _ERR("Failed to recursive directory: %s", error.what());
+ }
}
}
}
return doAOTList(dllList, refPaths, opt);
}
-static ni_error_e removeAndCreateNI(const char* pkgId, NIOption* pOptions)
-{
- if (removeNIUnderPkgRoot(pkgId) != NI_ERROR_NONE) {
- _SERR("Failed to remove previous dlls from [%s]", pkgId);
- return NI_ERROR_UNKNOWN;
- }
-
- if (createNIUnderPkgRoot(pkgId, pOptions) != NI_ERROR_NONE) {
- _SERR("Failed to generate NI file [%s]", pkgId);
- return NI_ERROR_UNKNOWN;
- }
-
- _SOUT("Complete make native image for pkg (%s)", pkgId);
- return NI_ERROR_NONE;
-}
-
-static bool isReadOnlyPkg(std::string pkgId)
-{
- int ret = 0;
- bool readonly = false;
- pkgmgrinfo_pkginfo_h handle;
-
- ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle);
- if (ret != PMINFO_R_OK) {
- _ERR("Fail to get pkginfo");
- return false;
- }
-
- ret = pkgmgrinfo_pkginfo_is_readonly(handle, &readonly);
- if (ret != PMINFO_R_OK) {
- _ERR("Fail to get is_readonly");
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return false;
- }
-
- pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
- return readonly;
-}
-
// callback function of "pkgmgrinfo_appinfo_metadata_filter_foreach"
static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData)
{
ni_error_e initNICommon()
{
-#if defined(__arm__) || defined(__aarch64__)
+#ifdef __i386__
+ _SERR("x86 doesnot supported. skip ni file generation");
+ return NI_ERROR_NOT_SUPPORTED;
+#endif
char *env = nullptr;
env = getenv("MIC_CROSSGEN2_ENABLED");
if (env != nullptr && !strcmp(env, "1")) {
CORERUN_CMD = std::string("/opt/usr/dotnet/mic/crossgen2");
CROSSGEN2_PATH = "";
- CLRJIT_PATH = std::string("/opt/usr/dotnet/mic/libclrjit_unix_") + ARCHITECTURE_IDENTIFIER + std::string("_x64.so");
+ CLRJIT_PATH = std::string("/opt/usr/dotnet/mic/libclrjit_");
+ if (strstr(bf::read_symlink(__RUNTIME_DIR).string().c_str(), "6.0.") != NULL) {
+ CLRJIT_PATH.append("unix_"); //6.0.X
+ CLRJIT_PATH.append(ARCHITECTURE_IDENTIFIER);
+ } else {
+ CLRJIT_PATH.append("universal_");
+ CLRJIT_PATH.append(ARCHITECTURE_IDENTIFIER_GENERAL);
+ }
+ CLRJIT_PATH.append("_x64.so");
}
// get interval value
}
return NI_ERROR_NONE;
-#else
- _SERR("crossgen supports arm/arm64 architecture only. skip ni file generation");
- return NI_ERROR_NOT_SUPPORTED;
-#endif
}
void finalizeNICommon()
return doAOTFile(dllPath, std::string(), opt);
}
-ni_error_e createNIUnderTAC(const std::string& targetPath, const std::string& refPaths, NIOption* opt)
+static ni_error_e createNIUnderTAC(const std::string& targetPath, const std::string& refPaths, NIOption* opt)
{
ni_error_e ret;
_SOUT("%s symbolic link file generated successfully.", symNIPath.c_str());
_INFO("%s symbolic link file generated successfully.", symNIPath.c_str());
}
+ std::string symPath = changeExtension(symNIPath, ".ni.dll", ".dll");
+ removeFile(symPath);
+ bf::create_symlink(niPath, symPath);
+ copySmackAndOwnership(targetPath.c_str(), symPath.c_str(), true);
+ _SOUT("%s symbolic link file generated successfully.", symPath.c_str());
+ _INFO("%s symbolic link file generated successfully.", symPath.c_str());
}
}
}
ni_error_e createNIUnderPkgRoot(const std::string& pkgId, NIOption* opt)
{
+ std::string rootPath = getRootPath(pkgId);
+ if (rootPath.empty()) {
+ _SERR("Failed to get root path from [%s]", pkgId.c_str());
+ return NI_ERROR_INVALID_PACKAGE;
+ }
+
+ return createNIUnderPkgRootWithPath(rootPath, opt, isRPK(pkgId));
+}
+
+ni_error_e createNIUnderPkgRootWithPath(const std::string& rootPath, NIOption* opt, bool rpk)
+{
if (!isR2RImage(concatPath(__pm->getRuntimePath(), "System.Private.CoreLib.dll"))) {
_SERR("The native image of System.Private.CoreLib does not exist.\n"
"Run the command to create the native image\n"
return NI_ERROR_CORE_NI_FILE;
}
- std::string rootPath = getRootPath(pkgId);
if (rootPath.empty()) {
- _SERR("Failed to get root path from [%s]", pkgId.c_str());
+ _SERR("Failed. rootPath should be set");
return NI_ERROR_INVALID_PACKAGE;
}
__pm->setAppRootPath(rootPath);
}
std::string targetDirs;
- if (isRPK(pkgId)) {
+ if (rpk) {
opt->flags &= ~NI_FLAGS_APPNI; // added to exclude logic of APP_NI
opt->flags |= NI_FLAGS_NO_PIPELINE; // added the flag to set the output path
std::string paths = getResourcePaths(rootPath);
if (paths.empty()) {
- _SERR("Failed to get rpk paths from [%s]", pkgId.c_str());
+ _SERR("Failed to get rpk paths from rootPath[%s]", rootPath.c_str());
return NI_ERROR_UNKNOWN;
}
targetDirs = paths;
if (isReadOnlyArea(rootPath)) {
opt->flags |= NI_FLAGS_APP_UNDER_RO_AREA;
opt->flags |= NI_FLAGS_NO_PIPELINE;
+ std::string tmpPath = replaceAll(rootPath, getBaseName(rootPath), __READ_ONLY_APP_UPDATE_DIR);
+ if (!removeAll(tmpPath)){
+ _SERR("Fail to remove RO App update path : %s", tmpPath.c_str());
+ }
_SERR("Only no-pipeline mode supported for RO app. Set no-pipeline option forcibly");
} else {
opt->flags &= ~NI_FLAGS_APP_UNDER_RO_AREA;
}
}
+static void removeNIUnderTAC(const std::string& rootPaths)
+{
+ auto convert = [&rootPaths](const std::string& path, const std::string& filename) {
+ if (isNativeImage(path)) {
+ std::string assemblyPath = changeExtension(path, ".ni.dll", ".dll");
+ if (exist(assemblyPath)) {
+ if (removeFile(assemblyPath)) {
+ bf::create_symlink(changeExtension(bf::read_symlink(path).string(), ".ni.dll", ".dll"), assemblyPath);
+ copySmackAndOwnership(rootPaths.c_str(), assemblyPath.c_str(), true);
+ }
+ }
+ removeFile(path);
+ }
+ };
+
+ std::vector<std::string> paths;
+ splitPath(rootPaths, paths);
+ for (const auto &path : paths) {
+ scanFilesInDirectory(path, convert, -1);
+ }
+}
+
ni_error_e removeNIUnderPkgRoot(const std::string& pkgId)
{
std::vector<std::string> paths;
if (!isReadOnlyArea(path)) {
// Only the native image inside the TAC should be removed.
if (strstr(path.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) {
- removeNIUnderDirs(path);
+ removeNIUnderTAC(path);
} else {
if (isDirectory(path)) {
if (!removeAll(path.c_str())) {
}
}
}
+ paths.clear();
// In special cases, the ni file may exist in the dll location.
// The code below is to avoid this exceptional case.
std::string appPaths = __pm->getAppPaths();
splitPath(appPaths, paths);
for (const auto &path : paths) {
- if (isDirectory(path)) {
- removeNIUnderDirs(path);
+ if (strstr(path.c_str(), TAC_SYMLINK_SUB_DIR) != NULL) {
+ removeNIUnderTAC(path);
+ } else {
+ if (isDirectory(path)) {
+ removeNIUnderDirs(path);
+ }
}
}
}
return NI_ERROR_NONE;
}
-ni_error_e regeneratePkgNI(NIOption* opt)
+ni_error_e regeneratePkgNI(NIOption* opt, bool removeOnly)
{
std::vector<std::string> pkgList;
ni_error_e ret = NI_ERROR_NONE;
continue;
}
- if (removeAndCreateNI(pkg.c_str(), opt) != NI_ERROR_NONE) {
+ if (removeNIUnderPkgRoot(pkg) != NI_ERROR_NONE) {
_SERR("Failed to remove previous dlls from [%s]", pkg.c_str());
ret = NI_ERROR_UNKNOWN;
- } else {
- _SOUT("Complete make application to native image");
+ }
+
+ if (!removeOnly) {
+ if (createNIUnderPkgRoot(pkg, opt) != NI_ERROR_NONE) {
+ _SERR("Failed to generate NI file [%s]", pkg.c_str());
+ ret = NI_ERROR_UNKNOWN;
+ } else {
+ _SOUT("Complete make application to native image");
+ }
}
}
return 0;
}
- sqlite3 *tac_db = openDB(TAC_APP_LIST_DB);
+ sqlite3 *tac_db = openDB(concatPath(__DOTNET_DIR, TAC_APP_LIST_DB));
if (!tac_db) {
_SERR("Sqlite open error");
return -1;
return 0;
}
-ni_error_e regenerateTACNI(NIOption* opt)
+ni_error_e regenerateTACNI(NIOption* opt, bool removeOnly)
{
removeNIUnderDirs(__DOTNET_DIR);
- pkgmgrinfo_appinfo_metadata_filter_h handle;
- int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
- if (ret != PMINFO_R_OK) {
- return NI_ERROR_UNKNOWN;
- }
+ if (!removeOnly) {
+ pkgmgrinfo_appinfo_metadata_filter_h handle;
+ int ret = pkgmgrinfo_appinfo_metadata_filter_create(&handle);
+ if (ret != PMINFO_R_OK) {
+ return NI_ERROR_UNKNOWN;
+ }
- ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE_TRUE);
- if (ret != PMINFO_R_OK) {
- pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
- return NI_ERROR_UNKNOWN;
- }
+ ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, TAC_METADATA_KEY, METADATA_VALUE_TRUE);
+ if (ret != PMINFO_R_OK) {
+ pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+ return NI_ERROR_UNKNOWN;
+ }
+
+ ret = pkgmgrAppMDFilterForeach(handle, regenTacCb, &opt);
+ if (ret != 0) {
+ pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
+ return NI_ERROR_UNKNOWN;
+ }
- ret = pkgmgrAppMDFilterForeach(handle, regenTacCb, &opt);
- if (ret != 0) {
pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
- return NI_ERROR_UNKNOWN;
}
- pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
-
return NI_ERROR_NONE;
}
#define __STR(x) __XSTR(x)
static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
static const char* __READ_ONLY_APP_UPDATE_DIR = __STR(READ_ONLY_APP_UPDATE_DIR);
+static const char* __READ_ONLY_TAC_DIR = __STR(READ_ONLY_TAC_DIR);
#undef __STR
#undef __XSTR
static std::vector<std::string> restore_nuget;
static std::vector<std::string> restore_library;
-static void cleanupDirectory()
+static void cleanupDirectory(bool isReadonly)
{
std::vector<std::string> removeNuget;
try {
- for (auto& nuget : bf::recursive_directory_iterator(__DOTNET_DIR)) {
+ std::string tacLocation = isReadonly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
+ for (auto& nuget : bf::recursive_directory_iterator(tacLocation)) {
std::string nugetPath = nuget.path().string();
if (!bf::is_directory(nugetPath) ||
- nugetPath.find(TLC_LIBRARIES_DIR) != std::string::npos ||
+ nugetPath.find(tlcLBPath(isReadonly)) != std::string::npos ||
nugetPath.find(__READ_ONLY_APP_UPDATE_DIR) != std::string::npos) {
continue;
}
char *pkgId = NULL;
char *root = NULL;
char *exec = NULL;
+ bool *isReadOnly = (bool*)userData;
int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
if (ret != PMINFO_R_OK) {
return -1;
}
+ if (userData == NULL || isReadOnlyPkg(pkgId) != *isReadOnly) {
+ return -1;
+ }
+
ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
if (ret != PMINFO_R_OK) {
_SERR("Failed to get root path");
"INSERT INTO TAC (PKGID, NUGET, NAME, VERSION) " \
"VALUES (%Q, %Q, %Q, %Q);", pkgId, nuget.c_str(), name.c_str(), version.c_str());
insertDB(tac_db, sql);
- restore_nuget.push_back(concatPath(__DOTNET_DIR, nuget));
+ restore_nuget.push_back(concatPath(*isReadOnly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR, nuget));
sqlite3_free(sql);
}
}
return 0;
}
-tac_error_e tac_restoreDB()
+tac_error_e tac_restoreDB(bool isReadonly)
{
- if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
- _SERR("Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
+ std::string tacRestoreDbPath = tacDBPath(isReadonly, TAC_APP_LIST_RESTORE_DB);
+ if (!removeFile(tacRestoreDbPath)) {
+ _SERR("Failed to remove of %s", tacRestoreDbPath.c_str());
return TAC_ERROR_UNKNOWN;
}
- std::string dbRestoreJournal = TAC_APP_LIST_RESTORE_DB + std::string("-journal");
+ std::string dbRestoreJournal = tacRestoreDbPath + std::string("-journal");
if (!removeFile(dbRestoreJournal)) {
_SERR("Failed to remove of %s", dbRestoreJournal.c_str());
return TAC_ERROR_UNKNOWN;
}
- tac_db = createDB(TAC_APP_LIST_RESTORE_DB, CREATE_TAC_DB_TABLE);
+ tac_db = createDB(tacRestoreDbPath, CREATE_TAC_DB_TABLE);
if (!tac_db) {
_SERR("Sqlite create error");
return TAC_ERROR_UNKNOWN;
return TAC_ERROR_UNKNOWN;
}
- ret = pkgmgrAppMDFilterForeach(handle, tac_restoreDBCb, NULL);
+ ret = pkgmgrAppMDFilterForeach(handle, tac_restoreDBCb, &isReadonly);
if (ret != 0) {
pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
return TAC_ERROR_UNKNOWN;
tac_db = NULL;
}
- if (!copyFile(TAC_APP_LIST_RESTORE_DB, TAC_APP_LIST_DB)) {
- _SERR("Failed to copy of %s", TAC_APP_LIST_DB);
+ std::string tacDbPath = tacDBPath(isReadonly, TAC_APP_LIST_DB);
+ if (!copyFile(tacRestoreDbPath, tacDbPath)) {
+ _SERR("Failed to copy of %s", tacDbPath.c_str());
return TAC_ERROR_UNKNOWN;
}
- if (!removeFile(TAC_APP_LIST_RESTORE_DB)) {
- _SERR("Failed to remove of %s", TAC_APP_LIST_RESTORE_DB);
+ if (!removeFile(tacRestoreDbPath)) {
+ _SERR("Failed to remove of %s", tacRestoreDbPath.c_str());
return TAC_ERROR_UNKNOWN;
}
- std::string dbJournal = TAC_APP_LIST_DB + std::string("-journal");
+ std::string dbJournal = tacDbPath + std::string("-journal");
if (!copyFile(dbRestoreJournal, dbJournal)) {
_SERR("Failed to copy of %s", dbJournal.c_str());
return TAC_ERROR_UNKNOWN;
return TAC_ERROR_UNKNOWN;
}
- cleanupDirectory();
+ cleanupDirectory(isReadonly);
return TAC_ERROR_NONE;
}
std::string fileName = symlinkAssembly.path().filename().string();
if (isSymlinkFile(symPath)) {
std::string originPath = bf::read_symlink(symPath).string();
- if (!isR2RImage(symPath)) {
- std::string dllPath = concatPath(binDir, fileName);
- if (!copyFile(originPath, dllPath)) {
- _SERR("Failed to copy of %s", dllPath.c_str());
- return TAC_ERROR_UNKNOWN;
- }
- copySmackAndOwnership(binDir.c_str(), concatPath(binDir, fileName).c_str());
- } else {
+ if (isNativeImage(fileName)) {
std::string niPath = concatPath(binNIDir, fileName);
if (!copyFile(originPath, niPath)) {
_SERR("Failed to copy of %s", niPath.c_str());
return TAC_ERROR_UNKNOWN;
}
copySmackAndOwnership(binDir.c_str(), niPath.c_str());
+ std::string dllFile = changeExtension(niPath, ".ni.dll", ".dll");
+ bf::create_symlink(niPath, dllFile);
+ copySmackAndOwnership(niPath, dllFile, true);
+ } else {
+ std::string dllPath = concatPath(binDir, fileName);
+ if (!copyFile(changeExtension(originPath, ".ni.dll", ".dll"), dllPath)) {
+ _SERR("Failed to copy of %s", dllPath.c_str());
+ return TAC_ERROR_UNKNOWN;
+ }
+ copySmackAndOwnership(binDir.c_str(), concatPath(binDir, fileName).c_str());
}
}
}
tac_error_e enableTACPackage(const std::string& pkgId)
{
+ std::string tacLocation = isReadOnlyPkg(pkgId) ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
std::string rootPath = getRootPath(pkgId);
if (rootPath.empty()) {
_SERR("Failed to get root path from [%s]", pkgId.c_str());
for (auto& npAssembly : depsJsonParser(rootPath, execName)) {
std::string nugetPackage = npAssembly.substr(0, npAssembly.rfind(':'));
std::string assemblyName = npAssembly.substr(npAssembly.rfind(':') + 1);
- std::string nugetPath = concatPath(__DOTNET_DIR, nugetPackage);
+ std::string nugetPath = concatPath(tacLocation, nugetPackage);
if (exist(nugetPath)) {
std::string originPath = concatPath(nugetPath, assemblyName);
if (exist(originPath)) {
for (auto& originPath : enableNuget) {
if (exist(originPath)) {
std::string fileName = originPath.substr(originPath.rfind('/') + 1);
+ std::string originNIPath = changeExtension(originPath, ".dll", ".ni.dll");
if (exist(binNIDir)) {
- std::string originNIPath = changeExtension(originPath, "dll", "ni.dll");
if (exist(originNIPath)) {
- if (createSymlinkFile(tacDir, binNIDir, originNIPath, changeExtension(fileName, "dll", "ni.dll")) != TAC_ERROR_NONE) {
+ if (createSymlinkFile(tacDir, binNIDir, originNIPath, changeExtension(fileName, ".dll", ".ni.dll")) != TAC_ERROR_NONE) {
return TAC_ERROR_UNKNOWN;
+ } else {
+ if (remove(concatPath(binNIDir, fileName).c_str())) {
+ _SERR("Failed to remove of %s", concatPath(binNIDir, fileName).c_str());
+ return TAC_ERROR_UNKNOWN;
+ }
}
}
- }
- if (createSymlinkFile(tacDir, binDir, originPath, fileName) != TAC_ERROR_NONE) {
- return TAC_ERROR_UNKNOWN;
+ if (createSymlinkFile(tacDir, binDir, originNIPath, fileName) != TAC_ERROR_NONE) {
+ return TAC_ERROR_UNKNOWN;
+ }
+ } else {
+ if (createSymlinkFile(tacDir, binDir, originPath, fileName) != TAC_ERROR_NONE) {
+ return TAC_ERROR_UNKNOWN;
+ }
}
}
}
std::vector<std::string> depsJsonParser(const std::string& rootPath, const std::string& execName)
{
std::vector<std::string> parserData;
- std::string depsJsonName = changeExtension(execName, "dll", "deps.json");
+ std::string depsJsonName = changeExtension(execName, ".dll", ".deps.json");
std::string depsJsonPath = concatPath(rootPath, depsJsonName);
try {
if (exist(depsJsonPath)) {
char *pkgId = NULL;
char *root = NULL;
std::string rootPath;
+ bool *isReadOnly = (bool*)userData;
int ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
if (ret != PMINFO_R_OK) {
return -1;
}
+ if (userData == NULL || isReadOnlyPkg(pkgId) != *isReadOnly) {
+ return -1;
+ }
+
ret = pkgmgrinfo_appinfo_get_root_path(handle, &root);
if (ret != PMINFO_R_OK) {
_SERR("Failed to get root path");
return 0;
}
-tac_error_e tlc_restoreDB()
+tac_error_e tlc_restoreDB(bool isReadonly)
{
- if (!removeFile(TLC_APP_LIST_RESTORE_DB)) {
- _SERR("Failed to remove of %s", TLC_APP_LIST_RESTORE_DB);
+ std::string tlcRestoreDbPath = tacDBPath(isReadonly, TLC_APP_LIST_RESTORE_DB);
+ if (!removeFile(tlcRestoreDbPath)) {
+ _SERR("Failed to remove of %s", tlcRestoreDbPath.c_str());
return TAC_ERROR_UNKNOWN;
}
- std::string dbRestoreJournal = TLC_APP_LIST_RESTORE_DB + std::string("-journal");
+ std::string dbRestoreJournal = tlcRestoreDbPath + std::string("-journal");
if (!removeFile(dbRestoreJournal)) {
_SERR("Failed to remove of %s", dbRestoreJournal.c_str());
return TAC_ERROR_UNKNOWN;
}
- tlc_db = createDB(TLC_APP_LIST_RESTORE_DB, CREATE_TLC_DB_TABLE);
+ tlc_db = createDB(tlcRestoreDbPath, CREATE_TLC_DB_TABLE);
if (!tlc_db) {
_SERR("Sqlite create error");
return TAC_ERROR_UNKNOWN;
return TAC_ERROR_UNKNOWN;
}
- ret = pkgmgrAppMDFilterForeach(handle, tlc_restoreDBCb, NULL);
+ ret = pkgmgrAppMDFilterForeach(handle, tlc_restoreDBCb, &isReadonly);
if (ret != 0) {
pkgmgrinfo_appinfo_metadata_filter_destroy(handle);
return TAC_ERROR_UNKNOWN;
tlc_db = NULL;
}
- if (!copyFile(TLC_APP_LIST_RESTORE_DB, TLC_APP_LIST_DB)) {
- _SERR("Failed to copy of %s", TLC_APP_LIST_DB);
+ std::string tlcDbPath = tacDBPath(isReadonly, TLC_APP_LIST_DB);
+ if (!copyFile(tlcRestoreDbPath, tlcDbPath)) {
+ _SERR("Failed to copy of %s", tlcDbPath.c_str());
return TAC_ERROR_UNKNOWN;
}
- if (!removeFile(TLC_APP_LIST_RESTORE_DB)) {
- _SERR("Failed to remove of %s", TLC_APP_LIST_RESTORE_DB);
+ if (!removeFile(tlcRestoreDbPath)) {
+ _SERR("Failed to remove of %s", tlcRestoreDbPath.c_str());
return TAC_ERROR_UNKNOWN;
}
- std::string dbJournal = TLC_APP_LIST_DB + std::string("-journal");
+ std::string dbJournal = tlcDbPath + std::string("-journal");
if (!copyFile(dbRestoreJournal, dbJournal)) {
_SERR("Failed to copy of %s", dbJournal.c_str());
return TAC_ERROR_UNKNOWN;
}
};
- scanFilesInDirectory(TLC_LIBRARIES_DIR, convert, 0);
+ scanFilesInDirectory(tlcLBPath(isReadonly), convert, 0);
return TAC_ERROR_NONE;
}
#define __XSTR(x) #x
#define __STR(x) __XSTR(x)
static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
+static const char* __READ_ONLY_TAC_DIR = __STR(READ_ONLY_TAC_DIR);
#undef __STR
#undef __XSTR
return 0;
}
-int tac_createDB()
+int tac_createDB(bool isReadonly)
{
- tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE);
+ std::string tacDbPath = tacDBPath(isReadonly, TAC_APP_LIST_DB);
+ tac_db = createDB(tacDbPath, CREATE_TAC_DB_TABLE);
if (!tac_db) {
_ERR("Sqlite create error. So restore the database.");
- if (tac_restoreDB() != TAC_ERROR_NONE) {
+ if (tac_restoreDB(isReadonly) != TAC_ERROR_NONE) {
_ERR("Sqlite create error");
return -1;
}
- tac_db = createDB(TAC_APP_LIST_DB, CREATE_TAC_DB_TABLE);
+ tac_db = createDB(tacDbPath, CREATE_TAC_DB_TABLE);
if (!tac_db) {
_ERR("Sqlite create error");
return -1;
return 0;
}
-int tac_openDB()
+int tac_openDB(bool isReadonly)
{
- tac_db = openDB(TAC_APP_LIST_DB);
+ std::string tacDbPath = tacDBPath(isReadonly, TAC_APP_LIST_DB);
+ tac_db = openDB(tacDbPath);
if (!tac_db) {
_ERR("Sqlite open error. So restore the database.");
- if (tac_restoreDB() != TAC_ERROR_NONE) {
+ if (tac_restoreDB(isReadonly) != TAC_ERROR_NONE) {
_ERR("Sqlite open error");
return -1;
}
- tac_db = openDB(TAC_APP_LIST_DB);
+ tac_db = openDB(tacDbPath);
if (!tac_db) {
_ERR("Sqlite open error");
return -1;
return false;
}
-int tlc_createDB()
+int tlc_createDB(bool isReadonly)
{
- if (!createDir(TLC_LIBRARIES_DIR)) {
- _ERR("Cannot create directory: %s", TLC_LIBRARIES_DIR);
+ std::string tlcPath = tlcLBPath(isReadonly);
+ if (!createDir(tlcPath)) {
+ _ERR("Cannot create directory: %s", tlcPath.c_str());
return -1;
}
- copySmackAndOwnership(__DOTNET_DIR, TLC_LIBRARIES_DIR);
+ std::string tacLocation = isReadonly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
+ copySmackAndOwnership(tacLocation, tlcPath);
- tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE);
+ std::string tlcDbPath = tacDBPath(isReadonly, TLC_APP_LIST_DB);
+ tlc_db = createDB(tlcDbPath, CREATE_TLC_DB_TABLE);
if (!tlc_db) {
_ERR("Sqlite create error. So restore the database.");
- if (tlc_restoreDB() != TAC_ERROR_NONE) {
+ if (tlc_restoreDB(isReadonly) != TAC_ERROR_NONE) {
_ERR("Sqlite create error");
return -1;
}
- tlc_db = createDB(TLC_APP_LIST_DB, CREATE_TLC_DB_TABLE);
+ tlc_db = createDB(tlcDbPath, CREATE_TLC_DB_TABLE);
if (!tlc_db) {
_ERR("Sqlite create error");
return -1;
return 0;
}
-int tlc_openDB()
+int tlc_openDB(bool isReadonly)
{
- tlc_db = openDB(TLC_APP_LIST_DB);
+ std::string tlcDbPath = tacDBPath(isReadonly, TLC_APP_LIST_DB);
+ tlc_db = openDB(tlcDbPath);
if (!tlc_db) {
_ERR("Sqlite open error. So restore the database.");
- if (tlc_restoreDB() != TAC_ERROR_NONE) {
+ if (tlc_restoreDB(isReadonly) != TAC_ERROR_NONE) {
_ERR("Sqlite open error");
return 0;
}
- tlc_db = openDB(TLC_APP_LIST_DB);
+ tlc_db = openDB(tlcDbPath);
if (!tlc_db) {
_ERR("Sqlite open error");
return 0;
#define __XSTR(x) #x
#define __STR(x) __XSTR(x)
static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
+static const char* __READ_ONLY_TAC_DIR = __STR(READ_ONLY_TAC_DIR);
#undef __STR
#undef __XSTR
static tac_state tacState = TAC_STATE_NONE;
static std::string prevInstallPkgId = std::string("");
static std::string prevFinishPkgId = std::string("");
+static std::string tacLocation = __DOTNET_DIR;
+static bool isTacReadonly = false;
// initialize static vector to support multi-package install scenario
static void tacInitialize()
static bool copyAssemblyCreateSymlink(std::string binPath, std::string tacDir, std::string nugetPackage, bool isCreateTacDir)
{
std::string binNiPath = concatPath(binPath, APP_NI_SUB_DIR);
- std::string tac_version_dir = concatPath(__DOTNET_DIR, nugetPackage);
+ std::string tac_version_dir = concatPath(tacLocation, nugetPackage);
bool nuget_restoration = false;
for (auto& npAssemblySha : nugetPackagesAssembliesSha) {
std::string nuget_package_assembly = npAssemblySha.substr(0, npAssemblySha.rfind(':'));
break;
}
if (exist(concatPath(tac_version_dir, niFile)) && exist(binNiPath)) {
- bf::create_symlink(concatPath(tac_version_dir, niFile), concatPath(tacDir, niFile), error);
+ bf::create_symlink(concatPath(tac_version_dir, niFile), concatPath(tacDir, assembly), error);
if (error) {
- _ERR("Failed to create symlink %s file", concatPath(tacDir, niFile).c_str());
+ _ERR("Failed to create symlink %s file", concatPath(tacDir, assembly).c_str());
}
}
std::string library = librarySha.substr(0, librarySha.find(':'));
std::string filename = library.substr(library.rfind('/') + 1);
std::string fileSha = filename + ".." + librarySha.substr(librarySha.find(':') + 1);
- std::string shaPath = concatPath(TLC_LIBRARIES_DIR, fileSha);
+ std::string shaPath = concatPath(tlcLBPath(isTacReadonly), fileSha);
bool fileCopied = false;
if (!exist(shaPath)) {
if (!copyFile(library, shaPath)) {
_INFO("TAC version : %s", tac_version.c_str());
bs::error_code error;
- std::string tac_version_dir = concatPath(__DOTNET_DIR, np);
+ std::string tac_version_dir = concatPath(tacLocation, np);
std::string sha256_info = concatPath(tac_version_dir, TAC_SHA_256_INFO);
bool isCreateTacDir = false;
if (!exist(tac_version_dir)) {
}
if (count == 0) {
- std::string tac_version_dir_prev = concatPath(__DOTNET_DIR, unp);
+ std::string tac_version_dir_prev = concatPath(tacLocation, unp);
std::string tac_version_dir_backup = tac_version_dir_prev + ".bck";
if (!copyDir(tac_version_dir_prev, tac_version_dir_backup)) {
_ERR("Failed to copy of %s to %s", tac_version_dir_prev.c_str(), tac_version_dir_backup.c_str());
}
if (count == 0) {
- std::string library_prev = concatPath(TLC_LIBRARIES_DIR, ulp);
+ std::string library_prev = concatPath(tlcLBPath(isTacReadonly), ulp);
std::string library_backup = library_prev + ".bck";
if (!copyFile(library_prev, library_backup)) {
_ERR("Failed to copy of %s", library_prev.c_str());
tacInitialize();
+ isTacReadonly = isReadOnlyPkg(pkgId);
+ tacLocation = isTacReadonly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
+
// Can be multiple apps in one package
if (strcmp(pkgId.c_str(), prevInstallPkgId.c_str()) == 0) {
_INFO("TAC Plugin(INSTALL) already run for same pkgId (%s)", pkgId.c_str());
return 0;
}
- if (tac_createDB() != 0) {
+ if (tac_createDB(isTacReadonly) != 0) {
return -1;
}
}
///// TLC /////
- if (tlc_createDB() != 0) {
+ if (tlc_createDB(isTacReadonly) != 0) {
tac_closeDB();
return -1;
}
tacInitialize();
+ isTacReadonly = isReadOnlyPkg(pkgId);
+ tacLocation = isTacReadonly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
+
// Can be multiple apps in one package
if (strcmp(pkgId.c_str(), prevInstallPkgId.c_str()) == 0) {
_INFO("TAC Plugin(UPGRADE) already run for same pkgId (%s)", pkgId.c_str());
}
tacState = TAC_STATE_UPGRADE;
- if (tac_createDB() != 0) {
+ if (tac_createDB(isTacReadonly) != 0) {
return -1;
}
}
///// TLC /////
- if (tlc_createDB() != 0) {
+ if (tlc_createDB(isTacReadonly) != 0) {
tac_closeDB();
return -1;
}
tacInitialize();
+ isTacReadonly = isReadOnlyPkg(pkgId);
+ tacLocation = isTacReadonly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
+
// Can be multiple apps in one package
if (strcmp(pkgId.c_str(), prevInstallPkgId.c_str()) == 0) {
_INFO("TAC Plugin(UNINSTALL) already run for same pkgId (%s)", pkgId.c_str());
prevInstallPkgId = pkgId;
tacState= state;
- if (tac_openDB() != 0) {
+ if (tac_openDB(isTacReadonly) != 0) {
return -1;
}
tacUpdateDB(pkgId);
///// TLC /////
- if (tlc_openDB() != 0) {
+ if (tlc_openDB(isTacReadonly) != 0) {
tac_closeDB();
return -1;
}
void undoStep(std::string tac)
{
- std::string current_tac = concatPath(__DOTNET_DIR, tac.substr(0, tac.find('/')));
+ std::string current_tac = concatPath(tacLocation, tac.substr(0, tac.find('/')));
try {
for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
std::string bck_path = bck.path().string();
}
};
- scanFilesInDirectory(TLC_LIBRARIES_DIR, convert, 0);
+ scanFilesInDirectory(tlcLBPath(isTacReadonly), convert, 0);
}
void install_Undo()
_DBG("[===== PKGMGR_MDPARSER_PLUGIN_UNDO =====]");
_INFO("PackageID : %s", pkgId.c_str());
+ isTacReadonly = isReadOnlyPkg(pkgId);
+ tacLocation = isTacReadonly ? __READ_ONLY_TAC_DIR : __DOTNET_DIR;
+
// Can be multiple apps in one package
if (strcmp(pkgId.c_str(), prevFinishPkgId.c_str()) == 0) {
_INFO("TAC Plugin(UNDO) already run for same pkgId (%s)", pkgId.c_str());
void changeOwnershipTAC(std::string current_tac)
{
- copySmackAndOwnership(__DOTNET_DIR, current_tac);
+ copySmackAndOwnership(tacLocation, current_tac);
try {
for (auto& path : bf::recursive_directory_iterator(current_tac))
- copySmackAndOwnership(__DOTNET_DIR, path.path().string());
+ copySmackAndOwnership(tacLocation, path.path().string());
} catch (const bf::filesystem_error& error) {
_ERR("Failed to recursive directory: %s", error.what());
}
void cleanStep(std::string tac)
{
- std::string current_tac = concatPath(__DOTNET_DIR, tac.substr(0, tac.find('/')));
+ std::string current_tac = concatPath(tacLocation, tac.substr(0, tac.find('/')));
try {
for (auto& bck : bf::recursive_directory_iterator(current_tac)) {
std::string bck_path = bck.path().string();
}
};
- scanFilesInDirectory(TLC_LIBRARIES_DIR, convert, 0);
+ scanFilesInDirectory(tlcLBPath(isTacReadonly), convert, 0);
}
void install_Clean()
{
for (auto& cd : createDirectories) {
changeOwnershipTAC(cd);
- copySmackAndOwnership(__DOTNET_DIR, cd.substr(0, cd.rfind('/')));
+ copySmackAndOwnership(tacLocation, cd.substr(0, cd.rfind('/')));
}
for (auto& cl : createLibraries) {
- copySmackAndOwnership(__DOTNET_DIR, cl);
+ copySmackAndOwnership(tacLocation, cl);
}
}
if (!tacDB.empty()) {
for (auto& np : tacDB) {
cleanStep(np);
- changeOwnershipTAC(concatPath(__DOTNET_DIR, np.substr(0, np.find('/'))));
+ changeOwnershipTAC(concatPath(tacLocation, np.substr(0, np.find('/'))));
}
}
unInstall_Clean();
}
if (tac_closeDB()) {
- copySmackAndOwnership(__DOTNET_DIR, TAC_APP_LIST_DB);
- copySmackAndOwnership(__DOTNET_DIR, TAC_APP_LIST_DB + std::string("-journal"));
+ std::string tacDbPath = tacDBPath(isTacReadonly, TAC_APP_LIST_DB);
+ copySmackAndOwnership(tacLocation, tacDbPath);
+ copySmackAndOwnership(tacLocation, tacDbPath + std::string("-journal"));
}
if (tlc_closeDB()) {
- copySmackAndOwnership(__DOTNET_DIR, TLC_APP_LIST_DB);
- copySmackAndOwnership(__DOTNET_DIR, TLC_APP_LIST_DB + std::string("-journal"));
+ std::string tlcDbPath = tacDBPath(isTacReadonly, TLC_APP_LIST_DB);
+ copySmackAndOwnership(tacLocation, tlcDbPath);
+ copySmackAndOwnership(tacLocation, tlcDbPath + std::string("-journal"));
}
return 0;
appTacPath = concatPath(appBinPath, TAC_SYMLINK_SUB_DIR);
appPaths = appRootPath + ":" + appBinPath + ":" + appLibPath + ":" + appTacPath;
appNIPaths = appNIBinPath + ":" + appNILibPath + ":" + appTacPath;
+ appCLRPaths = appNIPaths + ":" + appPaths;
if (!extraDllPaths.empty()) {
appPaths = appPaths + ":" + extraDllPaths;
appNIPaths = appNIPaths + ":" + extraDllPaths;
+ appCLRPaths = appCLRPaths + ":" + extraDllPaths;
}
}
if (!extraDllPaths.empty()) {
appPaths = appPaths + ":" + extraDllPaths;
appNIPaths = appNIPaths + ":" + extraDllPaths;
+ appCLRPaths = appCLRPaths + ":" + extraDllPaths;
}
}
return appNIPaths;
}
+// return ni dll and dll searching paths for app
+const std::string& PathManager::getAppCLRPaths()
+{
+ return appCLRPaths;
+}
+
// return native dll searching paths for app
const std::string& PathManager::getNativeDllSearchingPaths()
{
#include "path_manager.h"
#include "r2r_checker.h"
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+static const char* __DOTNET_DIR = __STR(DOTNET_DIR);
+static const char* __READ_ONLY_TAC_DIR = __STR(READ_ONLY_TAC_DIR);
+#undef __STR
+#undef __XSTR
+
static bool iCompare(const std::string& a, int aOffset, const std::string& b, int bOffset, int length)
{
return static_cast<int>(a.length()) - length >= aOffset &&
return iCompare(fileName, fileName.size()-4, ".dll", 0, 4);
}
+bool isNativeImage(const std::string& fileName)
+{
+ return iCompare(fileName, fileName.size()-7, ".ni", 0, 3);
+}
+
std::string concatPath(const std::string& path1, const std::string& path2)
{
std::string path(path1);
}
+bool isReadOnlyPkg(const std::string& pkgId)
+{
+ uid_t uid = 0;
+ int ret = 0;
+ bool readonly = false;
+ pkgmgrinfo_pkginfo_h handle;
+
+ if (pkgmgr_installer_info_get_target_uid(&uid) < 0) {
+ _ERR("Failed to get UID");
+ return false;
+ }
+
+ ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgId.c_str(), uid, &handle);
+ if (ret != PMINFO_R_OK) {
+ _ERR("Fail to get pkginfo");
+ return false;
+ }
+
+ ret = pkgmgrinfo_pkginfo_is_readonly(handle, &readonly);
+ if (ret != PMINFO_R_OK) {
+ _ERR("Fail to get is_readonly");
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return false;
+ }
+
+ pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+ return readonly;
+}
+
+std::string tacDBPath(bool isReadonly, const std::string& dbName)
+{
+ return isReadonly ? concatPath(__READ_ONLY_TAC_DIR, dbName) : concatPath(__DOTNET_DIR, dbName);
+}
+
+std::string tlcLBPath(bool isReadonly)
+{
+ return isReadonly ? concatPath(__READ_ONLY_TAC_DIR, TLC_LIBRARIES_DIR) : concatPath(__DOTNET_DIR, TLC_LIBRARIES_DIR);
+}
+
std::string getBaseName(const std::string& path)
{
auto pos = path.find_last_of(PATH_SEPARATOR);
std::string changeExtension(const std::string& path, const std::string& from, const std::string& to)
{
- return path.substr(0, path.rfind(from)) + to;
+ std::string result = path;
+ if (path.rfind(from) != std::string::npos) {
+ result = path.substr(0, path.rfind(from)) + to;
+ }
+ return result;
}
bool isFile(const std::string& path)
</request>
<assign>
<filesystem path="/opt/usr/dotnet" label="System::Shared" type="transmutable" />
+ <filesystem path="/usr/share/dotnet.tizen/tac" label="System::Shared" type="transmutable" />
<filesystem path="/opt/usr/dotnet/apps" label="User::Home"/>
<filesystem path="/usr/bin/dotnet-loader" label="User" exec_label="User" />
<filesystem path="/usr/bin/dotnet-hydra-loader" label="User" exec_label="User" />
PATH=/usr/bin:/bin:/usr/sbin:/sbin
+# remove application native image files of RO app
+rm -rf /opt/usr/dotnet/apps/*
+
/usr/bin/dotnettool --tac-regen-all
/usr/bin/dotnettool --ni-regen-all-app --skip-ro-app
/usr/bin/dotnettool --resolve-all-app
%define _native_lib_dir /usr/share/dotnet.tizen/lib
%define _dotnet_dir /opt/usr/dotnet
%define _readonly_app_update_dir /opt/usr/dotnet/apps
+%define _readonly_tac_dir /usr/share/dotnet.tizen/tac
%define _system_base_addr_file /opt/usr/dotnet.system.base.addr
%define _tizen_preload_dir /usr/share/dotnet.tizen/preload
-DINSTALL_PLUGIN_DIR=%{_install_plugin_dir} \
-DDOTNET_DIR=%{_dotnet_dir} \
-DREAD_ONLY_APP_UPDATE_DIR=%{_readonly_app_update_dir} \
+ -DREAD_ONLY_TAC_DIR=%{_readonly_tac_dir} \
-DVERSION=%{version} \
-DNATIVE_LIB_DIR=%{_native_lib_dir} \
%ifarch %{arm} aarch64
mkdir -p %{buildroot}%{_dotnet_dir}
mkdir -p %{buildroot}%{_readonly_app_update_dir}
+mkdir -p %{buildroot}%{_readonly_tac_dir}
mkdir -p %{buildroot}%{_native_lib_dir}
ln -sf %{_libdir}/libsqlite3.so.0 %{buildroot}%{_native_lib_dir}/libsqlite3.so
%{_framework_dir}/Tizen.Runtime.dll
%{_dotnet_dir}
%{_readonly_app_update_dir}
+%{_readonly_tac_dir}
%{_tizen_preload_dir}
%{_rw_update_scripts_dir}/%{_rw_dotnet_update_script}
%if 0%{_build_dotnet_plugin}
--- /dev/null
+#!/bin/bash
+html_content="$(cat $2)"
+
+json_payload=$(jq -n --arg body "$html_content" '{"body": $body}')
+echo "[GITHUB COMMENT] json_payload --> ${json_payload}"
+
+curl -L \
+ -X POST \
+ -H "Accept: application/vnd.github+json" \
+ -H "Authorization: Bearer $JH_GITHUB_TOKEN" \
+ https://github.sec.samsung.net/api/v3/repos/dotnet/launcher/issues/$1/comments \
+ -d "$json_payload"
+
+exit 0
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio Version 17\r
+VisualStudioVersion = 17.5.33627.172\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher_TC_EXCEPTION_01", "Launcher_TC_EXCEPTION_01\Launcher_TC_EXCEPTION_01.csproj", "{54606EFF-D558-4127-97BF-7020DCED4DA7}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|Any CPU = Debug|Any CPU\r
+ Release|Any CPU = Release|Any CPU\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {54606EFF-D558-4127-97BF-7020DCED4DA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {54606EFF-D558-4127-97BF-7020DCED4DA7}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+ {54606EFF-D558-4127-97BF-7020DCED4DA7}.Debug|Any CPU.Deploy.0 = Debug|Any CPU\r
+ {54606EFF-D558-4127-97BF-7020DCED4DA7}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+ {54606EFF-D558-4127-97BF-7020DCED4DA7}.Release|Any CPU.Build.0 = Release|Any CPU\r
+ {54606EFF-D558-4127-97BF-7020DCED4DA7}.Release|Any CPU.Deploy.0 = Release|Any CPU\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+ GlobalSection(ExtensibilityGlobals) = postSolution\r
+ SolutionGuid = {988BEE6E-FFA8-4340-BED5-A5CD6478EC93}\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+using System;\r
+using Tizen.NUI;\r
+using Tizen.NUI.BaseComponents;\r
+\r
+namespace Launcher_TC_EXCEPTION_01\r
+{\r
+ internal class Program : NUIApplication\r
+ {\r
+ private void ExceptionTest()\r
+ {\r
+ string foo = null;\r
+ foo.ToUpper();\r
+ }\r
+\r
+ public void TC()\r
+ {\r
+ try\r
+ {\r
+ ExceptionTest();\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ Console.WriteLine(e.Message);\r
+ Console.WriteLine(e.ToString());\r
+ }\r
+ }\r
+\r
+ protected override void OnCreate()\r
+ {\r
+ base.OnCreate();\r
+ Initialize();\r
+ TC();\r
+ }\r
+\r
+ void Initialize()\r
+ {\r
+ Window.Instance.KeyEvent += OnKeyEvent;\r
+\r
+ TextLabel text = new TextLabel("Hello Tizen NUI World");\r
+ text.HorizontalAlignment = HorizontalAlignment.Center;\r
+ text.VerticalAlignment = VerticalAlignment.Center;\r
+ text.TextColor = Color.Blue;\r
+ text.PointSize = 30.0f;\r
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;\r
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;\r
+ Window.Instance.GetDefaultLayer().Add(text);\r
+\r
+ Animation animation = new Animation(2000);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(180.0f)), PositionAxis.X), 0, 500);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(0.0f)), PositionAxis.X), 500, 1000);\r
+ animation.Looping = true;\r
+ animation.Play();\r
+ }\r
+\r
+ public void OnKeyEvent(object sender, Window.KeyEventArgs e)\r
+ {\r
+ if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))\r
+ {\r
+ Exit();\r
+ }\r
+ }\r
+\r
+ static void Main(string[] args)\r
+ {\r
+ var app = new Program();\r
+ app.Run(args);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<Project Sdk="Tizen.NET.Sdk/1.0.9">\r
+\r
+ <PropertyGroup>\r
+ <OutputType>Exe</OutputType>\r
+ <TargetFramework>tizen60</TargetFramework>\r
+ </PropertyGroup>\r
+\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+ <DebugType>portable</DebugType>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+ <DebugType>None</DebugType>\r
+ </PropertyGroup>\r
+\r
+ <ItemGroup>\r
+ <Folder Include="lib\" />\r
+ <Folder Include="res\" />\r
+ </ItemGroup>\r
+\r
+ <ItemGroup>\r
+ <PackageReference Include="Tizen.NET.TV" Version="5.5.0.4922">\r
+ <ExcludeAssets>Runtime</ExcludeAssets>\r
+ </PackageReference>\r
+\r
+ </ItemGroup>\r
+\r
+</Project>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<manifest xmlns="http://tizen.org/ns/packages" api-version="6.5" package="org.tizen.example.Launcher_TC_EXCEPTION_01" version="1.0.0">\r
+ <feature name="http://tizen.org/feature/screen.size.normal.1080.1920">true</feature>\r
+ <profile name="common" />\r
+ <ui-application appid="org.tizen.example.Launcher_TC_EXCEPTION_01"\r
+ exec="Launcher_TC_EXCEPTION_01.dll"\r
+ type="dotnet"\r
+ multiple="false"\r
+ taskmanage="true"\r
+ nodisplay="false"\r
+ launch_mode="single">\r
+ <label>Launcher_TC_EXCEPTION_01</label>\r
+ <icon>Launcher_TC_EXCEPTION_01.png</icon>\r
+ </ui-application>\r
+ <tv-info api-version="9.9.0">\r
+ <infolink>T-INFOLINK2022-1000</infolink>\r
+ </tv-info>\r
+</manifest>\r
--- /dev/null
+\r
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio Version 17\r
+VisualStudioVersion = 17.5.33627.172\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher_TC_EXCEPTION_02", "Launcher_TC_EXCEPTION_02\Launcher_TC_EXCEPTION_02.csproj", "{56FEFF50-B69E-4FA4-BC8C-3717101E3506}"\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|Any CPU = Debug|Any CPU\r
+ Release|Any CPU = Release|Any CPU\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {56FEFF50-B69E-4FA4-BC8C-3717101E3506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {56FEFF50-B69E-4FA4-BC8C-3717101E3506}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+ {56FEFF50-B69E-4FA4-BC8C-3717101E3506}.Debug|Any CPU.Deploy.0 = Debug|Any CPU\r
+ {56FEFF50-B69E-4FA4-BC8C-3717101E3506}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+ {56FEFF50-B69E-4FA4-BC8C-3717101E3506}.Release|Any CPU.Build.0 = Release|Any CPU\r
+ {56FEFF50-B69E-4FA4-BC8C-3717101E3506}.Release|Any CPU.Deploy.0 = Release|Any CPU\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+ GlobalSection(ExtensibilityGlobals) = postSolution\r
+ SolutionGuid = {54AA6825-7BE4-4AF0-A5AB-6FBCC23E26D3}\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+using System;\r
+using Tizen.NUI;\r
+using Tizen.NUI.BaseComponents;\r
+\r
+namespace Launcher_TC_EXCEPTION_02\r
+{\r
+ internal class Program : NUIApplication\r
+ {\r
+ private void ExceptionTest()\r
+ {\r
+ string foo = null;\r
+ foo.ToUpper();\r
+ }\r
+\r
+ public void TC()\r
+ {\r
+ try\r
+ {\r
+ ExceptionTest();\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ Console.WriteLine(e.Message);\r
+ Console.WriteLine(e.ToString());\r
+ }\r
+ }\r
+\r
+ protected override void OnCreate()\r
+ {\r
+ base.OnCreate();\r
+ Initialize();\r
+ TC();\r
+ }\r
+\r
+ void Initialize()\r
+ {\r
+ Window.Instance.KeyEvent += OnKeyEvent;\r
+\r
+ TextLabel text = new TextLabel("Hello Tizen NUI World");\r
+ text.HorizontalAlignment = HorizontalAlignment.Center;\r
+ text.VerticalAlignment = VerticalAlignment.Center;\r
+ text.TextColor = Color.Blue;\r
+ text.PointSize = 30.0f;\r
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;\r
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;\r
+ Window.Instance.GetDefaultLayer().Add(text);\r
+\r
+ Animation animation = new Animation(2000);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(180.0f)), PositionAxis.X), 0, 500);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(0.0f)), PositionAxis.X), 500, 1000);\r
+ animation.Looping = true;\r
+ animation.Play();\r
+ }\r
+\r
+ public void OnKeyEvent(object sender, Window.KeyEventArgs e)\r
+ {\r
+ if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))\r
+ {\r
+ Exit();\r
+ }\r
+ }\r
+\r
+ static void Main(string[] args)\r
+ {\r
+ var app = new Program();\r
+ app.Run(args);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<Project Sdk="Tizen.NET.Sdk/1.0.9">\r
+\r
+ <PropertyGroup>\r
+ <OutputType>Exe</OutputType>\r
+ <TargetFramework>tizen60</TargetFramework>\r
+ </PropertyGroup>\r
+\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+ <DebugType>portable</DebugType>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+ <DebugType>None</DebugType>\r
+ </PropertyGroup>\r
+\r
+ <ItemGroup>\r
+ <Folder Include="lib\" />\r
+ <Folder Include="res\" />\r
+ </ItemGroup>\r
+\r
+ <ItemGroup>\r
+ <PackageReference Include="Tizen.NET.TV" Version="5.5.0.4922">\r
+ <ExcludeAssets>Runtime</ExcludeAssets>\r
+ </PackageReference>\r
+\r
+ </ItemGroup>\r
+\r
+</Project>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<manifest xmlns="http://tizen.org/ns/packages" api-version="6.5" package="org.tizen.example.Launcher_TC_EXCEPTION_02" version="1.0.0">\r
+ <feature name="http://tizen.org/feature/screen.size.normal.1080.1920">true</feature>\r
+ <profile name="common" />\r
+ <ui-application appid="org.tizen.example.Launcher_TC_EXCEPTION_02"\r
+ exec="Launcher_TC_EXCEPTION_02.dll"\r
+ type="dotnet-nui"\r
+ multiple="false"\r
+ taskmanage="true"\r
+ nodisplay="false"\r
+ launch_mode="single">\r
+ <label>Launcher_TC_EXCEPTION_02</label>\r
+ <icon>Launcher_TC_EXCEPTION_02.png</icon>\r
+ </ui-application>\r
+ <tv-info api-version="9.9.0">\r
+ <infolink>T-INFOLINK2022-1000</infolink>\r
+ </tv-info>\r
+</manifest>\r
--- /dev/null
+Microsoft Visual Studio Solution File, Format Version 12.00\r
+# Visual Studio Version 16\r
+VisualStudioVersion = 16.0.31005.135\r
+MinimumVisualStudioVersion = 10.0.40219.1\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Launcher_TC_PLUGIN_11", "Launcher_TC_PLUGIN_11\Launcher_TC_PLUGIN_11.csproj", "{3daa496e-195a-4708-8316-dd6207adbd9a}"\r
+EndProject\r
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{c9bd2802-b0a0-41c2-9453-e159261615bc}"\r
+ ProjectSection(SolutionItems) = preProject\r
+ tizen_workspace.yaml = tizen_workspace.yaml\r
+ EndProjectSection\r
+EndProject\r
+Global\r
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
+ Debug|Any CPU = Debug|Any CPU\r
+ Release|Any CPU = Release|Any CPU\r
+ EndGlobalSection\r
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {3daa496e-195a-4708-8316-dd6207adbd9a}.Debug|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {3daa496e-195a-4708-8316-dd6207adbd9a}.Debug|Any CPU.Build.0 = Debug|Any CPU\r
+ {3daa496e-195a-4708-8316-dd6207adbd9a}.Release|Any CPU.ActiveCfg = Release|Any CPU\r
+ {3daa496e-195a-4708-8316-dd6207adbd9a}.Release|Any CPU.Build.0 = Release|Any CPU\r
+\r
+ EndGlobalSection\r
+ GlobalSection(SolutionProperties) = preSolution\r
+ HideSolutionNode = FALSE\r
+ EndGlobalSection\r
+EndGlobal\r
--- /dev/null
+<!--\r
+***********************************************************************************************\r
+<Build.Directory.targets>\r
+WARNING: DO NOT MODIFY this file. Incorrect changes to this file will make it\r
+ impossible to load or build your projects from the IDE.\r
+\r
+***********************************************************************************************\r
+-->\r
+\r
+<Project> \r
+ <Target Name="BuildDotnet" AfterTargets="TizenPackage" >\r
+ <Message Text="Tizen Build starts here ------------" Importance="high"/>\r
+ <Message Text="$(MSBuildProjectDirectory)" Importance="high"/>\r
+ <PropertyGroup>\r
+ <WorkspaceFolder>$([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))</WorkspaceFolder>\r
+ </PropertyGroup>\r
+ <Message Text="Workspace: '$(WorkspaceFolder)'" Importance="high" />\r
+\r
+ <Exec Command="C:\tizen-studio\tools\tizen-core\tz.exe pack -S $(ProjectDir) $(WorkspaceFolder)"> </Exec>\r
+ </Target>\r
+</Project>\r
--- /dev/null
+using System;\r
+using Tizen.NUI;\r
+using Tizen.NUI.BaseComponents;\r
+\r
+namespace Launcher_TC_PLUGIN_11\r
+{\r
+ class Program : NUIApplication\r
+ {\r
+ protected override void OnCreate()\r
+ {\r
+ base.OnCreate();\r
+ Initialize();\r
+ }\r
+\r
+ void Initialize()\r
+ {\r
+ Window.Instance.KeyEvent += OnKeyEvent;\r
+\r
+ TextLabel text = new TextLabel("Hello Tizen NUI World");\r
+ text.HorizontalAlignment = HorizontalAlignment.Center;\r
+ text.VerticalAlignment = VerticalAlignment.Center;\r
+ text.TextColor = Color.Blue;\r
+ text.PointSize = 12.0f;\r
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;\r
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;\r
+ Window.Instance.GetDefaultLayer().Add(text);\r
+\r
+ Animation animation = new Animation(2000);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(180.0f)), PositionAxis.X), 0, 500);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(0.0f)), PositionAxis.X), 500, 1000);\r
+ animation.Looping = true;\r
+ animation.Play();\r
+ }\r
+\r
+ public void OnKeyEvent(object sender, Window.KeyEventArgs e)\r
+ {\r
+ if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))\r
+ {\r
+ Exit();\r
+ }\r
+ }\r
+\r
+ static void Main(string[] args)\r
+ {\r
+ var app = new Program();\r
+ app.Run(args);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+ <PropertyGroup>\r
+ <OutputType>Exe</OutputType>\r
+ <TargetFramework>net6.0-tizen</TargetFramework>\r
+ </PropertyGroup>\r
+\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+ <DebugType>portable</DebugType>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+ <DebugType>None</DebugType>\r
+ </PropertyGroup>\r
+\r
+ <ItemGroup>\r
+ <Folder Include="res\" />\r
+ </ItemGroup>\r
+\r
+</Project>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="9.0" package="org.tizen.example.Launcher_TC_PLUGIN_11" version="1.0.0">
+ <profile name="common" />
+ <ui-application appid="org.tizen.example.Launcher_TC_PLUGIN_11"
+ exec="Launcher_TC_PLUGIN_11.dll"
+ type="dotnet-nui"
+ multiple="false"
+ taskmanage="true"
+ nodisplay="false"
+ launch_mode="single"
+ api-version="12">
+ <label>Launcher_TC_PLUGIN_11</label>
+ <icon>Launcher_TC_PLUGIN_11.png</icon>
+ <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+ </ui-application>
+</manifest>
--- /dev/null
+# csproj file path
+csproj_file: Launcher_TC_PLUGIN_11.csproj
+
+# files monitored for dirty/modified status
+files:
+ - Launcher_TC_PLUGIN_11.csproj
+ - Launcher_TC_PLUGIN_11.cs
+ - tizen-manifest.xml
+ - shared/res/Launcher_TC_PLUGIN_11.png
\ No newline at end of file
--- /dev/null
+<!--\r
+***********************************************************************************************\r
+<Build.Directory.targets>\r
+WARNING: DO NOT MODIFY this file. Incorrect changes to this file will make it\r
+ impossible to load or build your projects from the IDE.\r
+\r
+***********************************************************************************************\r
+-->\r
+\r
+<Project> \r
+ <Target Name="BuildDotnet" AfterTargets="TizenPackage" >\r
+ <Message Text="Tizen Build starts here ------------" Importance="high"/>\r
+ <Message Text="$(MSBuildProjectDirectory)" Importance="high"/>\r
+ <PropertyGroup>\r
+ <WorkspaceFolder>$([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))</WorkspaceFolder>\r
+ </PropertyGroup>\r
+ <Message Text="Workspace: '$(WorkspaceFolder)'" Importance="high" />\r
+\r
+ <Exec Command="C:\tizen-studio\tools\tizen-core\tz.exe pack -S $(ProjectDir) $(WorkspaceFolder)"> </Exec>\r
+ </Target>\r
+</Project>\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroArguments\r
+ {\r
+ [Params(true, false)] // Arguments can be combined with Params\r
+ public bool AddExtra5Milliseconds;\r
+\r
+ [Benchmark]\r
+ [Arguments(100, 10)]\r
+ [Arguments(100, 20)]\r
+ [Arguments(200, 10)]\r
+ [Arguments(200, 20)]\r
+ public void Benchmark(int a, int b)\r
+ {\r
+ if (AddExtra5Milliseconds)\r
+ Thread.Sleep(a + b + 5);\r
+ else\r
+ Thread.Sleep(a + b);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroArgumentsSource\r
+ {\r
+ [Benchmark]\r
+ [ArgumentsSource(nameof(Numbers))]\r
+ public double ManyArguments(double x, double y) => Math.Pow(x, y);\r
+\r
+ public IEnumerable<object[]> Numbers() // for multiple arguments it's an IEnumerable of array of objects (object[])\r
+ {\r
+ yield return new object[] { 1.0, 1.0 };\r
+ yield return new object[] { 2.0, 2.0 };\r
+ yield return new object[] { 4.0, 4.0 };\r
+ yield return new object[] { 10.0, 10.0 };\r
+ }\r
+\r
+ [Benchmark]\r
+ [ArgumentsSource(nameof(TimeSpans))]\r
+ public void SingleArgument(TimeSpan time) => Thread.Sleep(time);\r
+\r
+ public IEnumerable<object> TimeSpans() // for single argument it's an IEnumerable of objects (object)\r
+ {\r
+ yield return TimeSpan.FromMilliseconds(10);\r
+ yield return TimeSpan.FromMilliseconds(100);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroArrayParam\r
+ {\r
+ [Benchmark]\r
+ [ArgumentsSource(nameof(Data))]\r
+ public int ArrayIndexOf(int[] array, int value)\r
+ => Array.IndexOf(array, value);\r
+\r
+ [Benchmark]\r
+ [ArgumentsSource(nameof(Data))]\r
+ public int ManualIndexOf(int[] array, int value)\r
+ {\r
+ for (int i = 0; i < array.Length; i++)\r
+ if (array[i] == value)\r
+ return i;\r
+\r
+ return -1;\r
+ }\r
+\r
+ public IEnumerable<object[]> Data()\r
+ {\r
+ yield return new object[] { new int[] { 1, 2, 3 }, 4 };\r
+ yield return new object[] { Enumerable.Range(0, 100).ToArray(), 4 };\r
+ yield return new object[] { Enumerable.Range(0, 100).ToArray(), 101 };\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // It is very easy to use BenchmarkDotNet. You should just create a class\r
+ public class IntroBasic\r
+ {\r
+ // And define a method with the Benchmark attribute\r
+ [Benchmark]\r
+ public void Sleep() => Thread.Sleep(10);\r
+\r
+ // You can write a description for your method.\r
+ [Benchmark(Description = "Thread.Sleep(10)")]\r
+ public void SleepWithDescription() => Thread.Sleep(10);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroBenchmarkBaseline\r
+ {\r
+ [Benchmark]\r
+ public void Time50() => Thread.Sleep(50);\r
+\r
+ [Benchmark(Baseline = true)]\r
+ public void Time100() => Thread.Sleep(100);\r
+\r
+ [Benchmark]\r
+ public void Time150() => Thread.Sleep(150);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DryJob]\r
+ [CategoriesColumn]\r
+ [BenchmarkCategory("Awesome")]\r
+ [AnyCategoriesFilter("A", "1")]\r
+ public class IntroCategories\r
+ {\r
+ [Benchmark]\r
+ [BenchmarkCategory("A", "1")]\r
+ public void A1() => Thread.Sleep(10); // Will be benchmarked\r
+\r
+ [Benchmark]\r
+ [BenchmarkCategory("A", "2")]\r
+ public void A2() => Thread.Sleep(10); // Will be benchmarked\r
+\r
+ [Benchmark]\r
+ [BenchmarkCategory("B", "1")]\r
+ public void B1() => Thread.Sleep(10); // Will be benchmarked\r
+\r
+ [Benchmark]\r
+ [BenchmarkCategory("B", "2")]\r
+ public void B2() => Thread.Sleep(10);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]\r
+ [CategoriesColumn]\r
+ public class IntroCategoryBaseline\r
+ {\r
+ [BenchmarkCategory("Fast"), Benchmark(Baseline = true)]\r
+ public void Time50() => Thread.Sleep(50);\r
+\r
+ [BenchmarkCategory("Fast"), Benchmark]\r
+ public void Time100() => Thread.Sleep(100);\r
+\r
+ [BenchmarkCategory("Slow"), Benchmark(Baseline = true)]\r
+ public void Time550() => Thread.Sleep(550);\r
+\r
+ [BenchmarkCategory("Slow"), Benchmark]\r
+ public void Time600() => Thread.Sleep(600);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Running;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Reflection;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DryJob]\r
+ [CategoriesColumn]\r
+ [CustomCategoryDiscoverer]\r
+ public class IntroCategoryDiscoverer\r
+ {\r
+ private class CustomCategoryDiscoverer : DefaultCategoryDiscoverer\r
+ {\r
+ public override string[] GetCategories(MethodInfo method)\r
+ {\r
+ var categories = new List<string>();\r
+ categories.AddRange(base.GetCategories(method));\r
+ categories.Add("All");\r
+ categories.Add(method.Name.Substring(0, 1));\r
+ return categories.ToArray();\r
+ }\r
+ }\r
+\r
+ [AttributeUsage(AttributeTargets.Class)]\r
+ private class CustomCategoryDiscovererAttribute : Attribute, IConfigSource\r
+ {\r
+ public CustomCategoryDiscovererAttribute()\r
+ {\r
+ Config = ManualConfig.CreateEmpty()\r
+ .WithCategoryDiscoverer(new CustomCategoryDiscoverer());\r
+ }\r
+\r
+ public IConfig Config { get; }\r
+ }\r
+\r
+\r
+ [Benchmark]\r
+ public void Foo() { }\r
+\r
+ [Benchmark]\r
+ public void Bar() { }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [SimpleJob(RunStrategy.ColdStart, iterationCount: 5)]\r
+ [MinColumn, MaxColumn, MeanColumn, MedianColumn]\r
+ public class IntroColdStart\r
+ {\r
+ private bool firstCall;\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ if (firstCall == false)\r
+ {\r
+ firstCall = true;\r
+ Console.WriteLine("// First call");\r
+ Thread.Sleep(1000);\r
+ }\r
+ else\r
+ Thread.Sleep(10);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroComparableComplexParam\r
+ {\r
+ [ParamsSource(nameof(ValuesForA))]\r
+ public ComplexParam? A { get; set; }\r
+\r
+ public IEnumerable<ComplexParam> ValuesForA => new[] { new ComplexParam(1, "First"), new ComplexParam(2, "Second") };\r
+\r
+ [Benchmark]\r
+ public object? Benchmark() => A;\r
+\r
+ // Only non generic IComparable is required to provide custom order behavior, but implementing IComparable<> too is customary.\r
+ public class ComplexParam : IComparable<ComplexParam>, IComparable\r
+ {\r
+ public ComplexParam(int value, string name)\r
+ {\r
+ Value = value;\r
+ Name = name;\r
+ }\r
+\r
+ public int Value { get; set; }\r
+\r
+ public string Name { get; set; }\r
+\r
+ public override string ToString() => Name;\r
+\r
+ public int CompareTo(ComplexParam? other) => other == null ? 1 : Value.CompareTo(other.Value);\r
+\r
+ public int CompareTo(object obj) => obj is ComplexParam other ? CompareTo(other) : throw new ArgumentException();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [MyConfigSource(Jit.LegacyJit, Jit.RyuJit)]\r
+ public class IntroConfigSource\r
+ {\r
+ /// <summary>\r
+ /// Dry-x64 jobs for specific jits\r
+ /// </summary>\r
+ private class MyConfigSourceAttribute : Attribute, IConfigSource\r
+ {\r
+ public IConfig Config { get; }\r
+\r
+ public MyConfigSourceAttribute(params Jit[] jits)\r
+ {\r
+ var jobs = jits\r
+ .Select(jit => new Job(Job.Dry) { Environment = { Jit = jit, Platform = Platform.X64 } })\r
+ .ToArray();\r
+ Config = ManualConfig.CreateEmpty().AddJob(jobs);\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ Thread.Sleep(10);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Analysers;\r
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Columns;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Exporters.Csv;\r
+using BenchmarkDotNet.Exporters;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Loggers;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ public class IntroConfigUnion\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.Dry);\r
+ AddLogger(ConsoleLogger.Default);\r
+ AddColumn(TargetMethodColumn.Method, StatisticColumn.Max);\r
+ AddExporter(RPlotExporter.Default, CsvExporter.Default);\r
+ AddAnalyser(EnvironmentAnalyser.Default);\r
+ UnionRule = ConfigUnionRule.AlwaysUseLocal;\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ Thread.Sleep(10);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Running;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // *** Attribute Style ***\r
+\r
+ [MonoJob("Mono x64", @"C:\Program Files\Mono\bin\mono.exe")]\r
+ [MonoJob("Mono x86", @"C:\Program Files (x86)\Mono\bin\mono.exe")]\r
+ public class IntroCustomMono\r
+ {\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+\r
+ // *** Object Style ***\r
+\r
+ [Config(typeof(Config))]\r
+ public class IntroCustomMonoObjectStyle\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.ShortRun.WithRuntime(new MonoRuntime(\r
+ "Mono x64", @"C:\Program Files\Mono\bin\mono.exe")));\r
+ AddJob(Job.ShortRun.WithRuntime(new MonoRuntime(\r
+ "Mono x86", @"C:\Program Files (x86)\Mono\bin\mono.exe")));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+\r
+ // ** Object Style, Using AOT **\r
+\r
+ [Config(typeof(Config))]\r
+ public class IntroCustomMonoObjectStyleAot\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public void AddMono(string name, string mono_top_dir)\r
+ {\r
+ var aot_compile_args = "--aot=llvm";\r
+ var mono_bcl = $@"{mono_top_dir}\lib\mono\4.5";\r
+ var mono_bin = $@"{mono_top_dir}\bin\mono.exe";\r
+ AddJob(Job.ShortRun.WithRuntime(new MonoRuntime(\r
+ name, mono_bin, aot_compile_args, mono_bcl)));\r
+ }\r
+\r
+ public Config()\r
+ {\r
+ AddMono("Mono x64", @"C:\Program Files\Mono");\r
+ AddMono("Mono x86", @"C:\Program Files (x86)\Mono");\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+\r
+ // *** Fluent Config ***\r
+\r
+ public class IntroCustomMonoFluentConfig\r
+ {\r
+ public static void Run()\r
+ {\r
+ BenchmarkRunner.Run<IntroCustomMonoFluentConfig>(ManualConfig\r
+ .CreateMinimumViable()\r
+ .AddJob(Job.ShortRun.WithRuntime(new MonoRuntime(\r
+ "Mono x64", @"C:\Program Files\Mono\bin\mono.exe")))\r
+ .AddJob(Job.ShortRun.WithRuntime(new MonoRuntime(\r
+ "Mono x86", @"C:\Program Files (x86)\Mono\bin\mono.exe"))));\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(ConfigWithCustomArguments))]\r
+ public class IntroCustomMonoArguments\r
+ {\r
+ public class ConfigWithCustomArguments : ManualConfig\r
+ {\r
+ public ConfigWithCustomArguments()\r
+ {\r
+ // --optimize=MODE , -O=mode\r
+ // MODE is a comma separated list of optimizations. They also allow\r
+ // optimizations to be turned off by prefixing the optimization\r
+ // name with a minus sign.\r
+\r
+ AddJob(Job.Default\r
+ .WithRuntime(MonoRuntime.Default)\r
+ .WithArguments(new[] { new MonoArgument("--optimize=inline") })\r
+ .WithId("Inlining enabled"));\r
+ AddJob(Job.Default\r
+ .WithRuntime(MonoRuntime.Default)\r
+ .WithArguments(new[] { new MonoArgument("--optimize=-inline") })\r
+ .WithId("Inlining disabled"));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Sample()\r
+ {\r
+ ShouldGetInlined(); ShouldGetInlined(); ShouldGetInlined();\r
+ ShouldGetInlined(); ShouldGetInlined(); ShouldGetInlined();\r
+ ShouldGetInlined(); ShouldGetInlined(); ShouldGetInlined();\r
+ }\r
+\r
+ private void ShouldGetInlined() { }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroDeferredExecution\r
+ {\r
+ private readonly int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };\r
+\r
+ private readonly Consumer consumer = new Consumer();\r
+\r
+ /// <summary>\r
+ /// this benchmark returns a deferred LINQ query which is NOT executed\r
+ /// so the benchmark measures the cost of creating the query, not the actual execution\r
+ /// this is WRONG\r
+ /// You can read more about LINQ and Deferred Execution <see href="https://blogs.msdn.microsoft.com/charlie/2007/12/10/linq-and-deferred-execution/">here</see>\r
+ /// </summary>\r
+ /// <returns>deferred LINQ query</returns>\r
+ [Benchmark]\r
+ public IEnumerable<int> Wrong() => from number in numbers orderby number descending select number;\r
+\r
+ /// <summary>\r
+ /// this benchmark uses .Consume extension method which executes given deferred query and consumes its result\r
+ /// so the benchmark measures the cost of creating the query and executing it\r
+ /// </summary>\r
+ [Benchmark]\r
+ public void Ok() => (from number in numbers orderby number descending select number).Consume(consumer);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Diagnosers;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DisassemblyDiagnoser(printInstructionAddresses: true, syntax: DisassemblySyntax.Masm)]\r
+ public class IntroDisassembly\r
+ {\r
+ private int[] field = Enumerable.Range(0, 100).ToArray();\r
+\r
+ [Benchmark]\r
+ public int SumLocal()\r
+ {\r
+ var local = field; // we use local variable that points to the field\r
+\r
+ int sum = 0;\r
+ for (int i = 0; i < local.Length; i++)\r
+ sum += local[i];\r
+\r
+ return sum;\r
+ }\r
+\r
+ [Benchmark]\r
+ public int SumField()\r
+ {\r
+ int sum = 0;\r
+ for (int i = 0; i < field.Length; i++)\r
+ sum += field[i];\r
+\r
+ return sum;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Diagnosers;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(MultipleJits))]\r
+ public class IntroDisassemblyAllJits\r
+ {\r
+ public class MultipleJits : ManualConfig\r
+ {\r
+ public MultipleJits()\r
+ {\r
+ AddJob(Job.ShortRun.WithPlatform(Platform.X86).WithRuntime(new MonoRuntime(name: "Mono x86", customPath: @"C:\Program Files (x86)\Mono\bin\mono.exe")));\r
+ AddJob(Job.ShortRun.WithPlatform(Platform.X64).WithRuntime(new MonoRuntime(name: "Mono x64", customPath: @"C:\Program Files\Mono\bin\mono.exe")));\r
+\r
+ AddJob(Job.ShortRun.WithJit(Jit.LegacyJit).WithPlatform(Platform.X86).WithRuntime(ClrRuntime.Net462));\r
+ AddJob(Job.ShortRun.WithJit(Jit.LegacyJit).WithPlatform(Platform.X64).WithRuntime(ClrRuntime.Net462));\r
+\r
+ AddJob(Job.ShortRun.WithJit(Jit.RyuJit).WithPlatform(Platform.X64).WithRuntime(ClrRuntime.Net462));\r
+\r
+ // RyuJit for .NET Core 5.0\r
+ AddJob(Job.ShortRun.WithJit(Jit.RyuJit).WithPlatform(Platform.X64).WithRuntime(CoreRuntime.Core50));\r
+\r
+ AddDiagnoser(new DisassemblyDiagnoser(new DisassemblyDiagnoserConfig(maxDepth: 3, exportDiff: true)));\r
+ }\r
+ }\r
+\r
+ private Increment increment = new Increment();\r
+\r
+ [Benchmark]\r
+ public int CallVirtualMethod() => increment.OperateTwice(10);\r
+\r
+ public abstract class Operation // abstract unary integer operation\r
+ {\r
+ public abstract int Operate(int input);\r
+\r
+ public int OperateTwice(int input) => Operate(Operate(input)); // two virtual calls to Operate\r
+ }\r
+\r
+ public sealed class Increment : Operation // concrete, sealed operation: increment by fixed amount\r
+ {\r
+ public readonly int Amount;\r
+ public Increment(int amount = 1) { Amount = amount; }\r
+\r
+ public override int Operate(int input) => input + Amount;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DisassemblyDiagnoser(maxDepth: 3)]\r
+ [DryJob]\r
+ public class IntroDisassemblyDry\r
+ {\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DisassemblyDiagnoser(printSource: true)]\r
+ [RyuJitX64Job]\r
+ public class IntroDisassemblyRyuJit\r
+ {\r
+ private int[] field = Enumerable.Range(0, 100).ToArray();\r
+\r
+ [Benchmark]\r
+ public int SumLocal()\r
+ {\r
+ var local = field; // we use local variable that points to the field\r
+\r
+ int sum = 0;\r
+ for (int i = 0; i < local.Length; i++)\r
+ sum += local[i];\r
+\r
+ return sum;\r
+ }\r
+\r
+ [Benchmark]\r
+ public int SumField()\r
+ {\r
+ int sum = 0;\r
+ for (int i = 0; i < field.Length; i++)\r
+ sum += field[i];\r
+\r
+ return sum;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Diagnostics.dotTrace;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // Enables dotTrace profiling for all jobs\r
+ [DotTraceDiagnoser]\r
+ // Adds the default "external-process" job\r
+ // Profiling is performed using dotTrace command-line Tools\r
+ // See: https://www.jetbrains.com/help/profiler/Performance_Profiling__Profiling_Using_the_Command_Line.html\r
+ [SimpleJob]\r
+ // Adds an "in-process" job\r
+ // Profiling is performed using dotTrace SelfApi\r
+ // NuGet reference: https://www.nuget.org/packages/JetBrains.Profiler.SelfApi\r
+ [InProcess]\r
+ public class IntroDotTraceDiagnoser\r
+ {\r
+ [Benchmark]\r
+ public void Fibonacci() => Fibonacci(30);\r
+\r
+ private static int Fibonacci(int n)\r
+ {\r
+ return n <= 1 ? n : Fibonacci(n - 1) + Fibonacci(n - 2);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(ConfigWithCustomEnvVars))]\r
+ public class IntroEnvVars\r
+ {\r
+ private class ConfigWithCustomEnvVars : ManualConfig\r
+ {\r
+ private const string JitNoInline = "COMPlus_JitNoInline";\r
+\r
+ public ConfigWithCustomEnvVars()\r
+ {\r
+ AddJob(Job.Default.WithRuntime(CoreRuntime.Core21).WithId("Inlining enabled"));\r
+ AddJob(Job.Default.WithRuntime(CoreRuntime.Core21)\r
+ .WithEnvironmentVariables(new EnvironmentVariable(JitNoInline, "1"))\r
+ .WithId("Inlining disabled"));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Diagnosers;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [ShortRunJob]\r
+ [EventPipeProfiler(EventPipeProfile.CpuSampling)]\r
+ public class IntroEventPipeProfiler\r
+ {\r
+ [Benchmark]\r
+ public void Sleep() => Thread.Sleep(2000);\r
+ }\r
+\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Diagnosers;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using Microsoft.Diagnostics.NETCore.Client;\r
+using Microsoft.Diagnostics.Tracing.Parsers;\r
+using System;\r
+using System.Buffers;\r
+using System.Collections.Generic;\r
+using System.Diagnostics.Tracing;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(CustomConfig))]\r
+ public class IntroEventPipeProfilerAdvanced\r
+ {\r
+ private class CustomConfig : ManualConfig\r
+ {\r
+ public CustomConfig()\r
+ {\r
+ AddJob(Job.ShortRun.WithRuntime(CoreRuntime.Core50));\r
+\r
+ var providers = new[]\r
+ {\r
+ new EventPipeProvider(ClrTraceEventParser.ProviderName, EventLevel.Verbose,\r
+ (long) (ClrTraceEventParser.Keywords.Exception\r
+ | ClrTraceEventParser.Keywords.GC\r
+ | ClrTraceEventParser.Keywords.Jit\r
+ | ClrTraceEventParser.Keywords.JitTracing // for the inlining events\r
+ | ClrTraceEventParser.Keywords.Loader\r
+ | ClrTraceEventParser.Keywords.NGen)),\r
+ new EventPipeProvider("System.Buffers.ArrayPoolEventSource", EventLevel.Informational, long.MaxValue),\r
+ };\r
+\r
+ AddDiagnoser(new EventPipeProfiler(providers: providers));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void RentAndReturn_Shared()\r
+ {\r
+ var pool = ArrayPool<byte>.Shared;\r
+ byte[] array = pool.Rent(10000);\r
+ pool.Return(array);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [ShortRunJob]\r
+ [MediumRunJob]\r
+ [KeepBenchmarkFiles]\r
+\r
+ [AsciiDocExporter]\r
+ [CsvExporter]\r
+ [CsvMeasurementsExporter]\r
+ [HtmlExporter]\r
+ [PlainExporter]\r
+ [RPlotExporter]\r
+ [JsonExporterAttribute.Brief]\r
+ [JsonExporterAttribute.BriefCompressed]\r
+ [JsonExporterAttribute.Full]\r
+ [JsonExporterAttribute.FullCompressed]\r
+ [MarkdownExporterAttribute.Default]\r
+ [MarkdownExporterAttribute.GitHub]\r
+ [MarkdownExporterAttribute.StackOverflow]\r
+ [MarkdownExporterAttribute.Atlassian]\r
+ [XmlExporterAttribute.Brief]\r
+ [XmlExporterAttribute.BriefCompressed]\r
+ [XmlExporterAttribute.Full]\r
+ [XmlExporterAttribute.FullCompressed]\r
+ public class IntroExport\r
+ {\r
+ private Random random = new Random(42);\r
+\r
+ [Benchmark(Baseline = true)]\r
+ public void Sleep10() => Thread.Sleep(10);\r
+\r
+ [Benchmark]\r
+ public void Sleep50Noisy() => Thread.Sleep(random.Next(100));\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Exporters.Json;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // *** Attribute style ***\r
+\r
+ [DryJob]\r
+ [JsonExporterAttribute.Brief]\r
+ [JsonExporterAttribute.Full]\r
+ [JsonExporterAttribute.BriefCompressed]\r
+ [JsonExporterAttribute.FullCompressed]\r
+ [JsonExporter("-custom", indentJson: true, excludeMeasurements: true)]\r
+ public class IntroExportJson\r
+ {\r
+ [Benchmark] public void Sleep10() => Thread.Sleep(10);\r
+ [Benchmark] public void Sleep20() => Thread.Sleep(20);\r
+ }\r
+\r
+ // *** Object style ***\r
+\r
+ [Config(typeof(Config))]\r
+ public class IntroJsonExportObjectStyle\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddExporter(JsonExporter.Brief);\r
+ AddExporter(JsonExporter.Brief);\r
+ AddExporter(JsonExporter.Full);\r
+ AddExporter(JsonExporter.BriefCompressed);\r
+ AddExporter(JsonExporter.FullCompressed);\r
+ AddExporter(JsonExporter.Custom("-custom", indentJson: true, excludeMeasurements: true));\r
+ }\r
+ }\r
+\r
+ [Benchmark] public void Sleep10() => Thread.Sleep(10);\r
+ [Benchmark] public void Sleep20() => Thread.Sleep(20);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DryJob]\r
+ [XmlExporterAttribute.Brief]\r
+ [XmlExporterAttribute.Full]\r
+ [XmlExporterAttribute.BriefCompressed]\r
+ [XmlExporterAttribute.FullCompressed]\r
+ [XmlExporter("-custom", indentXml: true, excludeMeasurements: true)]\r
+ public class IntroExportXml\r
+ {\r
+ [Benchmark] public void Sleep10() => Thread.Sleep(10);\r
+ [Benchmark] public void Sleep20() => Thread.Sleep(20);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Filters;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DryJob]\r
+ [Config(typeof(Config))]\r
+ public class IntroFilters\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ // We will benchmark ONLY method with\r
+ // names (which contains "A" OR "1") AND (have length < 3)\r
+ public Config()\r
+ {\r
+ // benchmark with names which contains "A" OR "1"\r
+ AddFilter(new DisjunctionFilter(\r
+ new NameFilter(name => name.Contains("A")),\r
+ new NameFilter(name => name.Contains("1"))\r
+ ));\r
+\r
+ // benchmark with names with length < 3\r
+ AddFilter(new NameFilter(name => name.Length < 3));\r
+ }\r
+ }\r
+\r
+ [Benchmark] public void A1() => Thread.Sleep(10); // Will be benchmarked\r
+ [Benchmark] public void A2() => Thread.Sleep(10); // Will be benchmarked\r
+ [Benchmark] public void A3() => Thread.Sleep(10); // Will be benchmarked\r
+ [Benchmark] public void B1() => Thread.Sleep(10); // Will be benchmarked\r
+ [Benchmark] public void B2() => Thread.Sleep(10);\r
+ [Benchmark] public void B3() => Thread.Sleep(10);\r
+ [Benchmark] public void C1() => Thread.Sleep(10); // Will be benchmarked\r
+ [Benchmark] public void C2() => Thread.Sleep(10);\r
+ [Benchmark] public void C3() => Thread.Sleep(10);\r
+ [Benchmark] public void Aaa() => Thread.Sleep(10);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Running;\r
+using BenchmarkDotNet.Validators;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Security.Cryptography;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class Algo_Md5VsSha256\r
+ {\r
+ private const int N = 10000;\r
+ private readonly byte[] data;\r
+\r
+ private readonly MD5 md5 = MD5.Create();\r
+ private readonly SHA256 sha256 = SHA256.Create();\r
+\r
+ public Algo_Md5VsSha256()\r
+ {\r
+ data = new byte[N];\r
+ new Random(42).NextBytes(data);\r
+ }\r
+\r
+ [Benchmark(Baseline = true)]\r
+ public byte[] Md5() => md5.ComputeHash(data);\r
+\r
+ [Benchmark]\r
+ public byte[] Sha256() => sha256.ComputeHash(data);\r
+ }\r
+\r
+ public class IntroFluentConfigBuilder\r
+ {\r
+ public static void Run()\r
+ {\r
+ BenchmarkRunner\r
+ .Run<Algo_Md5VsSha256>(\r
+ DefaultConfig.Instance\r
+ .AddJob(Job.Default.WithRuntime(ClrRuntime.Net462))\r
+ .AddJob(Job.Default.WithRuntime(CoreRuntime.Core21))\r
+ .AddValidator(ExecutionValidator.FailOnError));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Order;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Runtime.CompilerServices;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ [Orderer(SummaryOrderPolicy.FastestToSlowest)]\r
+ [MemoryDiagnoser]\r
+ public class IntroGcMode\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.MediumRun.WithGcServer(true).WithGcForce(true).WithId("ServerForce"));\r
+ AddJob(Job.MediumRun.WithGcServer(true).WithGcForce(false).WithId("Server"));\r
+ AddJob(Job.MediumRun.WithGcServer(false).WithGcForce(true).WithId("Workstation"));\r
+ AddJob(Job.MediumRun.WithGcServer(false).WithGcForce(false).WithId("WorkstationForce"));\r
+ }\r
+ }\r
+\r
+ [Benchmark(Description = "new byte[10kB]")]\r
+ public byte[] Allocate()\r
+ {\r
+ return new byte[10000];\r
+ }\r
+\r
+ [Benchmark(Description = "stackalloc byte[10kB]")]\r
+ public unsafe void AllocateWithStackalloc()\r
+ {\r
+ var array = stackalloc byte[10000];\r
+ Consume(array);\r
+ }\r
+\r
+ [MethodImpl(MethodImplOptions.NoInlining)]\r
+ private static unsafe void Consume(byte* input)\r
+ {\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [GenericTypeArguments(typeof(int))]\r
+ [GenericTypeArguments(typeof(char))]\r
+ public class IntroGenericTypeArguments<T>\r
+ {\r
+ [Benchmark] public T Create() => Activator.CreateInstance<T>();\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Diagnosers;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [HardwareCounters(\r
+ HardwareCounter.BranchMispredictions,\r
+ HardwareCounter.BranchInstructions)]\r
+ public class IntroHardwareCounters\r
+ {\r
+ private const int N = 32767;\r
+ private readonly int[] sorted, unsorted;\r
+\r
+ public IntroHardwareCounters()\r
+ {\r
+ var random = new Random(0);\r
+ unsorted = new int[N];\r
+ sorted = new int[N];\r
+ for (int i = 0; i < N; i++)\r
+ sorted[i] = unsorted[i] = random.Next(256);\r
+ Array.Sort(sorted);\r
+ }\r
+\r
+ private static int Branch(int[] data)\r
+ {\r
+ int sum = 0;\r
+ for (int i = 0; i < N; i++)\r
+ if (data[i] >= 128)\r
+ sum += data[i];\r
+ return sum;\r
+ }\r
+\r
+ private static int Branchless(int[] data)\r
+ {\r
+ int sum = 0;\r
+ for (int i = 0; i < N; i++)\r
+ {\r
+ int t = (data[i] - 128) >> 31;\r
+ sum += ~t & data[i];\r
+ }\r
+ return sum;\r
+ }\r
+\r
+ [Benchmark]\r
+ public int SortedBranch() => Branch(sorted);\r
+\r
+ [Benchmark]\r
+ public int UnsortedBranch() => Branch(unsorted);\r
+\r
+ [Benchmark]\r
+ public int SortedBranchless() => Branchless(sorted);\r
+\r
+ [Benchmark]\r
+ public int UnsortedBranchless() => Branchless(unsorted);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Order;\r
+using BenchmarkDotNet.Toolchains.InProcess.Emit;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Runtime.CompilerServices;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ [Orderer(SummaryOrderPolicy.FastestToSlowest)]\r
+ [MemoryDiagnoser]\r
+ public class IntroInProcess\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.MediumRun\r
+ .WithLaunchCount(1)\r
+ .WithId("OutOfProc"));\r
+\r
+ AddJob(Job.MediumRun\r
+ .WithLaunchCount(1)\r
+ .WithToolchain(InProcessEmitToolchain.Instance)\r
+ .WithId("InProcess"));\r
+ }\r
+ }\r
+\r
+ [Benchmark(Description = "new byte[10kB]")]\r
+ public byte[] Allocate()\r
+ {\r
+ return new byte[10000];\r
+ }\r
+\r
+ [Benchmark(Description = "stackalloc byte[10kB]")]\r
+ public unsafe void AllocateWithStackalloc()\r
+ {\r
+ var array = stackalloc byte[10000];\r
+ Consume(array);\r
+ }\r
+\r
+ [MethodImpl(MethodImplOptions.NoInlining)]\r
+ private static unsafe void Consume(byte* input)\r
+ {\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using System;\r
+using System.Runtime.CompilerServices;\r
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Order;\r
+using BenchmarkDotNet.Toolchains.InProcess;\r
+using BenchmarkDotNet.Toolchains.InProcess.Emit;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ [Orderer(SummaryOrderPolicy.FastestToSlowest)]\r
+ [MemoryDiagnoser]\r
+ public class IntroInProcessWrongEnv\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ var wrongPlatform = Environment.Is64BitProcess\r
+ ? Platform.X64\r
+ : Platform.X86;\r
+\r
+ AddJob(Job.MediumRun\r
+ .WithLaunchCount(1)\r
+ .WithPlatform(wrongPlatform)\r
+ .WithToolchain(InProcessEmitToolchain.Instance)\r
+ .WithId("InProcess"));\r
+\r
+ AddValidator(InProcessValidator.DontFailOnError);\r
+ }\r
+ }\r
+\r
+ [Benchmark(Description = "new byte[10kB]")]\r
+ public byte[] Allocate()\r
+ {\r
+ return new byte[10000];\r
+ }\r
+\r
+ [Benchmark(Description = "stackalloc byte[10kB]")]\r
+ public unsafe void AllocateWithStackalloc()\r
+ {\r
+ var array = stackalloc byte[10000];\r
+ Consume(array);\r
+ }\r
+\r
+ [MethodImpl(MethodImplOptions.NoInlining)]\r
+ private static unsafe void Consume(byte* input)\r
+ {\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Runtime.CompilerServices;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [BenchmarkDotNet.Diagnostics.Windows.Configs.InliningDiagnoser(logFailuresOnly: false, allowedNamespaces: new[] { "BenchmarkDotNet.Samples" })]\r
+ public class IntroInliningDiagnoser\r
+ {\r
+ [Benchmark]\r
+ public int IterationTest()\r
+ {\r
+ int j = 0;\r
+ for (int i = 0; i < short.MaxValue; ++i)\r
+ {\r
+ j = i + AddThree(i);\r
+ }\r
+\r
+ return j + ReturnFive() + AddThree(ReturnFive());\r
+ }\r
+\r
+ [Benchmark]\r
+ public int SplitJoin()\r
+ => string.Join(",", new string[1000]).Split(',').Length;\r
+\r
+ private int ReturnFive()\r
+ {\r
+ return 5;\r
+ }\r
+\r
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]\r
+ private int AddThree(int a)\r
+ {\r
+ return a + 3;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System.Threading;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+\r
+ [BenchmarkDotNet.Diagnostics.Windows.Configs.JitStatsDiagnoser]\r
+ public class IntroJitStatsDiagnoser\r
+ {\r
+ [Benchmark]\r
+ public void Sleep() => Thread.Sleep(10);\r
+ }\r
+\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [SimpleJob(runtimeMoniker: RuntimeMoniker.Net462, baseline: true)]\r
+ [SimpleJob(runtimeMoniker: RuntimeMoniker.Mono)]\r
+ [SimpleJob(runtimeMoniker: RuntimeMoniker.Net50)]\r
+ public class IntroJobBaseline\r
+ {\r
+ [Benchmark]\r
+ public int SplitJoin()\r
+ => string.Join(",", new string[1000]).Split(',').Length;\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // Run BenchmarkSwitcher with arguments: "--join --category=IntroJoinA"\r
+\r
+ [DryJob]\r
+ public class IntroJoin1\r
+ {\r
+ [Benchmark]\r
+ [BenchmarkCategory("IntroJoinA")]\r
+ public void A() => Thread.Sleep(10);\r
+\r
+ [Benchmark]\r
+ [BenchmarkCategory("IntroJoinB")]\r
+ public void B() => Thread.Sleep(10);\r
+ }\r
+\r
+ [DryJob]\r
+ public class IntroJoin2\r
+ {\r
+ [Benchmark]\r
+ [BenchmarkCategory("IntroJoinA")]\r
+ public void A() => Thread.Sleep(10);\r
+\r
+ [Benchmark]\r
+ [BenchmarkCategory("IntroJoinB")]\r
+ public void B() => Thread.Sleep(10);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Runtime.InteropServices;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [MemoryDiagnoser]\r
+ [Config(typeof(Config))]\r
+ public class IntroLargeAddressAware\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.Default\r
+ .WithRuntime(ClrRuntime.Net462)\r
+ .WithPlatform(Platform.X86)\r
+ .WithLargeAddressAware(value: RuntimeInformation.IsOSPlatform(OSPlatform.Windows))\r
+ .WithId("Framework"));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void AllocateMoreThan2GB()\r
+ {\r
+ const int oneGB = 1024 * 1024 * 1024;\r
+ const int halfGB = oneGB / 2;\r
+ byte[] bytes1 = new byte[oneGB];\r
+ byte[] bytes2 = new byte[oneGB];\r
+ byte[] bytes3 = new byte[halfGB];\r
+ GC.KeepAlive(bytes1);\r
+ GC.KeepAlive(bytes2);\r
+ GC.KeepAlive(bytes3);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [SimpleJob(RunStrategy.Monitoring, iterationCount: 10, id: "MonitoringJob")]\r
+ [MinColumn, Q1Column, Q3Column, MaxColumn]\r
+ public class IntroMonitoring\r
+ {\r
+ private Random random = new Random(42);\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ Thread.Sleep(random.Next(10) * 10);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [MValueColumn]\r
+ [SimpleJob(RunStrategy.Throughput, 1, 0, -1, 1, "MyJob")]\r
+ public class IntroMultimodal\r
+ {\r
+ private readonly Random rnd = new Random(42);\r
+\r
+ private void Multimodal(int n)\r
+ => Thread.Sleep((rnd.Next(n) + 1) * 100);\r
+\r
+ [Benchmark] public void Unimodal() => Multimodal(1);\r
+ [Benchmark] public void Bimodal() => Multimodal(2);\r
+ [Benchmark] public void Trimodal() => Multimodal(3);\r
+ [Benchmark] public void Quadrimodal() => Multimodal(4);\r
+ }\r
+}\r
--- /dev/null
+using System;\r
+using System.Drawing;\r
+using System.Runtime.InteropServices;\r
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Diagnostics.Windows.Configs;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [ShortRunJob]\r
+ [NativeMemoryProfiler]\r
+ [MemoryDiagnoser]\r
+ public class IntroNativeMemory\r
+ {\r
+ [Benchmark]\r
+ public void BitmapWithLeaks()\r
+ {\r
+ var flag = new Bitmap(200, 100);\r
+ var graphics = Graphics.FromImage(flag);\r
+ var blackPen = new Pen(Color.Black, 3);\r
+ graphics.DrawLine(blackPen, 100, 100, 500, 100);\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Bitmap()\r
+ {\r
+ using (var flag = new Bitmap(200, 100))\r
+ {\r
+ using (var graphics = Graphics.FromImage(flag))\r
+ {\r
+ using (var blackPen = new Pen(Color.Black, 3))\r
+ {\r
+ graphics.DrawLine(blackPen, 100, 100, 500, 100);\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ private const int Size = 20; // Greater value could cause System.OutOfMemoryException for test with memory leaks.\r
+ private int ArraySize = Size * Marshal.SizeOf(typeof(int));\r
+\r
+ [Benchmark]\r
+ public unsafe void AllocHGlobal()\r
+ {\r
+ IntPtr unmanagedHandle = Marshal.AllocHGlobal(ArraySize);\r
+ Span<byte> unmanaged = new Span<byte>(unmanagedHandle.ToPointer(), ArraySize);\r
+ Marshal.FreeHGlobal(unmanagedHandle);\r
+ }\r
+\r
+ [Benchmark]\r
+ public unsafe void AllocHGlobalWithLeaks()\r
+ {\r
+ IntPtr unmanagedHandle = Marshal.AllocHGlobal(ArraySize);\r
+ Span<byte> unmanaged = new Span<byte>(unmanagedHandle.ToPointer(), ArraySize);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Jobs;\r
+using Newtonsoft.Json;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ /// <summary>\r
+ /// Benchmarks between various versions of a NuGet package\r
+ /// </summary>\r
+ /// <remarks>\r
+ /// Only supported with the CsProjCoreToolchain toolchain\r
+ /// </remarks>\r
+ [Config(typeof(Config))]\r
+ public class IntroNuGet\r
+ {\r
+ // Specify jobs with different versions of the same NuGet package to benchmark.\r
+ // The NuGet versions referenced on these jobs must be greater or equal to the\r
+ // same NuGet version referenced in this benchmark project.\r
+ // Example: This benchmark project references Newtonsoft.Json 9.0.1\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ var baseJob = Job.MediumRun;\r
+\r
+ AddJob(baseJob.WithNuGet("Newtonsoft.Json", "11.0.2").WithId("11.0.2"));\r
+ AddJob(baseJob.WithNuGet("Newtonsoft.Json", "11.0.1").WithId("11.0.1"));\r
+ AddJob(baseJob.WithNuGet("Newtonsoft.Json", "10.0.3").WithId("10.0.3"));\r
+ AddJob(baseJob.WithNuGet("Newtonsoft.Json", "10.0.2").WithId("10.0.2"));\r
+ AddJob(baseJob.WithNuGet("Newtonsoft.Json", "10.0.1").WithId("10.0.1"));\r
+ AddJob(baseJob.WithNuGet("Newtonsoft.Json", "9.0.1").WithId("9.0.1"));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void SerializeAnonymousObject()\r
+ => JsonConvert.SerializeObject(\r
+ new { hello = "world", price = 1.99, now = DateTime.UtcNow });\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Order;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Orderer(SummaryOrderPolicy.FastestToSlowest, MethodOrderPolicy.Declared)]\r
+ [DryJob]\r
+ public class IntroOrderAttr\r
+ {\r
+ [Params(1, 2, 3)]\r
+ public int X { get; set; }\r
+\r
+ [Benchmark]\r
+ public void Slow() => Thread.Sleep(X * 100);\r
+\r
+ [Benchmark]\r
+ public void Fast() => Thread.Sleep(X * 50);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Order;\r
+using BenchmarkDotNet.Reports;\r
+using BenchmarkDotNet.Running;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Collections.Immutable;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ [DryJob]\r
+ [RankColumn]\r
+ public class IntroOrderManual\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config() => Orderer = new FastestToSlowestOrderer();\r
+\r
+ private class FastestToSlowestOrderer : IOrderer\r
+ {\r
+ public IEnumerable<BenchmarkCase> GetExecutionOrder(ImmutableArray<BenchmarkCase> benchmarksCase,\r
+ IEnumerable<BenchmarkLogicalGroupRule>? order = null) =>\r
+ from benchmark in benchmarksCase\r
+ orderby benchmark.Parameters["X"] descending,\r
+ benchmark.Descriptor.WorkloadMethodDisplayInfo\r
+ select benchmark;\r
+\r
+ public IEnumerable<BenchmarkCase> GetSummaryOrder(ImmutableArray<BenchmarkCase> benchmarksCase, Summary summary) =>\r
+ from benchmark in benchmarksCase\r
+ orderby summary[benchmark].ResultStatistics.Mean\r
+ select benchmark;\r
+\r
+ public string GetHighlightGroupKey(BenchmarkCase benchmarkCase) => null;\r
+\r
+ public string GetLogicalGroupKey(ImmutableArray<BenchmarkCase> allBenchmarksCases, BenchmarkCase benchmarkCase) =>\r
+ benchmarkCase.Job.DisplayInfo + "_" + benchmarkCase.Parameters.DisplayInfo;\r
+\r
+ public IEnumerable<IGrouping<string, BenchmarkCase>> GetLogicalGroupOrder(IEnumerable<IGrouping<string, BenchmarkCase>> logicalGroups,\r
+ IEnumerable<BenchmarkLogicalGroupRule>? order = null) =>\r
+ logicalGroups.OrderBy(it => it.Key);\r
+\r
+ public bool SeparateLogicalGroups => true;\r
+ }\r
+ }\r
+\r
+ [Params(1, 2, 3)]\r
+ public int X { get; set; }\r
+\r
+ [Benchmark]\r
+ public void Fast() => Thread.Sleep(X * 50);\r
+\r
+ [Benchmark]\r
+ public void Slow() => Thread.Sleep(X * 100);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Jobs;\r
+using Perfolizer.Mathematics.OutlierDetection;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ public class IntroOutliers\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ var jobBase = Job.Default.WithWarmupCount(0).WithIterationCount(10).WithInvocationCount(1).WithUnrollFactor(1);\r
+ AddJob(jobBase.WithOutlierMode(OutlierMode.DontRemove).WithId("DontRemoveOutliers"));\r
+ AddJob(jobBase.WithOutlierMode(OutlierMode.RemoveUpper).WithId("RemoveUpperOutliers"));\r
+ }\r
+ }\r
+\r
+ private int counter;\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ counter++;\r
+ int noise = counter % 10 == 0 ? 500 : 0;\r
+ Thread.Sleep(100 + noise);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroParams\r
+ {\r
+ [Params(100, 200)]\r
+ public int A { get; set; }\r
+\r
+ [Params(10, 20)]\r
+ public int B { get; set; }\r
+\r
+ [Benchmark]\r
+ public void Benchmark() => Thread.Sleep(A + B + 5);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [DryJob]\r
+ public class IntroParamsAllValues\r
+ {\r
+ public enum CustomEnum\r
+ {\r
+ One = 1,\r
+ Two,\r
+ Three\r
+ }\r
+\r
+ [ParamsAllValues]\r
+ public CustomEnum E { get; set; }\r
+\r
+ [ParamsAllValues]\r
+ public bool? B { get; set; }\r
+\r
+ [Benchmark]\r
+ public void Benchmark()\r
+ {\r
+ Thread.Sleep(\r
+ (int)E * 100 +\r
+ (B == true ? 20 : B == false ? 10 : 0));\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroParamsSource\r
+ {\r
+ // property with public setter\r
+ [ParamsSource(nameof(ValuesForA))]\r
+ public int A { get; set; }\r
+\r
+ // public field\r
+ [ParamsSource(nameof(ValuesForB))]\r
+ public int B;\r
+\r
+ // public property\r
+ public IEnumerable<int> ValuesForA => new[] { 100, 200 };\r
+\r
+ // public static method\r
+ public static IEnumerable<int> ValuesForB() => new[] { 10, 20 };\r
+\r
+ [Benchmark]\r
+ public void Benchmark() => Thread.Sleep(A + B + 5);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Columns;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // Using percentiles for adequate timings representation\r
+ [Config(typeof(Config))]\r
+ [SimpleJob(RunStrategy.ColdStart, launchCount: 4,\r
+ warmupCount: 3, iterationCount: 20, id: "MyJob")]\r
+ public class IntroPercentiles\r
+ {\r
+ // To share between runs.\r
+ // DO NOT do this in production code. The System.Random IS NOT thread safe.\r
+ private static readonly Random Rnd = new Random();\r
+\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddColumn(\r
+ StatisticColumn.P0,\r
+ StatisticColumn.P25,\r
+ StatisticColumn.P50,\r
+ StatisticColumn.P67,\r
+ StatisticColumn.P80,\r
+ StatisticColumn.P85,\r
+ StatisticColumn.P90,\r
+ StatisticColumn.P95,\r
+ StatisticColumn.P100);\r
+ }\r
+ }\r
+\r
+ [Benchmark(Baseline = true)]\r
+ public void ConstantDelays() => Thread.Sleep(20);\r
+\r
+ [Benchmark]\r
+ public void RandomDelays() => Thread.Sleep(10 + (int)(20 * Rnd.NextDouble()));\r
+\r
+ [Benchmark]\r
+ public void RareDelays()\r
+ {\r
+ int rndTime = 10;\r
+ // Bigger delays for 15% of the runs\r
+ if (Rnd.NextDouble() > 0.85)\r
+ {\r
+ rndTime += 30;\r
+ }\r
+\r
+ Thread.Sleep(rndTime);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [Config(typeof(Config))]\r
+ public class IntroPowerPlan\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.MediumRun.WithPowerPlan(new Guid("e9a42b02-d5df-448d-aa00-03f14749eb61")));\r
+ AddJob(Job.MediumRun.WithPowerPlan(PowerPlan.UltimatePerformance));\r
+ AddJob(Job.MediumRun.WithPowerPlan(PowerPlan.UserPowerPlan));\r
+ AddJob(Job.MediumRun.WithPowerPlan(PowerPlan.HighPerformance));\r
+ AddJob(Job.MediumRun.WithPowerPlan(PowerPlan.Balanced));\r
+ AddJob(Job.MediumRun.WithPowerPlan(PowerPlan.PowerSaver));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public int IterationTest()\r
+ {\r
+ int j = 0;\r
+ for (int i = 0; i < short.MaxValue; ++i)\r
+ {\r
+ j = i;\r
+ }\r
+\r
+ return j;\r
+ }\r
+\r
+ [Benchmark]\r
+ public int SplitJoin()\r
+ => string.Join(",", new string[1000]).Split(',').Length;\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Mathematics;\r
+using BenchmarkDotNet.Order;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [ShortRunJob]\r
+ [Orderer(SummaryOrderPolicy.FastestToSlowest)]\r
+ [RankColumn(NumeralSystem.Arabic)]\r
+ [RankColumn(NumeralSystem.Roman)]\r
+ [RankColumn(NumeralSystem.Stars)]\r
+ public class IntroRankColumn\r
+ {\r
+ [Params(1, 2)]\r
+ public int Factor;\r
+\r
+ [Benchmark]\r
+ public void Foo() => Thread.Sleep(Factor * 100);\r
+\r
+ [Benchmark]\r
+ public void Bar() => Thread.Sleep(Factor * 200);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using Perfolizer.Mathematics.OutlierDetection;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // Don't remove outliers\r
+ [Outliers(OutlierMode.DontRemove)]\r
+ // Skip jitting, pilot, warmup; measure 10 iterations\r
+ [SimpleJob(RunStrategy.Monitoring, iterationCount: 10, invocationCount: 1)]\r
+ public class IntroRatioSD\r
+ {\r
+ private int counter;\r
+\r
+ [GlobalSetup]\r
+ public void Setup() => counter = 0;\r
+\r
+ [Benchmark(Baseline = true)]\r
+ public void Base()\r
+ {\r
+ Thread.Sleep(100);\r
+ if (++counter % 7 == 0)\r
+ Thread.Sleep(5000); // Emulate outlier\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Slow() => Thread.Sleep(200);\r
+\r
+ [Benchmark]\r
+ public void Fast() => Thread.Sleep(50);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Columns;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Reports;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [ShortRunJob, Config(typeof(Config))]\r
+ public class IntroRatioStyle\r
+ {\r
+ [Benchmark(Baseline = true)]\r
+ public void Baseline() => Thread.Sleep(1000);\r
+\r
+ [Benchmark]\r
+ public void Bar() => Thread.Sleep(150);\r
+\r
+ [Benchmark]\r
+ public void Foo() => Thread.Sleep(1150);\r
+\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ SummaryStyle = SummaryStyle.Default.WithRatioStyle(RatioStyle.Trend);\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroSetupCleanupGlobal\r
+ {\r
+ [Params(10, 100, 1000)]\r
+ public int N;\r
+\r
+ private int[] data;\r
+\r
+ [GlobalSetup]\r
+ public void GlobalSetup()\r
+ {\r
+ data = new int[N]; // executed once per each N value\r
+ }\r
+\r
+ [Benchmark]\r
+ public int Logic()\r
+ {\r
+ int res = 0;\r
+ for (int i = 0; i < N; i++)\r
+ res += data[i];\r
+ return res;\r
+ }\r
+\r
+ [GlobalCleanup]\r
+ public void GlobalCleanup()\r
+ {\r
+ // Disposing logic\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [SimpleJob(RunStrategy.Monitoring, launchCount: 1,\r
+ warmupCount: 2, iterationCount: 3)]\r
+ public class IntroSetupCleanupIteration\r
+ {\r
+ private int setupCounter;\r
+ private int cleanupCounter;\r
+\r
+ [IterationSetup]\r
+ public void IterationSetup()\r
+ => Console.WriteLine($"// IterationSetup ({++setupCounter})");\r
+\r
+ [IterationCleanup]\r
+ public void IterationCleanup()\r
+ => Console.WriteLine($"// IterationCleanup ({++cleanupCounter})");\r
+\r
+ [GlobalSetup]\r
+ public void GlobalSetup()\r
+ => Console.WriteLine("// " + "GlobalSetup");\r
+\r
+ [GlobalCleanup]\r
+ public void GlobalCleanup()\r
+ => Console.WriteLine("// " + "GlobalCleanup");\r
+\r
+ [Benchmark]\r
+ public void Benchmark()\r
+ => Console.WriteLine("// " + "Benchmark");\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Engines;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [SimpleJob(RunStrategy.Monitoring, launchCount: 0,\r
+ warmupCount: 0, iterationCount: 1)]\r
+ public class IntroSetupCleanupTarget\r
+ {\r
+ [GlobalSetup(Target = nameof(BenchmarkA))]\r
+ public void GlobalSetupA()\r
+ => Console.WriteLine("// " + "GlobalSetup A");\r
+\r
+ [Benchmark]\r
+ public void BenchmarkA()\r
+ => Console.WriteLine("// " + "Benchmark A");\r
+\r
+ [GlobalSetup(Targets = new[] { nameof(BenchmarkB), nameof(BenchmarkC) })]\r
+ public void GlobalSetupB()\r
+ => Console.WriteLine("// " + "GlobalSetup B");\r
+\r
+ [Benchmark]\r
+ public void BenchmarkB()\r
+ => Console.WriteLine("// " + "Benchmark B");\r
+\r
+ [Benchmark]\r
+ public void BenchmarkC()\r
+ => Console.WriteLine("// " + "Benchmark C");\r
+\r
+ [Benchmark]\r
+ public void BenchmarkD()\r
+ => Console.WriteLine("// " + "Benchmark D");\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class IntroStaThread\r
+ {\r
+ [Benchmark, System.STAThread]\r
+ public void CheckForSTA()\r
+ {\r
+ if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)\r
+ {\r
+ throw new ThreadStateException(\r
+ "The current threads apartment state is not STA");\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using Perfolizer.Mathematics.SignificanceTesting;\r
+using Perfolizer.Mathematics.Thresholds;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [StatisticalTestColumn(StatisticalTestKind.Welch, ThresholdUnit.Microseconds, 1, true)]\r
+ [StatisticalTestColumn(StatisticalTestKind.MannWhitney, ThresholdUnit.Microseconds, 1, true)]\r
+ [StatisticalTestColumn(StatisticalTestKind.Welch, ThresholdUnit.Ratio, 0.03, true)]\r
+ [StatisticalTestColumn(StatisticalTestKind.MannWhitney, ThresholdUnit.Ratio, 0.03, true)]\r
+ [SimpleJob(warmupCount: 0, iterationCount: 5)]\r
+ public class IntroStatisticalTesting\r
+ {\r
+ [Benchmark] public void Sleep50() => Thread.Sleep(50);\r
+ [Benchmark] public void Sleep97() => Thread.Sleep(97);\r
+ [Benchmark] public void Sleep99() => Thread.Sleep(99);\r
+ [Benchmark(Baseline = true)] public void Sleep100() => Thread.Sleep(100);\r
+ [Benchmark] public void Sleep101() => Thread.Sleep(101);\r
+ [Benchmark] public void Sleep103() => Thread.Sleep(103);\r
+ [Benchmark] public void Sleep150() => Thread.Sleep(150);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Security.Cryptography;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [MediumRunJob, SkewnessColumn, KurtosisColumn]\r
+ public class IntroStatisticsColumns\r
+ {\r
+ private const int N = 10000;\r
+ private readonly byte[] data;\r
+\r
+ private readonly MD5 md5 = MD5.Create();\r
+ private readonly SHA256 sha256 = SHA256.Create();\r
+\r
+ public IntroStatisticsColumns()\r
+ {\r
+ data = new byte[N];\r
+ new Random(42).NextBytes(data);\r
+ }\r
+\r
+ [Benchmark(Baseline = true)]\r
+ public byte[] Md5A() => md5.ComputeHash(data);\r
+\r
+ [Benchmark]\r
+ public byte[] Md5B() => md5.ComputeHash(data);\r
+\r
+ [Benchmark]\r
+ public byte[] Sha256() => sha256.ComputeHash(data);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [StopOnFirstError]\r
+ public class IntroStopOnFirstError\r
+ {\r
+ [Benchmark(Baseline = true)]\r
+ public int FirstMethod() => throw new Exception("Example exception.");\r
+\r
+ [Benchmark]\r
+ public int SecondMethod() => 1;\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Columns;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Jobs;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // You can add custom tags per each method using Columns\r
+ [Config(typeof(Config))]\r
+ public class IntroTagColumn\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config()\r
+ {\r
+ AddJob(Job.Dry);\r
+ AddColumn(new TagColumn("Kind", name => name.Substring(0, 3)));\r
+ AddColumn(new TagColumn("Number", name => name.Substring(3)));\r
+ }\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo1() => Thread.Sleep(10);\r
+\r
+ [Benchmark]\r
+ public void Foo12() => Thread.Sleep(10);\r
+\r
+ [Benchmark]\r
+ public void Bar3() => Thread.Sleep(10);\r
+\r
+ [Benchmark]\r
+ public void Bar34() => Thread.Sleep(10);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ [BenchmarkDotNet.Diagnostics.Windows.Configs.TailCallDiagnoser]\r
+ [LegacyJitX86Job, LegacyJitX64Job, RyuJitX64Job]\r
+ public class IntroTailcall\r
+ {\r
+ [Benchmark]\r
+ public long Calc()\r
+ => FactorialWithoutTailing(7) - FactorialWithTailing(7);\r
+\r
+ private static long FactorialWithoutTailing(int depth)\r
+ => depth == 0 ? 1 : depth * FactorialWithoutTailing(depth - 1);\r
+\r
+ private static long FactorialWithTailing(int pos, int depth)\r
+ => pos == 0 ? depth : FactorialWithTailing(pos - 1, depth * pos);\r
+\r
+ private static long FactorialWithTailing(int depth)\r
+ => FactorialWithTailing(depth - 1, depth);\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Running;\r
+using BenchmarkDotNet.Toolchains.DotNetCli;\r
+using BenchmarkDotNet.Toolchains.MonoWasm;\r
+using BenchmarkDotNet.Toolchains;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+using BenchmarkDotNet.Loggers;\r
+using System.Diagnostics;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // *** Attribute Style ***\r
+ [UnicodeConsoleLogger]\r
+ public class IntroUnicode\r
+ {\r
+ [Benchmark]\r
+ public long Foo()\r
+ {\r
+ long waitUntil = Stopwatch.GetTimestamp() + 1000;\r
+ while (Stopwatch.GetTimestamp() < waitUntil) { }\r
+ return waitUntil;\r
+ }\r
+ }\r
+\r
+ // *** Object Style ***\r
+ [Config(typeof(Config))]\r
+ public class IntroUnicodeObjectStyle\r
+ {\r
+ private class Config : ManualConfig\r
+ {\r
+ public Config() => AddLogger(ConsoleLogger.Unicode);\r
+ }\r
+\r
+ [Benchmark]\r
+ public long Foo()\r
+ {\r
+ long waitUntil = Stopwatch.GetTimestamp() + 1000;\r
+ while (Stopwatch.GetTimestamp() < waitUntil) { }\r
+ return waitUntil;\r
+ }\r
+ }\r
+\r
+ // *** Fluent Config ***\r
+ public class IntroUnicodeFluentConfig\r
+ {\r
+ public static void Run()\r
+ {\r
+ BenchmarkRunner.Run<IntroUnicodeFluentConfig>(\r
+ DefaultConfig.Instance\r
+ .AddLogger(ConsoleLogger.Unicode));\r
+ }\r
+\r
+ [Benchmark]\r
+ public long Foo()\r
+ {\r
+ long waitUntil = Stopwatch.GetTimestamp() + 1000;\r
+ while (Stopwatch.GetTimestamp() < waitUntil) { }\r
+ return waitUntil;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Attributes;\r
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Environments;\r
+using BenchmarkDotNet.Jobs;\r
+using BenchmarkDotNet.Loggers;\r
+using BenchmarkDotNet.Running;\r
+using BenchmarkDotNet.Toolchains.DotNetCli;\r
+using BenchmarkDotNet.Toolchains.MonoWasm;\r
+using BenchmarkDotNet.Toolchains;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Diagnostics;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ // *** Command Line Arguments ***\r
+ public class IntroWasmCmdConfig\r
+ {\r
+ // the args must contain:\r
+ // an information that we want to run benchmark as Wasm:\r
+ // --runtimes Wasm\r
+ // path to dotnet cli\r
+ // --cli /home/adam/projects/runtime/dotnet.sh\r
+ public static void Run(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(IntroWasmCmdConfig).Assembly).Run(args);\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+\r
+ // *** Fluent Config ***\r
+ public class IntroWasmFluentConfig\r
+ {\r
+ public static void Run()\r
+ {\r
+ // the Wasm Toolchain requires two mandatory arguments:\r
+ const string cliPath = @"/home/adam/projects/runtime/dotnet.sh";\r
+\r
+ WasmRuntime runtime = new WasmRuntime(msBuildMoniker: "net5.0");\r
+ NetCoreAppSettings netCoreAppSettings = new NetCoreAppSettings(\r
+ targetFrameworkMoniker: "net5.0", runtimeFrameworkVersion: null, name: "Wasm",\r
+ customDotNetCliPath: cliPath);\r
+ IToolchain toolChain = WasmToolchain.From(netCoreAppSettings);\r
+\r
+ BenchmarkRunner.Run<IntroCustomMonoFluentConfig>(DefaultConfig.Instance\r
+ .AddJob(Job.ShortRun.WithRuntime(runtime).WithToolchain(toolChain)));\r
+ }\r
+\r
+ [Benchmark]\r
+ public void Foo()\r
+ {\r
+ // Benchmark body\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using BenchmarkDotNet.Configs;\r
+using BenchmarkDotNet.Exporters;\r
+using BenchmarkDotNet.Loggers;\r
+using BenchmarkDotNet.Running;\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+\r
+namespace TizenBenchmark.Intro\r
+{\r
+ public class TizenDotnet\r
+ {\r
+ void IntroArguments()\r
+ {\r
+ Console.WriteLine("##### IntroArguments Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroArguments>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroArguments Benchmark END #####");\r
+ }\r
+ void IntroArgumentsSource()\r
+ {\r
+ Console.WriteLine("##### IntroArgumentsSource Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroArgumentsSource>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroArgumentsSource Benchmark END #####");\r
+ }\r
+ void IntroArrayParam()\r
+ {\r
+ Console.WriteLine("##### IntroArrayParam Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroArrayParam>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroArrayParam Benchmark END #####");\r
+ }\r
+ void IntroBasic()\r
+ {\r
+ Console.WriteLine("##### IntroBasic Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroBasic>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroBasic Benchmark END #####");\r
+ }\r
+ void IntroBenchmarkBaseline()\r
+ {\r
+ Console.WriteLine("##### IntroBenchmarkBaseline Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroBenchmarkBaseline>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroBenchmarkBaseline Benchmark END #####");\r
+ }\r
+ void IntroCategories()\r
+ {\r
+ Console.WriteLine("##### IntroCategories Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroCategories>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroCategories Benchmark END #####");\r
+ }\r
+ void IntroCategoryBaseline()\r
+ {\r
+ Console.WriteLine("##### IntroCategoryBaseline Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroCategoryBaseline>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroCategoryBaseline Benchmark END #####");\r
+ }\r
+ void IntroCategoryDiscoverer()\r
+ {\r
+ Console.WriteLine("##### IntroCategoryDiscoverer Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroCategoryDiscoverer>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroCategoryDiscoverer Benchmark END #####");\r
+ }\r
+ void IntroColdStart()\r
+ {\r
+ Console.WriteLine("##### IntroColdStart Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroColdStart>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroColdStart Benchmark END #####");\r
+ }\r
+ void IntroComparableComplexParam()\r
+ {\r
+ Console.WriteLine("##### IntroComparableComplexParam Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroComparableComplexParam>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroComparableComplexParam Benchmark END #####");\r
+ }\r
+ void IntroConfigSource()\r
+ {\r
+ Console.WriteLine("##### IntroConfigSource Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroConfigSource>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroConfigSource Benchmark END #####");\r
+ }\r
+ void IntroConfigUnion()\r
+ {\r
+ Console.WriteLine("##### IntroConfigUnion Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroConfigUnion>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroConfigUnion Benchmark END #####");\r
+ }\r
+ void IntroCustomMono()\r
+ {\r
+ Console.WriteLine("##### IntroCustomMono Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ //var summary = BenchmarkRunner.Run<IntroCustomMono>(config);\r
+ //MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ //Console.WriteLine(logger.GetLog());\r
+\r
+ //summary = BenchmarkRunner.Run<IntroCustomMonoObjectStyle>(config);\r
+ //MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ //Console.WriteLine(logger.GetLog());\r
+\r
+ //summary = BenchmarkRunner.Run<IntroCustomMonoObjectStyleAot>(config);\r
+ //MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ //Console.WriteLine(logger.GetLog());\r
+\r
+ var summary = BenchmarkRunner.Run<IntroCustomMonoFluentConfig>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroCustomMono Benchmark END #####");\r
+ }\r
+ void IntroCustomMonoArguments()\r
+ {\r
+ Console.WriteLine("##### IntroCustomMonoArguments Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroCustomMonoArguments>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroCustomMonoArguments Benchmark END #####");\r
+ }\r
+ void IntroDeferredExecution()\r
+ {\r
+ Console.WriteLine("##### IntroDeferredExecution Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroDeferredExecution>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroDeferredExecution Benchmark END #####");\r
+ }\r
+ void IntroDisassembly()\r
+ {\r
+ Console.WriteLine("##### IntroDisassembly Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroDisassembly>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroDisassembly Benchmark END #####");\r
+ }\r
+ void IntroDisassemblyAllJits()\r
+ {\r
+ Console.WriteLine("##### IntroDisassemblyAllJits Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroDisassemblyAllJits>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroDisassemblyAllJits Benchmark END #####");\r
+ }\r
+ void IntroDisassemblyDry()\r
+ {\r
+ Console.WriteLine("##### IntroDisassemblyDry Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroDisassemblyDry>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroDisassemblyDry Benchmark END #####");\r
+ }\r
+ void IntroDisassemblyRyuJit()\r
+ {\r
+ Console.WriteLine("##### IntroDisassemblyRyuJit Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroDisassemblyRyuJit>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroDisassemblyRyuJit Benchmark END #####");\r
+ }\r
+ void IntroDotTraceDiagnoser()\r
+ {\r
+ Console.WriteLine("##### IntroDotTraceDiagnoser Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroDotTraceDiagnoser>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroDotTraceDiagnoser Benchmark END #####");\r
+ }\r
+ void IntroEnvVars()\r
+ {\r
+ Console.WriteLine("##### IntroEnvVars Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroEnvVars>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroEnvVars Benchmark END #####");\r
+ }\r
+ void IntroEventPipeProfiler()\r
+ {\r
+ Console.WriteLine("##### IntroEventPipeProfiler Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroEventPipeProfiler>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroEventPipeProfiler Benchmark END #####");\r
+ }\r
+ void IntroEventPipeProfilerAdvanced()\r
+ {\r
+ Console.WriteLine("##### IntroEventPipeProfilerAdvanced Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroEventPipeProfilerAdvanced>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroEventPipeProfilerAdvanced Benchmark END #####");\r
+ }\r
+ void IntroExport()\r
+ {\r
+ Console.WriteLine("##### IntroExport Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroExport>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroExport Benchmark END #####");\r
+ }\r
+ void IntroExportJson()\r
+ {\r
+ Console.WriteLine("##### IntroExportJson Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroExportJson>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroExportJson Benchmark END #####");\r
+ }\r
+ void IntroExportXml()\r
+ {\r
+ Console.WriteLine("##### IntroExportXml Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroExportXml>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroExportXml Benchmark END #####");\r
+ }\r
+ void IntroFilters()\r
+ {\r
+ Console.WriteLine("##### IntroFilters Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroFilters>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroFilters Benchmark END #####");\r
+ }\r
+ void IntroFluentConfigBuilder()\r
+ {\r
+ Console.WriteLine("##### IntroFluentConfigBuilder Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroFluentConfigBuilder>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroFluentConfigBuilder Benchmark END #####");\r
+ }\r
+ void IntroGcMode()\r
+ {\r
+ Console.WriteLine("##### IntroGcMode Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroGcMode>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroGcMode Benchmark END #####");\r
+ }\r
+ void IntroGenericTypeArguments()\r
+ {\r
+ Console.WriteLine("##### IntroGenericTypeArguments Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroGenericTypeArguments<int>>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+\r
+ summary = BenchmarkRunner.Run<IntroGenericTypeArguments<char>>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroGenericTypeArguments Benchmark END #####");\r
+ }\r
+ void IntroHardwareCounters()\r
+ {\r
+ Console.WriteLine("##### IntroHardwareCounters Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroHardwareCounters>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroHardwareCounters Benchmark END #####");\r
+ }\r
+ void IntroInliningDiagnoser()\r
+ {\r
+ Console.WriteLine("##### IntroInliningDiagnoser Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroInliningDiagnoser>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroInliningDiagnoser Benchmark END #####");\r
+ }\r
+ void IntroInProcess()\r
+ {\r
+ Console.WriteLine("##### IntroInProcess Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroInProcess>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroInProcess Benchmark END #####");\r
+ }\r
+ void IntroInProcessWrongEnv()\r
+ {\r
+ Console.WriteLine("##### IntroInProcessWrongEnv Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroInProcessWrongEnv>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroInProcessWrongEnv Benchmark END #####");\r
+ }\r
+ void IntroJitStatsDiagnoser()\r
+ {\r
+ Console.WriteLine("##### IntroJitStatsDiagnoser Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroJitStatsDiagnoser>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroJitStatsDiagnoser Benchmark END #####");\r
+ }\r
+ void IntroJobBaseline()\r
+ {\r
+ Console.WriteLine("##### IntroJobBaseline Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroJobBaseline>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroJobBaseline Benchmark END #####");\r
+ }\r
+ void IntroJoin()\r
+ {\r
+ Console.WriteLine("##### IntroJoin Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroJoin1>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+\r
+ summary = BenchmarkRunner.Run<IntroJoin2>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroJoin Benchmark END #####");\r
+ }\r
+ void IntroLargeAddressAware()\r
+ {\r
+ Console.WriteLine("##### IntroLargeAddressAware Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroLargeAddressAware>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroLargeAddressAware Benchmark END #####");\r
+ }\r
+ void IntroMonitoring()\r
+ {\r
+ Console.WriteLine("##### IntroMonitoring Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroMonitoring>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroMonitoring Benchmark END #####");\r
+ }\r
+ void IntroMultimodal()\r
+ {\r
+ Console.WriteLine("##### IntroMultimodal Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroMultimodal>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroMultimodal Benchmark END #####");\r
+ }\r
+ void IntroNativeMemory()\r
+ {\r
+ Console.WriteLine("##### IntroNativeMemory Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroNativeMemory>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroNativeMemory Benchmark END #####");\r
+ }\r
+ void IntroNuGet()\r
+ {\r
+ Console.WriteLine("##### IntroNuGet Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroNuGet>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroNuGet Benchmark END #####");\r
+ }\r
+ void IntroOrderAttr()\r
+ {\r
+ Console.WriteLine("##### IntroOrderAttr Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroOrderAttr>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroOrderAttr Benchmark END #####");\r
+ }\r
+ void IntroOrderManual()\r
+ {\r
+ Console.WriteLine("##### IntroOrderManual Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroOrderManual>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroOrderManual Benchmark END #####");\r
+ }\r
+ void IntroOutliers()\r
+ {\r
+ Console.WriteLine("##### IntroOutliers Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroOutliers>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroOutliers Benchmark END #####");\r
+ }\r
+ void IntroParams()\r
+ {\r
+ Console.WriteLine("##### IntroParams Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroParams>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroParams Benchmark END #####");\r
+ }\r
+ void IntroParamsAllValues()\r
+ {\r
+ Console.WriteLine("##### IntroParamsAllValues Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroParamsAllValues>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroParamsAllValues Benchmark END #####");\r
+ }\r
+ void IntroParamsSource()\r
+ {\r
+ Console.WriteLine("##### aIntroParamsSourceaa Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroParamsSource>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroParamsSource Benchmark END #####");\r
+ }\r
+ void IntroPercentiles()\r
+ {\r
+ Console.WriteLine("##### IntroPercentiles Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroPercentiles>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroPercentiles Benchmark END #####");\r
+ }\r
+ void IntroPowerPlan()\r
+ {\r
+ Console.WriteLine("##### IntroPowerPlan Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroPowerPlan>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroPowerPlan Benchmark END #####");\r
+ }\r
+ void IntroRankColumn()\r
+ {\r
+ Console.WriteLine("##### IntroRankColumn Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroRankColumn>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroRankColumn Benchmark END #####");\r
+ }\r
+ void IntroRatioSD()\r
+ {\r
+ Console.WriteLine("##### IntroRatioSD Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroRatioSD>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroRatioSD Benchmark END #####");\r
+ }\r
+ void IntroRatioStyle()\r
+ {\r
+ Console.WriteLine("##### IntroRatioStyle Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroRatioStyle>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroRatioStyle Benchmark END #####");\r
+ }\r
+ void IntroSetupCleanupGlobal()\r
+ {\r
+ Console.WriteLine("##### IntroSetupCleanupGlobal Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroSetupCleanupGlobal>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroSetupCleanupGlobal Benchmark END #####");\r
+ }\r
+ void IntroSetupCleanupIteration()\r
+ {\r
+ Console.WriteLine("##### IntroSetupCleanupIteration Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroSetupCleanupIteration>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroSetupCleanupIteration Benchmark END #####");\r
+ }\r
+ void IntroSetupCleanupTarget()\r
+ {\r
+ Console.WriteLine("##### IntroSetupCleanupTarget Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroSetupCleanupTarget>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroSetupCleanupTarget Benchmark END #####");\r
+ }\r
+ void IntroStaThread()\r
+ {\r
+ Console.WriteLine("##### IntroStaThread Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroStaThread>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroStaThread Benchmark END #####");\r
+ }\r
+ void IntroStatisticalTesting()\r
+ {\r
+ Console.WriteLine("##### IntroStatisticalTesting Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroStatisticalTesting>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroStatisticalTesting Benchmark END #####");\r
+ }\r
+ void IntroStatisticsColumns()\r
+ {\r
+ Console.WriteLine("##### IntroStatisticsColumns Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroStatisticsColumns>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroStatisticsColumns Benchmark END #####");\r
+ }\r
+ void IntroStopOnFirstError()\r
+ {\r
+ Console.WriteLine("##### IntroStopOnFirstError Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroStopOnFirstError>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroStopOnFirstError Benchmark END #####");\r
+ }\r
+ void IntroTagColumn()\r
+ {\r
+ Console.WriteLine("##### IntroTagColumn Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroTagColumn>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroTagColumn Benchmark END #####");\r
+ }\r
+ void IntroTailcall()\r
+ {\r
+ Console.WriteLine("##### IntroTailcall Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroTailcall>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroTailcall Benchmark END #####");\r
+ }\r
+ void IntroUnicode()\r
+ {\r
+ Console.WriteLine("##### IntroUnicode Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroUnicode>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+\r
+ summary = BenchmarkRunner.Run<IntroUnicodeObjectStyle>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+\r
+ summary = BenchmarkRunner.Run<IntroUnicodeFluentConfig>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroUnicode Benchmark END #####");\r
+ }\r
+ void IntroWasm()\r
+ {\r
+ Console.WriteLine("##### IntroWasm Benchmark START #####");\r
+ var logger = new AccumulationLogger();\r
+ var config = default(IConfig);\r
+ config = new DebugInProcessConfig();\r
+ config = config.WithArtifactsPath("/tmp/BenchmarkDotnet");\r
+\r
+ var summary = BenchmarkRunner.Run<IntroWasmCmdConfig>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+\r
+ summary = BenchmarkRunner.Run<IntroWasmFluentConfig>(config);\r
+ MarkdownExporter.Console.ExportToLog(summary, logger);\r
+ Console.WriteLine(logger.GetLog());\r
+ Console.WriteLine("##### IntroWasm Benchmark END #####");\r
+ }\r
+\r
+\r
+ public void Benchmark()\r
+ {\r
+ Console.WriteLine("##### Tizen.NET Benchmark START #####");\r
+ IntroArguments(); //1\r
+ IntroArgumentsSource(); //1\r
+ IntroArrayParam(); //1\r
+ IntroBasic(); //1\r
+ IntroBenchmarkBaseline(); //1\r
+ //IntroCategories();\r
+ IntroCategoryBaseline(); //1\r
+ //IntroCategoryDiscoverer();\r
+ //IntroColdStart();\r
+ IntroComparableComplexParam(); //1\r
+ //IntroConfigSource();\r
+ //IntroConfigUnion();\r
+ IntroCustomMono(); //1\r
+ //IntroCustomMonoArguments();\r
+ IntroDeferredExecution(); //1\r
+ //IntroDisassembly();\r
+ //IntroDisassemblyAllJits();\r
+ //IntroDisassemblyDry();\r
+ //IntroDisassemblyRyuJit();\r
+ //IntroDotTraceDiagnoser();\r
+ //IntroEnvVars();\r
+ //IntroEventPipeProfiler();\r
+ //IntroEventPipeProfilerAdvanced();\r
+ //IntroExport();\r
+ //IntroExportJson();\r
+ //IntroExportXml();\r
+ //IntroFilters();\r
+ //IntroFluentConfigBuilder();\r
+ //IntroGcMode();\r
+ IntroGenericTypeArguments(); //2\r
+ IntroHardwareCounters(); //1\r
+ //IntroInliningDiagnoser();\r
+ //IntroInProcess();\r
+ IntroInProcessWrongEnv(); //1\r
+ //IntroJitStatsDiagnoser();\r
+ //IntroJobBaseline();\r
+ //IntroJoin();\r
+ //IntroLargeAddressAware();\r
+ //IntroMonitoring();\r
+ //IntroMultimodal();\r
+ //IntroNativeMemory();\r
+ //IntroNuGet();\r
+ //IntroOrderAttr();\r
+ //IntroOrderManual();\r
+ //IntroOutliers();\r
+ IntroParams(); //1\r
+ //IntroParamsAllValues();\r
+ IntroParamsSource(); //1\r
+ //IntroPercentiles();\r
+ //IntroPowerPlan();\r
+ //IntroRankColumn();\r
+ //IntroRatioSD();\r
+ //IntroRatioStyle();\r
+ IntroSetupCleanupGlobal(); //1\r
+ //IntroSetupCleanupIteration();\r
+ //IntroSetupCleanupTarget();\r
+ IntroStaThread(); //1\r
+ //IntroStatisticalTesting();\r
+ //IntroStatisticsColumns();\r
+ //IntroStopOnFirstError();\r
+ //IntroTagColumn();\r
+ //IntroTailcall();\r
+ IntroUnicode(); //3\r
+ IntroWasm(); //2\r
+ Console.WriteLine("##### Tizen.NET Benchmark END #####");\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using Tizen.NUI;\r
+using Tizen.NUI.BaseComponents;\r
+\r
+namespace TizenBenchmark\r
+{\r
+ class Program : NUIApplication\r
+ {\r
+ protected override void OnCreate()\r
+ {\r
+ base.OnCreate();\r
+ Initialize();\r
+ }\r
+\r
+ void Initialize()\r
+ {\r
+ Intro.TizenDotnet benchmark = new Intro.TizenDotnet();\r
+ benchmark.Benchmark();\r
+\r
+ Window.Instance.KeyEvent += OnKeyEvent;\r
+\r
+ TextLabel text = new TextLabel("Hello Tizen NUI World");\r
+ text.HorizontalAlignment = HorizontalAlignment.Center;\r
+ text.VerticalAlignment = VerticalAlignment.Center;\r
+ text.TextColor = Color.Blue;\r
+ text.PointSize = 12.0f;\r
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;\r
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;\r
+ Window.Instance.GetDefaultLayer().Add(text);\r
+\r
+ Animation animation = new Animation(2000);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(180.0f)), PositionAxis.X), 0, 500);\r
+ animation.AnimateTo(text, "Orientation", new Rotation(new Radian(new Degree(0.0f)), PositionAxis.X), 500, 1000);\r
+ animation.Looping = true;\r
+ animation.Play();\r
+ }\r
+\r
+ public void OnKeyEvent(object sender, Window.KeyEventArgs e)\r
+ {\r
+ if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))\r
+ {\r
+ Exit();\r
+ }\r
+ }\r
+\r
+ static void Main(string[] args)\r
+ {\r
+ var app = new Program();\r
+ app.Run(args);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+ <PropertyGroup>\r
+ <OutputType>Exe</OutputType>\r
+ <TargetFramework>net6.0-tizen</TargetFramework>\r
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
+ </PropertyGroup>\r
+\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+ <DebugType>portable</DebugType>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+ <DebugType>None</DebugType>\r
+ </PropertyGroup>\r
+\r
+ <ItemGroup>\r
+ <Folder Include="lib\" />\r
+ <Folder Include="res\" />\r
+ </ItemGroup>\r
+\r
+ <ItemGroup>\r
+ <PackageReference Include="BenchmarkDotNet" Version="0.13.12" />\r
+ <PackageReference Include="BenchmarkDotNet.Annotations" Version="0.13.12" />\r
+ <PackageReference Include="BenchmarkDotNet.Diagnostics.dotTrace" Version="0.13.12" />\r
+ <PackageReference Include="BenchmarkDotNet.Diagnostics.Windows" Version="0.13.12" />\r
+ <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />\r
+ <PackageReference Include="System.Drawing.Common" Version="8.0.0" />\r
+ </ItemGroup>\r
+\r
+</Project>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="8.0" package="org.tizen.dotnet.TizenBenchmark" version="1.0.0">
+ <profile name="common" />
+ <ui-application appid="org.tizen.dotnet.TizenBenchmark"
+ exec="TizenBenchmark.dll"
+ type="dotnet"
+ multiple="false"
+ taskmanage="true"
+ nodisplay="false"
+ launch_mode="single"
+ api-version="11">
+ <label>TizenBenchmark</label>
+ <icon>TizenBenchmark.png</icon>
+ <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+ </ui-application>
+</manifest>
--- /dev/null
+# csproj file path
+csproj_file: TizenBenchmark.csproj
+
+# files monitored for dirty/modified status
+files:
+ - TizenBenchmark.csproj
+ - TizenBenchmark.cs
+ - tizen-manifest.xml
+ - shared/res/TizenBenchmark.png
\ No newline at end of file
--- /dev/null
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
--- /dev/null
+# Default ignored files
+/shelf/
+/workspace.xml
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="CompilerConfiguration">
+ <bytecodeTargetLevel target="17" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="deploymentTargetSelector">
+ <selectionStates>
+ <SelectionState runConfigName="app">
+ <option name="selectionMode" value="DROPDOWN" />
+ </SelectionState>
+ </selectionStates>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="GradleMigrationSettings" migrationVersion="1" />
+ <component name="GradleSettings">
+ <option name="linkedExternalProjectsSettings">
+ <GradleProjectSettings>
+ <option name="externalProjectPath" value="$PROJECT_DIR$" />
+ <option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
+ <option name="modules">
+ <set>
+ <option value="$PROJECT_DIR$" />
+ <option value="$PROJECT_DIR$/app" />
+ </set>
+ </option>
+ <option name="resolveExternalAnnotations" value="false" />
+ </GradleProjectSettings>
+ </option>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectMigrations">
+ <option name="MigrateToGradleLocalJavaHome">
+ <set>
+ <option value="$PROJECT_DIR$" />
+ </set>
+ </option>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<project version="4">
+ <component name="ExternalStorageConfigurationManager" enabled="true" />
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/build/classes" />
+ </component>
+ <component name="ProjectType">
+ <option name="id" value="Android" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="direct_access_persist.xml">
+ <option name="deviceSelectionList">
+ <list>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="27" />
+ <option name="brand" value="DOCOMO" />
+ <option name="codename" value="F01L" />
+ <option name="id" value="F01L" />
+ <option name="manufacturer" value="FUJITSU" />
+ <option name="name" value="F-01L" />
+ <option name="screenDensity" value="360" />
+ <option name="screenX" value="720" />
+ <option name="screenY" value="1280" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="28" />
+ <option name="brand" value="DOCOMO" />
+ <option name="codename" value="SH-01L" />
+ <option name="id" value="SH-01L" />
+ <option name="manufacturer" value="SHARP" />
+ <option name="name" value="AQUOS sense2 SH-01L" />
+ <option name="screenDensity" value="480" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2160" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="31" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="a51" />
+ <option name="id" value="a51" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy A51" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="akita" />
+ <option name="id" value="akita" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 8a" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="b0q" />
+ <option name="id" value="b0q" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy S22 Ultra" />
+ <option name="screenDensity" value="600" />
+ <option name="screenX" value="1440" />
+ <option name="screenY" value="3088" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="32" />
+ <option name="brand" value="google" />
+ <option name="codename" value="bluejay" />
+ <option name="id" value="bluejay" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 6a" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="caiman" />
+ <option name="id" value="caiman" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 9 Pro" />
+ <option name="screenDensity" value="360" />
+ <option name="screenX" value="960" />
+ <option name="screenY" value="2142" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="comet" />
+ <option name="id" value="comet" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 9 Pro Fold" />
+ <option name="screenDensity" value="390" />
+ <option name="screenX" value="2076" />
+ <option name="screenY" value="2152" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="29" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="crownqlteue" />
+ <option name="id" value="crownqlteue" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy Note9" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="2220" />
+ <option name="screenY" value="1080" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="dm3q" />
+ <option name="id" value="dm3q" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy S23 Ultra" />
+ <option name="screenDensity" value="600" />
+ <option name="screenX" value="1440" />
+ <option name="screenY" value="3088" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="e1q" />
+ <option name="id" value="e1q" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy S24" />
+ <option name="screenDensity" value="480" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2340" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="google" />
+ <option name="codename" value="felix" />
+ <option name="id" value="felix" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel Fold" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="2208" />
+ <option name="screenY" value="1840" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="felix" />
+ <option name="id" value="felix" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel Fold" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="2208" />
+ <option name="screenY" value="1840" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="google" />
+ <option name="codename" value="felix_camera" />
+ <option name="id" value="felix_camera" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel Fold (Camera-enabled)" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="2208" />
+ <option name="screenY" value="1840" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="gts8uwifi" />
+ <option name="id" value="gts8uwifi" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy Tab S8 Ultra" />
+ <option name="screenDensity" value="320" />
+ <option name="screenX" value="1848" />
+ <option name="screenY" value="2960" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="husky" />
+ <option name="id" value="husky" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 8 Pro" />
+ <option name="screenDensity" value="390" />
+ <option name="screenX" value="1008" />
+ <option name="screenY" value="2244" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="30" />
+ <option name="brand" value="motorola" />
+ <option name="codename" value="java" />
+ <option name="id" value="java" />
+ <option name="manufacturer" value="Motorola" />
+ <option name="name" value="G20" />
+ <option name="screenDensity" value="280" />
+ <option name="screenX" value="720" />
+ <option name="screenY" value="1600" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="komodo" />
+ <option name="id" value="komodo" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 9 Pro XL" />
+ <option name="screenDensity" value="360" />
+ <option name="screenX" value="1008" />
+ <option name="screenY" value="2244" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="google" />
+ <option name="codename" value="lynx" />
+ <option name="id" value="lynx" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 7a" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="31" />
+ <option name="brand" value="google" />
+ <option name="codename" value="oriole" />
+ <option name="id" value="oriole" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 6" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="google" />
+ <option name="codename" value="panther" />
+ <option name="id" value="panther" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 7" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="q5q" />
+ <option name="id" value="q5q" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy Z Fold5" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1812" />
+ <option name="screenY" value="2176" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="30" />
+ <option name="brand" value="google" />
+ <option name="codename" value="r11" />
+ <option name="id" value="r11" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel Watch" />
+ <option name="screenDensity" value="320" />
+ <option name="screenX" value="384" />
+ <option name="screenY" value="384" />
+ <option name="type" value="WEAR_OS" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="30" />
+ <option name="brand" value="google" />
+ <option name="codename" value="redfin" />
+ <option name="id" value="redfin" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 5" />
+ <option name="screenDensity" value="440" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2340" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="shiba" />
+ <option name="id" value="shiba" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 8" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2400" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="33" />
+ <option name="brand" value="google" />
+ <option name="codename" value="tangorpro" />
+ <option name="id" value="tangorpro" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel Tablet" />
+ <option name="screenDensity" value="320" />
+ <option name="screenX" value="1600" />
+ <option name="screenY" value="2560" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="34" />
+ <option name="brand" value="google" />
+ <option name="codename" value="tokay" />
+ <option name="id" value="tokay" />
+ <option name="manufacturer" value="Google" />
+ <option name="name" value="Pixel 9" />
+ <option name="screenDensity" value="420" />
+ <option name="screenX" value="1080" />
+ <option name="screenY" value="2424" />
+ </PersistentDeviceSelectionData>
+ <PersistentDeviceSelectionData>
+ <option name="api" value="29" />
+ <option name="brand" value="samsung" />
+ <option name="codename" value="x1q" />
+ <option name="id" value="x1q" />
+ <option name="manufacturer" value="Samsung" />
+ <option name="name" value="Galaxy S20" />
+ <option name="screenDensity" value="480" />
+ <option name="screenX" value="1440" />
+ <option name="screenY" value="3200" />
+ </PersistentDeviceSelectionData>
+ </list>
+ </option>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+/build
\ No newline at end of file
--- /dev/null
+plugins {
+ alias(libs.plugins.android.application)
+}
+
+android {
+ namespace 'com.android.gctest'
+ compileSdk 34
+
+ defaultConfig {
+ applicationId "com.android.gctest"
+ minSdk 29
+ targetSdk 34
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+}
+
+dependencies {
+
+ implementation libs.appcompat
+ implementation libs.material
+ implementation libs.activity
+ implementation libs.constraintlayout
+ implementation files('achartengine/achartengine-1.2.0.jar')
+ testImplementation libs.junit
+ androidTestImplementation libs.ext.junit
+ androidTestImplementation libs.espresso.core
+}
\ No newline at end of file
--- /dev/null
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
--- /dev/null
+package com.android.gctest;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.android.gctest", appContext.getPackageName());
+ }
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools">
+
+ <application
+ android:allowBackup="true"
+ android:dataExtractionRules="@xml/data_extraction_rules"
+ android:fullBackupContent="@xml/backup_rules"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:roundIcon="@mipmap/ic_launcher_round"
+ android:supportsRtl="true"
+ android:theme="@style/Theme.AndroidGCTest"
+ tools:targetApi="31"
+ android:largeHeap="true">
+ <activity
+ android:name=".MainActivity"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".ResultActivity" >
+ </activity>
+ <activity
+ android:name=".ProfileSettingActivity" >
+ </activity>
+ </application>
+
+</manifest>
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.gctest;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Random;
+import java.lang.reflect.Method;
+
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Debug;
+import android.os.Message;
+import android.os.Parcelable;
+import android.os.SystemClock;
+import android.util.Log;
+
+// 6 kinds of small objects
+class TreeNode { // object size = 16
+ TreeNode left, right;
+ TreeNode (TreeNode l, TreeNode r) { left = l; right = r; }
+ TreeNode () { }
+ int count() {
+ int c = 1;
+ if (left != null)
+ c += left.count();
+ if (right != null)
+ c += right.count();
+ return c;
+ }
+}
+
+class TreeNode32 extends TreeNode { // object size = 24
+ private long payload1;
+ TreeNode32(TreeNode32 l, TreeNode32 r) { left = l; right = r; }
+ TreeNode32() { }
+}
+
+class TreeNode64 extends TreeNode { // object size = 40
+ private long payload1, payload2, payload3;
+ TreeNode64(TreeNode64 l, TreeNode64 r) { left = l; right = r; }
+ TreeNode64() { }
+}
+
+class TreeNode128 extends TreeNode { // object size = 96
+ private long payload1, payload2, payload3, payload4, payload5;
+ private long payload6, payload7, payload8, payload9, payload10;
+ TreeNode128(TreeNode128 l, TreeNode128 r) { left = l; right = r; }
+ TreeNode128() { }
+}
+
+class TreeNode256 extends TreeNode { // object size = 192
+ private long payload1, payload2, payload3, payload4, payload5;
+ private long payload6, payload7, payload8, payload9, payload10;
+ private long payload11, payload12, payload13, payload14, payload15;
+ private long payload16, payload17, payload18, payload19, payload20;
+ private long payload21, payload22;
+ TreeNode256(TreeNode256 l, TreeNode256 r) { left = l; right = r; }
+ TreeNode256() { }
+}
+
+class TreeNode512 extends TreeNode { // object size = 336
+ private long payload1, payload2, payload3, payload4, payload5;
+ private long payload6, payload7, payload8, payload9, payload10;
+ private long payload11, payload12, payload13, payload14, payload15;
+ private long payload16, payload17, payload18, payload19, payload20;
+ private long payload101, payload102, payload103, payload104, payload105;
+ private long payload106, payload107, payload108, payload109, payload100;
+ private long payload111, payload112, payload113, payload114, payload115;
+ private long payload116, payload117, payload118, payload119, payload120;
+ TreeNode512(TreeNode512 l, TreeNode512 r) { left = l; right = r; }
+ TreeNode512() { }
+}
+
+class LinkNode {
+ LinkNode next;
+ TreeNode treeNode;
+ LinkNode(TreeNode n) { treeNode = n; }
+ LinkNode() { }
+}
+
+class LivedLink {
+ public LinkNode treeHead;
+ LivedLink() { treeHead = null;}
+ void insertNode(TreeNode newTree) {
+ if (treeHead == null) {
+ treeHead = new LinkNode(newTree);
+ treeHead.next = null;
+ } else {
+ LinkNode newNode = new LinkNode(newTree);
+ newNode.next = treeHead;
+ treeHead = newNode;
+ }
+ }
+}
+
+public class AndroidGCTestMain {
+ private final String mTag = "AndroidGCTest";
+ private MainActivity mActivity = null;
+
+ // size of small objects
+ public static final int OBJECT_16_BYTE = 0;
+ public static final int OBJECT_32_BYTE = 1;
+ public static final int OBJECT_64_BYTE = 2;
+ public static final int OBJECT_128_BYTE = 3;
+ public static final int OBJECT_256_BYTE = 4;
+ public static final int OBJECT_512_BYTE = 5;
+ public static final int OBJECT_LARGE_BYTE = 6;
+ public static final int OBJECT_SIZE_TYPE = 7;
+ private final int[] mObjectSize = new int[]{16, 24, 40, 96, 192, 336};
+
+ // size of large object, default is 12KByte
+ private int mLargeObjectSize = 0;
+ // array element type distribution for large object
+ // {1-byte array, 2-byte array, 4-byte array, 8-byte array}
+ private float[] mLargeObjectDistribution = null;
+
+ // allocation configuration
+ // total allocate size
+ private int mTotalAllocateSize = 0;
+ // total allocate size by one thread
+ private int mTotalAllocSizePerThread = 0;
+
+ // unit for tree allocation/deletion operation.
+ // mBucketSize is also the unit to measure object lifetime.
+ // Benchmark allocates mBucketSize of data -> deletes some data
+ // -> allocates mBucketSize of Data
+ private int mBucketSize = 0;
+
+ // allocated object size distribution
+ // {[1-16], [17-32], [33-64], [65, 128], [129, 256], [257, 512], >12K}
+ private float[] mSizeDistribution = null;
+
+ // allocated object lifetime:
+ // mLifetime[X][0] is long lived object percentage of object size X,
+ // mLifetime[X][1] is percentage of object die immediately,
+ // mLifetime[X][2] is percentage of object die in next period after
+ // creation period ...
+ private float[][] mLifetime = null;
+
+ private int mLongLiveSmallObjectSize;
+
+ // a big array to store random values to decide object size of next allocated object
+ private byte[][] mObjectSizeRandom = null;
+ // a big array to store random values to decide lifetime of next allocated object
+ private byte[][] mLifetimeRandom = null;
+ private int mShortLiveTreeCount;
+ private int mTotalNodeCount;
+ private final int mTreeCountParallel = 4;
+
+ private int[] mLargeArrayLength = null;
+ private int[] mLargeArrayNum = null;
+ private int[] mLargeArrayInter = null;
+ private int mLongLiveLargeObjectSize;
+ private int[][] mDieNumLargeObject = null;
+
+ // thread mode configuration
+ private int mThreadNum;
+ private boolean mSingleThread = false;
+
+ private long[] mElapseTime = null;
+ private int[] mHeapFootprint = null;
+ private long[] mHeapBytesAllocated = null;
+
+ private long mTotalGcCount;
+ private long mTotalGcTime;
+ private long mTotalBlockingGcCount;
+ private long mTotalBlockingGcTime;
+ public final String[] GC_CAUSE_ART = new String[]{"Alloc", "Background", "Explicit",
+ "NativeAlloc", "CollectorTransition", "DisableMovingGc", "HomogeneousSpaceCompact",
+ "HeapTrim"};
+ public final String[] GC_CAUSE_DALVIK = new String[]{"GC_FOR_ALLOC","GC_CONCURRENT",
+ "GC_EXPLICIT", "GC_BEFORE_OOM"};
+ private int[] mGcCauseCount = null;
+ private float[] mGcPauseTime = null;
+ private float[] mGcTotalTime = null;
+ private String[] mGcCause = null;
+
+ private boolean isArt;
+ private boolean mWorkloadComplete;
+ private int mIterNum = 100;
+
+ private FileWriter fileOutput;
+ private BenchThread[] mTestThreads;
+ private boolean mOutOfMemory;
+
+ // initialize benchmark setting
+ private void init() {
+ // thread number;
+ if (mSingleThread) {
+ mThreadNum = 1;
+ } else if (mThreadNum == 0) {
+ mThreadNum = Runtime.getRuntime().availableProcessors();
+ }
+ if (mThreadNum == 0) {
+ mThreadNum = 1;
+ }
+
+ if (mSizeDistribution == null) {
+ mSizeDistribution = new float[]{0.0436f,0.5465f,0.2103f,0.1499f,
+ 0.0275f,0.0125f,0.0097f};
+ }
+ if (mLifetime == null) {
+ mLifetime = new float[][] {
+ {0.0865f,0.5404f,0.2887f,0.0865f},
+ {0.0469f,0.7724f,0.1460f,0.0346f},
+ {0.1154f,0.5982f,0.1880f,0.0984f},
+ {0.0662f,0.7851f,0.1077f,0.0411f},
+ {0.0520f,0.8778f,0.0503f,0.0198f},
+ {0.1628f,0.7137f,0.0821f,0.0414f},
+ {0.0923f,0.7117f,0.1769f,0.0192f} // large object lifetime
+ };
+ }
+
+ if (mLargeObjectDistribution == null) {
+ mLargeObjectDistribution = new float[]{0.9f, 0.07f, 0.02f, 0.01f};
+ }
+
+ if (mTotalAllocateSize == 0) {
+ mTotalAllocateSize = 100 * 1024 * 1024;
+ }
+ mTotalAllocSizePerThread = mTotalAllocateSize / mThreadNum;
+
+ if (mBucketSize == 0) {
+ mBucketSize = 1 * 1024 * 1024;
+ }
+
+ if (mLargeObjectSize == 0) {
+ mLargeObjectSize = 12 * 1024;
+ }
+
+ Log.i(mTag, "Allocate Size: " + (mTotalAllocateSize / 1024) + " kB");
+ Log.i(mTag, "BucketSize: " + (mBucketSize / 1024) + " kB");
+ Log.i(mTag, "Large object size: " + (mLargeObjectSize / 1024) + " kB");
+ Log.i(mTag, "Single Thread: " + mSingleThread);
+ Log.i(mTag, "Thread number: " + mThreadNum);
+ Log.i(mTag, "Stress test part iterates " + mIterNum + " times");
+
+ String curDate = DateFormat.getDateTimeInstance().format(Calendar.getInstance().getTime());
+ try {
+ fileOutput = new FileWriter("/sdcard/AndroidGCTest-result.txt", true);
+ fileOutput.append("\n\n" + curDate);
+
+ fileOutput.append("\nWorkload configuration:");
+ fileOutput.append("\n\tAllocate Size: " + (mTotalAllocateSize / 1024) + " kB");
+ fileOutput.append("\n\tBucketSize: " + (mBucketSize / 1024) + " kB");
+ fileOutput.append("\n\tLarge object size: " + (mLargeObjectSize / 1024) + " kB");
+ fileOutput.append("\n\tThread mode: "
+ + (mSingleThread? "Single-Thread" : "Multi-Thread"));
+ fileOutput.append("\n\tThread number: " + mThreadNum);
+ fileOutput.append("\n\tStress test part iterates " + mIterNum + " times");
+ } catch (IOException e) {
+ Log.i(mTag, "Cannot open /sdcard/AndroidGCTest-result.txt" + e.getMessage());
+ }
+
+ int smallObjectSize, largeObjectSize;
+ largeObjectSize = (int)(mTotalAllocSizePerThread * mSizeDistribution[OBJECT_LARGE_BYTE]);
+ smallObjectSize = mTotalAllocSizePerThread - largeObjectSize;
+
+ float[] countDistr = new float[OBJECT_LARGE_BYTE];
+ float nodeSize = 0.0f;
+ int[] sizeThreshold = new int[OBJECT_LARGE_BYTE];
+ int lifetimeLen = mLifetime[0].length;
+ int[][] lifetimeThreshold = new int[OBJECT_LARGE_BYTE][lifetimeLen];
+ float sum = 0.0f;
+ for (int i = 0; i < OBJECT_LARGE_BYTE; i++) {
+ countDistr[i] = mSizeDistribution[i]
+ / (1 - mSizeDistribution[OBJECT_LARGE_BYTE]) / mObjectSize[i];
+ sum += countDistr[i];
+ }
+
+ mLongLiveSmallObjectSize = 0;
+ float sum1 = 0.0f;
+ for (int i = 0; i < OBJECT_LARGE_BYTE; i++) {
+ sum1 += countDistr[i];
+ sizeThreshold[i] = (int)(sum1 * 1000 / sum + 0.5);
+ nodeSize += mObjectSize[i] * countDistr[i] / sum;
+
+ float sum2 = 0.0f;
+ for (int j = 1; j < lifetimeLen; j++) {
+ sum2 += mLifetime[i][j];
+ lifetimeThreshold[i][j-1] = (int)(sum2 * 1000 + 0.5);
+ }
+ lifetimeThreshold[i][lifetimeLen - 1] = 1000;
+
+ mLongLiveSmallObjectSize += mTotalAllocSizePerThread * mSizeDistribution[i]
+ * mLifetime[i][0];
+ }
+ sizeThreshold[OBJECT_512_BYTE] = 1000;
+
+
+ mShortLiveTreeCount = (int)(smallObjectSize / mBucketSize + 0.5);
+ mTotalNodeCount = (int)(mBucketSize / nodeSize * 1.11);
+
+ mObjectSizeRandom = new byte[mThreadNum][mTotalNodeCount];
+ mLifetimeRandom = new byte[mThreadNum][mTotalNodeCount];
+ for (int i = 0; i < mThreadNum; i++) {
+ Random r_size = new Random(i);
+ Random r_lifetime = new Random(i + mThreadNum);
+ for (int j = 0; j < mTotalNodeCount; j++) {
+ int vs = r_size.nextInt(1000);
+ int vl = r_lifetime.nextInt(1000);
+ for (int k = 0; k < OBJECT_LARGE_BYTE; k++) {
+ if (vs < sizeThreshold[k]) {
+ mObjectSizeRandom[i][j] = (byte)(OBJECT_16_BYTE + k);
+ for (int l = 0; l < lifetimeLen; l++) {
+ if (vl < lifetimeThreshold[k][l]) {
+ mLifetimeRandom[i][j] = (byte)l;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ mLongLiveLargeObjectSize = (int)(largeObjectSize * mLifetime[OBJECT_LARGE_BYTE][0]);
+ mDieNumLargeObject = new int[4][lifetimeLen - 1];
+ mLargeArrayInter = new int[4];
+ mLargeArrayLength = new int[4];
+ mLargeArrayNum = new int[4];
+ for (int i = 0; i < 4; i++) {
+ mLargeArrayLength[i] = (int)((largeObjectSize * mLargeObjectDistribution[i]
+ / mLargeObjectSize) + 0.5);
+ if (mLargeArrayLength[i] == 0) {
+ mLargeArrayInter[i] = mShortLiveTreeCount + 1;
+ mLargeArrayNum[i] = 0;
+ continue;
+ }
+ if (mShortLiveTreeCount > mLargeArrayLength[i]) {
+ mLargeArrayInter[i] = mShortLiveTreeCount / mLargeArrayLength[i];
+ mLargeArrayNum[i] = 1;
+ mLargeArrayLength[i] = mShortLiveTreeCount/mLargeArrayInter[i] + 1;
+ } else {
+ mLargeArrayInter[i] = 1;
+ mLargeArrayNum[i] = (int)(mLargeArrayLength[i]/(float)mShortLiveTreeCount + 0.5);
+ mLargeArrayLength[i] = mLargeArrayNum[i] * mShortLiveTreeCount;
+ }
+
+ sum = 0.0f;
+ for (int j = 1; j < lifetimeLen; j++) {
+ sum += mLifetime[OBJECT_LARGE_BYTE][j];
+ mDieNumLargeObject[i][j-1] = (int)(mLargeArrayNum[i] * sum);
+ }
+ }
+
+ Log.i(mTag, "init done");
+ }
+
+ private void clearInitData() {
+ Log.i(mTag, "clear auxiliary data to run workload");
+ mLifetime = null;
+ mLargeObjectDistribution = null;
+ mSizeDistribution = null;
+ mObjectSizeRandom = null;
+ mLifetimeRandom = null;
+ mLargeArrayInter = null;
+ mLargeArrayLength = null;
+ mLargeArrayNum = null;
+ mDieNumLargeObject = null;
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ }
+
+ AndroidGCTestMain() {
+ init();
+ }
+ AndroidGCTestMain(MainActivity activity, int heapSize, int bucketSize, int largeObjectSize,
+ float[]sizeDistr, float[][] lifetimeDistr, float[] largeObjectSizeDist,
+ boolean singleThread, int thread_num, int exeTime) {
+ mActivity = activity;
+ mTotalAllocateSize = heapSize * 1024 * 1024;
+ mBucketSize = bucketSize * 1024 * 1024;
+ mLargeObjectSize = largeObjectSize * 1024;
+ mSizeDistribution = sizeDistr;
+ mLifetime = lifetimeDistr;
+ mLargeObjectDistribution = largeObjectSizeDist;
+ mSingleThread = singleThread;
+ mThreadNum = mSingleThread? 1 : thread_num;
+ mIterNum = exeTime > 0 ? exeTime : 100;
+ init();
+ }
+
+ private void freeArrays(byte[][] byteArray, char[][] charArray, int[][] intArray,
+ long[][] longArray, int[] arrayIdx, int treeCount) {
+ int len = mDieNumLargeObject[0].length;
+ int died, release, phase;
+
+ phase = treeCount % mLargeArrayInter[0];
+ if (byteArray != null && phase <= len) {
+ int curIdx = arrayIdx[0] - mLargeArrayNum[0];
+ while (curIdx >= 0 && phase <= len) {
+ if (phase == 0)
+ died = 0;
+ else
+ died = mDieNumLargeObject[0][phase - 1];
+ if (phase == len) {
+ if (byteArray[curIdx + died] != null) {
+ for (int i = died; i < mLargeArrayNum[0]; i++)
+ byteArray[curIdx + i] = null;
+ }
+ break;
+ }
+ release = mDieNumLargeObject[0][phase];
+ for (int i = died; i < release; i++) {
+ if (i >= mLargeArrayNum[0])
+ break;
+ byteArray[curIdx + i] = null;
+ }
+ curIdx -= mLargeArrayNum[0];
+ phase += mLargeArrayInter[0];
+ }
+ }
+
+ phase = treeCount % mLargeArrayInter[1];
+ if (charArray != null && phase < mLargeArrayNum[1]) {
+ int curIdx = arrayIdx[1] - mLargeArrayNum[1];
+ while (curIdx >= 0 && phase <= len) {
+ if (phase == 0)
+ died = 0;
+ else
+ died = mDieNumLargeObject[1][phase - 1];
+ if (phase == len) {
+ if (charArray[curIdx + died] != null) {
+ for (int i = died; i < mLargeArrayNum[1]; i++)
+ charArray[curIdx + i] = null;
+ }
+ break;
+ }
+ release = mDieNumLargeObject[1][phase];
+ for (int i = died; i < release; i++) {
+ if (i >= mLargeArrayNum[1])
+ break;
+ charArray[curIdx + i] = null;
+ }
+ curIdx -= mLargeArrayNum[1];
+ phase += mLargeArrayInter[1];
+ }
+ }
+
+ phase = treeCount % mLargeArrayInter[2];
+ if (intArray != null && phase < mLargeArrayNum[2]) {
+ int curIdx = arrayIdx[2] - mLargeArrayNum[2];
+ while (curIdx >= 0 && phase <= len) {
+ if (phase == 0)
+ died = 0;
+ else
+ died = mDieNumLargeObject[2][phase - 1];
+ if (phase == len) {
+ if (intArray[curIdx + died] != null) {
+ for (int i = died; i < mLargeArrayNum[2]; i++)
+ intArray[curIdx + i] = null;
+ }
+ break;
+ }
+ release = mDieNumLargeObject[2][phase];
+ for (int i = died; i < release; i++) {
+ if (i >= mLargeArrayNum[2])
+ break;
+ intArray[curIdx + i] = null;
+ }
+ curIdx -= mLargeArrayNum[2];
+ phase += mLargeArrayInter[2];
+ }
+ }
+
+ phase = treeCount % mLargeArrayInter[3];
+ if (longArray != null && phase < mLargeArrayNum[3]) {
+ int curIdx = arrayIdx[3] - mLargeArrayNum[3];
+ while (curIdx >= 0 && phase <= len) {
+ if (phase == 0)
+ died = 0;
+ else
+ died = mDieNumLargeObject[3][phase - 1];
+ if (phase == len) {
+ if (longArray[curIdx + died] != null) {
+ for (int i = died; i < mLargeArrayNum[3]; i++)
+ longArray[curIdx + i] = null;
+ }
+ break;
+ }
+ release = mDieNumLargeObject[3][phase];
+ for (int i = died; i < release; i++) {
+ if (i >= mLargeArrayNum[3])
+ break;
+ longArray[curIdx + i] = null;
+ }
+ curIdx -= mLargeArrayNum[3];
+ phase += mLargeArrayInter[3];
+ }
+ }
+ }
+
+ private void makeTreesLongLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount) {
+ while (true) {
+ if (allocSize <= 0) {
+ trees = null;
+ return;
+ }
+
+ int len = trees.length;
+ TreeNode[] nextTrees = new TreeNode[len*2];
+ byte random;
+ for (int i = 0; i < len; i++) {
+ TreeNode node = null;
+ random = mObjectSizeRandom[myId][nodeCount[0]];
+ switch (random) {
+ case OBJECT_16_BYTE:
+ node = new TreeNode();
+ break;
+ case OBJECT_32_BYTE:
+ node = new TreeNode32();
+ break;
+ case OBJECT_64_BYTE:
+ node = new TreeNode64();
+ break;
+ case OBJECT_128_BYTE:
+ node = new TreeNode128();
+ break;
+ case OBJECT_256_BYTE:
+ node = new TreeNode256();
+ break;
+ case OBJECT_512_BYTE:
+ node = new TreeNode512();
+ break;
+ }
+ trees[i].left = node;
+ nextTrees[2 * i] = node;
+ allocSize -= mObjectSize[random];
+ nodeCount[0]++;
+ if (nodeCount[0] == mTotalNodeCount)
+ nodeCount[0] = 0;
+
+ random = mObjectSizeRandom[myId][nodeCount[0]];
+ switch (random) {
+ case OBJECT_16_BYTE:
+ node = new TreeNode();
+ break;
+ case OBJECT_32_BYTE:
+ node = new TreeNode32();
+ break;
+ case OBJECT_64_BYTE:
+ node = new TreeNode64();
+ break;
+ case OBJECT_128_BYTE:
+ node = new TreeNode128();
+ break;
+ case OBJECT_256_BYTE:
+ node = new TreeNode256();
+ break;
+ case OBJECT_512_BYTE:
+ node = new TreeNode512();
+ break;
+ }
+ trees[i].right = node;
+ nextTrees[2*i + 1] = node;
+ allocSize -= mObjectSize[random];
+ nodeCount[0]++;
+ if (nodeCount[0] == mTotalNodeCount)
+ nodeCount[0] = 0;
+
+ if (allocSize <= 0) {
+ trees = null;
+ break;
+ }
+ }
+ trees = null;
+ trees = nextTrees;
+ }
+ }
+
+ private void makeTreesShortLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount) {
+ int lifetimeLen = mLifetime[0].length;
+ int[] curTreeIdx = new int[lifetimeLen];
+ int[] nextTreeIdx = new int[lifetimeLen];
+ TreeNode[][] curTrees = new TreeNode[lifetimeLen][1];
+ TreeNode[][] nextTrees = new TreeNode[lifetimeLen][];
+ for (int i = 0; i < lifetimeLen; i++) {
+ curTrees[i][0] = trees[i];
+ curTreeIdx[i] = 0;
+ }
+
+ while (true) {
+ if (allocSize <= 0) {
+ trees = null;
+ return;
+ }
+
+ byte rs = mObjectSizeRandom[myId][nodeCount[0]];
+ TreeNode node = null;
+ switch (rs) {
+ case OBJECT_16_BYTE:
+ node = new TreeNode();
+ break;
+ case OBJECT_32_BYTE:
+ node = new TreeNode32();
+ break;
+ case OBJECT_64_BYTE:
+ node = new TreeNode64();
+ break;
+ case OBJECT_128_BYTE:
+ node = new TreeNode128();
+ break;
+ case OBJECT_256_BYTE:
+ node = new TreeNode256();
+ break;
+ case OBJECT_512_BYTE:
+ node = new TreeNode512();
+ break;
+ }
+
+ byte rl = mLifetimeRandom[myId][nodeCount[0]];
+ if (nextTrees[rl] == null) {
+ nextTrees[rl] = new TreeNode[curTrees[rl].length << 1];
+ nextTreeIdx[rl] = 0;
+ nextTrees[rl][0] = node;
+ } else {
+ nextTrees[rl][++nextTreeIdx[rl]] = node;
+ }
+ TreeNode parent = curTrees[rl][curTreeIdx[rl]];
+ if (parent.left == null) {
+ parent.left = node;
+ } else {
+ parent.right = node;
+ curTreeIdx[rl]++;
+ if (curTreeIdx[rl] == curTrees[rl].length) {
+ curTrees[rl] = nextTrees[rl];
+ nextTrees[rl] = null;
+ curTreeIdx[rl] = 0;
+ }
+ }
+
+ allocSize -= mObjectSize[rs];
+ nodeCount[0]++;
+ if (nodeCount[0] == mTotalNodeCount) nodeCount[0] = 0;
+ }
+ }
+
+ public boolean allocTrace(int myId) throws OutOfMemoryError {
+ // long-lived data
+ Log.i(mTag, "Thread-" + myId + " ----- Build long lived trees -----");
+
+ LivedLink longLiveTreeLink = new LivedLink();
+ TreeNode[] trees = new TreeNode[mTreeCountParallel];
+
+ int[] nodeCount = new int[]{0};
+ for (int i = 0; i < mTreeCountParallel; i++) {
+ TreeNode node = new TreeNode();
+ longLiveTreeLink.insertNode(node);
+ trees[i] = node;
+ }
+
+ makeTreesLongLive(trees, mLongLiveSmallObjectSize, myId, nodeCount);
+
+ trees = null;
+
+ Log.i(mTag, "Thread-" + myId + " ----- Build long lived byte array -----");
+ int longLiveArrayCount = (int)(mLongLiveLargeObjectSize / mLargeObjectSize + 0.5);
+ if (longLiveArrayCount <= 0)
+ longLiveArrayCount = 1;
+ byte[][] longLiveByteArrays = new byte[longLiveArrayCount][];
+ for (int i = 0; i < longLiveArrayCount; i++) {
+ longLiveByteArrays[i] = new byte[mLargeObjectSize];
+ for (int j = 0; j < mLargeObjectSize; j+=100)
+ longLiveByteArrays[i][j] = (byte) 0xff;
+ }
+
+ // stress test
+ Log.i(mTag, "Thread-" + myId + " ----- Stress test -----");
+ Debug.MemoryInfo memInfo = new Debug.MemoryInfo();
+
+ int lifetimeLen = mLifetime[0].length;
+ TreeNode[][] shortLiveTrees = new TreeNode[lifetimeLen][lifetimeLen];
+
+ byte[][] shortLiveByteArray = null;
+ char[][] shortLiveCharArray = null;
+ int[][] shortLiveIntArray = null;
+ long[][] shortLiveLongArray = null;
+
+ nodeCount[0] = 0;
+ int round = 0;
+
+ for (int iter = 0; iter < mIterNum; iter++) {
+ if (mOutOfMemory)
+ break;
+ int[] allocIdx = new int[]{0, 0, 0, 0};
+
+ if (mLargeArrayLength[0] != 0)
+ shortLiveByteArray = new byte[mLargeArrayLength[0]][];
+ if (mLargeArrayLength[1] != 0)
+ shortLiveCharArray = new char[mLargeArrayLength[1]][];
+ if (mLargeArrayLength[2] != 0)
+ shortLiveIntArray = new int[mLargeArrayLength[2]][];
+ if (mLargeArrayLength[3] != 0)
+ shortLiveLongArray = new long[mLargeArrayLength[3]][];
+
+ int treeCount = 0;
+ while (treeCount < mShortLiveTreeCount) {
+ int treesIdx = round % lifetimeLen;
+ round++;
+ for (int i = 0; i < lifetimeLen; i++) {
+ TreeNode node = new TreeNode();
+ shortLiveTrees[treesIdx][i] = node;
+ }
+ makeTreesShortLive(shortLiveTrees[treesIdx], mBucketSize, myId, nodeCount);
+
+ for (int i = 0; i < lifetimeLen; i++) {
+ int idx = (treesIdx - i + lifetimeLen) % lifetimeLen;
+ shortLiveTrees[idx][i] = null;
+ }
+
+ if ((mLargeArrayLength[0] > 0) && ((treeCount % mLargeArrayInter[0]) == 0)) {
+ for (int n = 0; n < mLargeArrayNum[0]; n++)
+ shortLiveByteArray[allocIdx[0] + n] = new byte[mLargeObjectSize];
+ allocIdx[0] += mLargeArrayNum[0];
+ }
+
+ if ((mLargeArrayLength[1] > 0) && ((treeCount % mLargeArrayInter[1]) == 0)) {
+ for (int n = 0; n < mLargeArrayNum[1]; n++)
+ shortLiveCharArray[allocIdx[1] + n] = new char[mLargeObjectSize/2];
+ allocIdx[1] += mLargeArrayNum[1];
+ }
+
+ if ((mLargeArrayLength[2] > 0) && ((treeCount % mLargeArrayInter[2]) == 0)) {
+ for (int n = 0; n < mLargeArrayNum[2]; n++)
+ shortLiveIntArray[allocIdx[2] + n] = new int[mLargeObjectSize/4];
+ allocIdx[2] += mLargeArrayNum[2];
+ }
+
+ if ((mLargeArrayLength[3] > 0) && ((treeCount % mLargeArrayInter[3]) == 0)) {
+ for (int n = 0; n < mLargeArrayNum[3]; n++)
+ shortLiveLongArray[allocIdx[3] + n] = new long[mLargeObjectSize/8];
+ allocIdx[3] += mLargeArrayNum[3];
+ }
+
+ freeArrays(shortLiveByteArray, shortLiveCharArray, shortLiveIntArray,
+ shortLiveLongArray, allocIdx, treeCount);
+
+ treeCount++;
+ }
+
+ if (myId == 0) {
+ Debug.getMemoryInfo(memInfo);
+ mHeapFootprint[iter] = memInfo.dalvikPss;
+ if (getRuntimeStatMethod != null)
+ mHeapBytesAllocated[iter] = (getRuntimeStat("art.gc.bytes-allocated")
+ - getRuntimeStat("art.gc.bytes-freed")) / 1024;
+ else
+ mHeapBytesAllocated[iter] = (Runtime.getRuntime().totalMemory()
+ - Runtime.getRuntime().freeMemory()) / 1024;
+
+ Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkProgress);
+ m.arg1 = iter + 1;
+ mActivity.getHandler().sendMessage(m);
+ }
+ }
+
+ if (longLiveTreeLink.treeHead.treeNode != null
+ && longLiveByteArrays[0][100] == (byte)0xff
+ && longLiveByteArrays[longLiveArrayCount - 1][200] == (byte)0xff)
+ return true;
+ return false;
+ }
+
+ class BenchThread extends Thread {
+ private int myId;
+ BenchThread (int id) {
+ super();
+ myId = id;
+ }
+ public void run() {
+ mElapseTime[myId] = 0;
+ long start = System.currentTimeMillis();
+ try {
+ if (!allocTrace(myId))
+ Log.i(mTag, "Error in thread-" + myId);
+ } catch (OutOfMemoryError e) {
+ mOutOfMemory = true;
+ Log.i(mTag, "Thread-" + myId + " meets OutOfMemory");
+
+ Message m = mActivity.getHandler().obtainMessage(
+ MainActivity.BenchmarkOutOfMemoryError);
+ m.arg1 = myId;
+ mActivity.getHandler().sendMessage(m);
+ }
+ mElapseTime[myId] = System.currentTimeMillis() - start;
+ }
+ }
+
+ public void start() {
+ if (getRuntimeStatMethod == null) {
+ try {
+ Class c = Class.forName("android.os.Debug");
+ getRuntimeStatMethod = c.getDeclaredMethod("getRuntimeStat", String.class);
+ } catch (ClassNotFoundException e) {
+ Log.w(mTag, "Cannot find android.os.Debug class");
+ } catch (NoSuchMethodException e) {
+ Log.w(mTag, "No getRuntimeStat method in android.os.Debug");
+ }
+ }
+ mElapseTime = new long[mThreadNum];
+ mHeapFootprint = new int[mIterNum];
+ mHeapBytesAllocated = new long[mIterNum];
+ isArt = false;
+ String vmVersion = System.getProperty("java.vm.version");
+ isArt = vmVersion != null && vmVersion.startsWith("2");
+ String androidVersion = Build.VERSION.RELEASE;
+ String deviceName = Build.MODEL;
+ String deviceDesc = deviceName + "/" + "android-" + androidVersion
+ + ", runtime: " + (isArt? "ART" :"Dalvik");
+ mTotalGcCount = getRuntimeStat("art.gc.gc-count");
+ mTotalGcTime = getRuntimeStat("art.gc.gc-time");
+ mTotalBlockingGcCount = getRuntimeStat("art.gc.blocking-gc-count");
+ mTotalBlockingGcTime = getRuntimeStat("art.gc.blocking-gc-time");
+ if (isArt)
+ mGcCauseCount = new int[]{0, 0, 0, 0, 0, 0, 0, 0};
+ else
+ mGcCauseCount = new int[]{0, 0, 0, 0};
+
+ mWorkloadComplete = false;
+ clearLogcat();
+ Thread logcat = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ readLogcat();
+ }
+ });
+ logcat.start();
+
+ mOutOfMemory = false;
+ mTestThreads = new BenchThread[mThreadNum];
+ for (int i = 1; i < mThreadNum; i++) {
+ mTestThreads[i] = new BenchThread(i);
+ mTestThreads[i].start();
+ }
+
+ mElapseTime[0] = 0;
+ long start = System.currentTimeMillis();
+ try {
+ if (!allocTrace(0))
+ Log.i(mTag, "Error in thread-0");
+ } catch (OutOfMemoryError e) {
+ mOutOfMemory = true;
+ Log.i(mTag, "Thread-0 meets OutOfMemory");
+ Message m = mActivity.getHandler().obtainMessage(
+ MainActivity.BenchmarkOutOfMemoryError);
+ m.arg1 = 0;
+ mActivity.getHandler().sendMessage(m);
+ }
+ mElapseTime[0] = System.currentTimeMillis() - start;
+
+ for (int i = 1; i < mThreadNum; i++) {
+ try {
+ mTestThreads[i].join();
+ } catch (InterruptedException e) {
+ Log.i(mTag, "Waiting thread " + i + " finish interrupted by "
+ + e.getLocalizedMessage());
+ }
+ }
+ SystemClock.sleep(1000);
+ mWorkloadComplete = true;
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ try {
+ logcat.join();
+ } catch (InterruptedException e) {
+ Log.i(mTag, "Waiting logcat finish interrupted by " + e.getLocalizedMessage());
+ }
+ if (mOutOfMemory) {
+ try {
+ if (fileOutput != null) {
+ fileOutput.append("\nOutOfMemory! Please config proifle or "
+ + "Java Runtime and run again!\n");
+ fileOutput.flush();
+ fileOutput.close();
+ }
+ } catch (IOException e) {
+ Log.i(mTag, "Cannot write to /sdcard/AndroidGCTest-result.txt"
+ + e.getMessage());
+ }
+ } else {
+ mTotalGcCount = getRuntimeStat("art.gc.gc-count") - mTotalGcCount;
+ mTotalGcTime = getRuntimeStat("art.gc.gc-time") - mTotalGcTime;
+ mTotalBlockingGcCount = getRuntimeStat("art.gc.blocking-gc-count")
+ - mTotalBlockingGcCount;
+ mTotalBlockingGcTime = getRuntimeStat("art.gc.blocking-gc-time")
+ - mTotalBlockingGcTime;
+ long maxTime = 0;
+ String completionTime = "";
+ for (int i = 0; i < mThreadNum; i++) {
+ if (maxTime < mElapseTime[i])
+ maxTime = mElapseTime[i];
+ Log.i(mTag, "Thread-" + i + " completion time: "
+ + String.valueOf((mElapseTime[i])) + "ms");
+ completionTime += "Thread-" + i + " completion time: "
+ + String.valueOf((mElapseTime[i])) + "ms\n";
+ }
+ String totalTime = "AndroidGCTest is done by " + mThreadNum
+ + " threads. Completion time is " + maxTime + "ms";
+ Log.i(mTag, totalTime);
+ completionTime += totalTime + "\n";
+ String gcDesc = "Total GC count: " + mTotalGcCount;
+ gcDesc += "\nTotal GC time: " + mTotalGcTime + "ms";
+ gcDesc += "\nTotal Blocking GC count: " + mTotalBlockingGcCount;
+ gcDesc += "\nTotal Blocking GC time: " + mTotalBlockingGcTime + "ms";
+ Log.i(mTag, "Total GC count: " + mTotalGcCount);
+ Log.i(mTag, "Total GC time: " + mTotalGcTime + "ms");
+ Log.i(mTag, "Total Blocking GC count: " + mTotalBlockingGcCount);
+ Log.i(mTag, "Total Blocking GC time: " + mTotalBlockingGcTime + "ms");
+ String pauseDesc = "";
+ String[] causes;
+ if (isArt)
+ causes = GC_CAUSE_ART;
+ else
+ causes = GC_CAUSE_DALVIK;
+ for (int i = 0; i < causes.length; i++) {
+ Log.i(mTag, mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat");
+ gcDesc += "\n" + mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat";
+ }
+ for (int i = 0; i < mGcPauseTime.length; i++) {
+ String gc_time = "GC-" + i + ": " + mGcCause[i] + ", pause "
+ + mGcPauseTime[i] + "ms, total " + mGcTotalTime[i] + "ms";
+ pauseDesc += "\n" + gc_time;
+ Log.i(mTag, gc_time);
+ }
+ try {
+ if (fileOutput != null) {
+ fileOutput.append("\n" + "Device config:\n\t" + deviceDesc);
+ fileOutput.append("\n" + completionTime);
+ fileOutput.append("\n" + "Heap status after each iteration "
+ + "(footprint, bytes allocated):\n");
+ for (int j = 0; j < mIterNum; j++)
+ fileOutput.append("\t" + mHeapFootprint[j] + " kB, "
+ + mHeapBytesAllocated[j] + " kB\n");
+ fileOutput.append(gcDesc);
+ fileOutput.append(pauseDesc);
+ fileOutput.flush();
+ fileOutput.close();
+ }
+ } catch (IOException e) {
+ Log.i(mTag, "Cannot write to /sdcard/AndroidGCTest-result.txt"
+ + e.getMessage());
+ }
+ if (mActivity != null) {
+ Message m = mActivity.getHandler().obtainMessage(
+ MainActivity.BenchmarkDone);
+ Bundle b = new Bundle();
+ b.putBoolean(ResultActivity.KEY_VM_TYPE, isArt);
+ b.putString("device", deviceDesc);
+ b.putLongArray(ResultActivity.KEY_THREAD_COMPLETE_TIME, mElapseTime);
+ b.putLong(ResultActivity.KEY_WORKLOAD_COMPLETE_TIME, maxTime);
+ b.putLongArray(ResultActivity.KEY_BYTES_LIVING, mHeapBytesAllocated);
+ b.putIntArray(ResultActivity.KEY_HEAP_FOOTPRINT, mHeapFootprint);
+ b.putFloatArray(ResultActivity.KEY_GC_PAUSE_TIME, mGcPauseTime);
+ b.putFloatArray(ResultActivity.KEY_GC_COMPLETION_TIME, mGcTotalTime);
+ b.putStringArray(ResultActivity.KEY_GC_CAUSE, mGcCause);
+ m.setData(b);
+ mActivity.getHandler().sendMessage(m);
+ }
+ }
+ mElapseTime = null;
+ mHeapFootprint = null;
+ mHeapBytesAllocated = null;
+ mGcPauseTime = null;
+ mGcTotalTime = null;
+ mGcCause = null;
+
+ clearInitData();
+ }
+
+ public void stop() {
+ }
+
+ private void clearLogcat() {
+ try {
+ Process process = Runtime.getRuntime().exec("logcat -c");
+ try {
+ process.waitFor();
+ } catch (InterruptedException e) {
+ Log.e(mTag, "Clear logcat fails, interrupted by " + e.getLocalizedMessage());
+ }
+ Log.i(mTag, "Clear logcat before workload running");
+ } catch (Exception e) {
+ Log.e(mTag, "Clear logcat fails, " + e.getLocalizedMessage());
+ }
+ }
+
+ private void readLogcat() {
+ String cmd;
+ if (isArt)
+ cmd = "logcat -s art";
+ else
+ cmd = "logcat -s dalvikvm";
+ ArrayList<Float> gcPauseTimeList = new ArrayList<Float>();
+ ArrayList<Float> gcTotalTimeList = new ArrayList<Float>();
+ ArrayList<String> gcCauseList = new ArrayList<String>();
+ int loggerGcCount = 0;
+ try {
+ Process process = Runtime.getRuntime().exec(cmd);
+ InputStream inStream = process.getInputStream();
+ InputStream errorStream = process.getErrorStream();
+ int error = errorStream.available();
+ if (error > 0) {
+ byte[] errorMsg = new byte[error];
+ errorStream.read(errorMsg);
+ Log.i(mTag, "executing logcat return error message: " + new String(errorMsg));
+ }
+ BufferedReader inReader = new BufferedReader(new InputStreamReader(inStream));
+ String line;
+ while (!mWorkloadComplete && (line = inReader.readLine()) != null) {
+ if (mWorkloadComplete)
+ break;
+
+ int idx = line.indexOf(": ");
+ if (idx == -1)
+ continue;
+ line = line.substring(idx+2);
+ boolean isGCLog = false;
+ String gcCause = "";
+ if (isArt) {
+ for (int i = 0; i < GC_CAUSE_ART.length; i++) {
+ if ((line.contains("mark sweep") || line.contains("marksweep")
+ || line.contains("mark compact"))
+ && line.startsWith(GC_CAUSE_ART[i])) {
+ isGCLog = true;
+ mGcCauseCount[i]++;
+ idx = line.indexOf(" GC ");
+ if (idx > 0)
+ gcCause = line.substring(0, idx);
+ else {
+ Log.i(mTag, "Error: cannot find ' GC ' from this log, " + line);
+ continue;
+ }
+ break;
+ }
+ }
+ } else {
+ for (int i = 0; i < GC_CAUSE_DALVIK.length; i++) {
+ if (line.startsWith(GC_CAUSE_DALVIK[i])) {
+ isGCLog = true;
+ mGcCauseCount[i]++;
+ gcCause = GC_CAUSE_DALVIK[i];
+ break;
+ }
+ }
+ }
+ if (!isGCLog)
+ continue;
+ loggerGcCount++;
+
+ int idx0 = line.indexOf("paused ");
+ int idx1 = line.indexOf(" total ");
+ if (idx0 == -1 || idx1 == -1) {
+ Log.i(mTag, "Cannot find pause or total completion time from the GC log "
+ + line);
+ continue;
+ }
+
+ String pauseTimeStr = line.substring(idx0+7, idx1);
+ String totalTimeStr = line.substring(idx1+7);
+ float completeTime = 0.0f;
+ float pauseTime = 0.0f;
+ idx = totalTimeStr.indexOf("ms");
+ int timeToSec = 1000;
+ if (idx == -1) {
+ idx = totalTimeStr.indexOf("us");
+ timeToSec = 1000000;
+ }
+ if (idx == -1) {
+ idx = totalTimeStr.indexOf("s");
+ timeToSec = 1;
+ }
+ if (idx == -1) {
+ Log.i(mTag, "Cannot identify total complete time format, " + line);
+ continue;
+ }
+ completeTime = Float.parseFloat(totalTimeStr.substring(0, idx)) * 1000 / timeToSec;
+ String[] pauseTimes = pauseTimeStr.split("\\+\\s*|,\\s*");
+ for (int i = 0; i < pauseTimes.length; i++) {
+ String tmp = pauseTimes[i];
+ idx = tmp.indexOf("ms");
+ if (idx > 0) {
+ pauseTime += Float.parseFloat(tmp.substring(0, idx));
+ } else {
+ idx = tmp.indexOf("us");
+ if (idx > 0) {
+ pauseTime += Float.parseFloat(tmp.substring(0, idx))/1000;
+ } else {
+ Log.i(mTag, "Cannot identify pause time format, " + line);
+ continue;
+ }
+ }
+ }
+ gcPauseTimeList.add(pauseTime);
+ gcTotalTimeList.add(completeTime);
+ gcCauseList.add(gcCause);
+ }
+ errorStream.close();
+ inReader.close();
+ process.destroy();
+ Log.i(mTag, "workload complete, stop reading logcat");
+ mGcTotalTime = new float[loggerGcCount];
+ mGcPauseTime = new float[loggerGcCount];
+ mGcCause = new String[loggerGcCount];
+ for (int i = 0; i < gcPauseTimeList.size(); i++) {
+ mGcTotalTime[i] = gcTotalTimeList.get(i).floatValue();
+ mGcPauseTime[i] = gcPauseTimeList.get(i).floatValue();
+ mGcCause[i] = gcCauseList.get(i);
+ }
+ } catch (OutOfMemoryError e) {
+ mOutOfMemory = true;
+ Log.i(mTag, "logcat thread meets OutOfMemory");
+ Message m = mActivity.getHandler().obtainMessage(
+ MainActivity.BenchmarkOutOfMemoryError);
+ m.arg1 = -1;
+ mActivity.getHandler().sendMessage(m);
+ } catch (Exception e) {
+ Log.i(mTag, "Cannot run logcat " + e.getMessage());
+ }
+ gcPauseTimeList.clear();
+ gcPauseTimeList = null;
+ gcTotalTimeList.clear();
+ gcTotalTimeList = null;
+ gcCauseList.clear();
+ gcCauseList = null;
+ Log.i(mTag, "logcat done");
+ }
+
+ private static Method getRuntimeStatMethod = null;
+ private long getRuntimeStat(String statName) {
+ if (getRuntimeStatMethod == null) {
+ return 0;
+ }
+ String valueStr;
+ try {
+ valueStr = (String) getRuntimeStatMethod.invoke(null, statName);
+ } catch (Exception e) {
+ Log.w(mTag, "Failed to invoke getRuntimeStat");
+ return 0;
+ }
+ if (valueStr != null)
+ return Long.parseLong(valueStr);
+ return 0;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.gctest;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.Spinner;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.TextView;
+
+public class MainActivity extends Activity {
+ private final String mTag = "AndroidGCTest";
+ private boolean mRunning;
+
+ private Button mStartButton;
+ private Button mProfileSettingButton;
+ private Spinner mProfileNameList;
+ private SeekBar mSeekBar;
+ private LinearLayout mWorkloadResultLayout;
+ private Button mShowResultButton;
+ private TextView mExeTimeView;
+ private TextView mRuntimeView;
+ private TextView mWorkloadStatus;
+ private Profile mProfile = null;
+ private Bundle mResultData = null;
+
+ // handler to handle BenchmarkDone message
+ final static int BenchmarkDone = 100;
+ final static int BenchmarkProgress = 101;
+ final static int BenchmarkOutOfMemoryError = 102;
+ private class MyHandler extends Handler {
+ public void handleMessage(Message m) {
+ switch(m.what) {
+ case BenchmarkDone:
+ if (mRunning) {
+ mRunning = false;
+ mStartButton.setVisibility(View.VISIBLE);
+ mProfileSettingButton.setVisibility(View.VISIBLE);
+ mWorkloadStatus.setText(R.string.workload_status_desc);
+ mResultData = m.getData();
+ String device = mResultData.getString("device");
+ long execution_time = mResultData.getLong(ResultActivity.KEY_WORKLOAD_COMPLETE_TIME);
+ mRuntimeView.setText(device);
+ mExeTimeView.setText(String.valueOf(execution_time));
+ mWorkloadResultLayout.setVisibility(View.VISIBLE);
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ }
+ break;
+ case BenchmarkProgress:
+ if (mRunning && mSeekBar != null) {
+ int progress = m.arg1;
+ if (progress < mSeekBar.getMax())
+ mSeekBar.setProgress(progress);
+ }
+ break;
+ case BenchmarkOutOfMemoryError:
+ if (mRunning) {
+ mWorkloadStatus.setText(R.string.outofmemory_desc);
+ mRunning = false;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ private MyHandler mBenchmarkHandler = null;
+ public Handler getHandler() {
+ return mBenchmarkHandler;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ Log.i(mTag, "MainActivity onCreate");
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ mBenchmarkHandler = new MyHandler();
+
+ mWorkloadResultLayout = (LinearLayout)findViewById(R.id.workload_result_layout);
+ mSeekBar = (SeekBar)findViewById(R.id.seek_bar);
+ mSeekBar.setVisibility(View.INVISIBLE);
+ mWorkloadResultLayout.setVisibility(View.INVISIBLE);
+ mStartButton = (Button)findViewById(R.id.button_start);
+ mStartButton.setOnClickListener(startWorkload);
+ mWorkloadStatus = (TextView)findViewById(R.id.workload_status);
+
+ mProfileSettingButton = (Button)findViewById(R.id.button_set);
+ mProfileSettingButton.setOnClickListener(settingProfile);
+ mRuntimeView = (TextView)findViewById(R.id.runtime_info);
+ mExeTimeView = (TextView)findViewById(R.id.execution_time);
+ mShowResultButton = (Button)findViewById(R.id.button_result);
+ mShowResultButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ if (mResultData != null) {
+ Intent intent = new Intent(getApplicationContext(), ResultActivity.class);
+ Bundle b = new Bundle(mResultData);
+ intent.putExtra("result_data", b);
+ startActivity(intent);
+ } else
+ Log.e(mTag, "no result to show now");
+ }
+ });
+
+ mProfileNameList = (Spinner)findViewById(R.id.profile_list_view);
+ mProfile = Profile.getInstance();
+ Bundle b = getIntent().getExtras();
+ if (b != null && b.containsKey("profile_file")) {
+ FileInputStream profileFile;
+ try {
+ profileFile = new FileInputStream(b.getString("profile_file"));
+ mProfile.parseProfileData(profileFile);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ Log.i(mTag, "Cannot load profile. " + e.getMessage());
+ }
+ } else {
+ mProfile.parseProfileData(getResources().openRawResource(R.raw.profile));
+ }
+
+ if (mProfile.initialized()) {
+ String[] names = new String[mProfile.mData.size()];
+ for (int i = 0; i < mProfile.mData.size(); i++) {
+ Profile.ProfileData d = mProfile.mData.get(i);
+ names[i] = d.getName();
+ }
+ ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
+ android.R.layout.simple_spinner_item, names);
+ adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ mProfileNameList.setAdapter(adapter);
+ mProfileNameList.setOnItemSelectedListener(new OnItemSelectedListener() {
+
+ @Override
+ public void onItemSelected(AdapterView<?> arg0, View arg1,
+ int arg2, long arg3) {
+ String name = (String)(arg0.getAdapter().getItem(arg2));
+ mProfile.setCurrentProfileData(name);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> arg0) {
+ // TODO Auto-generated method stub
+ }
+
+ });
+ mProfileNameList.setVisibility(View.VISIBLE);
+ if (b != null && b.containsKey("profile_name")) {
+ int pos = adapter.getPosition(b.getString("profile_name"));
+ mProfileNameList.setSelection(pos);
+ }
+ } else {
+ mProfileNameList.setVisibility(View.INVISIBLE);
+ Log.i(mTag, "Cannot get profile data");
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_HOME) {
+ android.os.Process.killProcess(android.os.Process.myPid());
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+
+ @Override
+ protected void onResume() {
+ if (mRunning) {
+ if (mStartButton != null)
+ mStartButton.setVisibility(View.INVISIBLE);
+ }
+ super.onResume();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.main, menu);
+ return true;
+ }
+
+ private View.OnClickListener startWorkload = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ Log.i(mTag, "Start Benchmark");
+ Profile.ProfileData profileData = mProfile.getCurrentProfileData();
+ if (profileData == null) {
+ Log.e(mTag, "no profile data?!");
+ return;
+ }
+ final AndroidGCTestMain benchMain = new AndroidGCTestMain((MainActivity)(v.getContext()),
+ profileData.getTotalSize(), profileData.getBucketSize(),
+ profileData.getLosThreshold(), profileData.getSizeDistribution(),
+ profileData.getLifetime(), profileData.getLosElementDist(),
+ profileData.getThreadMode(), profileData.getThreadNum(),
+ profileData.getIterationNum());
+
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+
+ mResultData = null;
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+
+ mWorkloadResultLayout.setVisibility(View.INVISIBLE);
+ mProfileSettingButton.setVisibility(View.INVISIBLE);
+ v.setVisibility(View.INVISIBLE);
+ mWorkloadStatus.setText("AndroidGCTest is running");
+ mSeekBar.setVisibility(View.VISIBLE);
+ mSeekBar.setMax(profileData.getIterationNum());
+ mSeekBar.setProgress(0);
+
+ mRunning = true;
+ Thread worker = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ // TODO Auto-generated method stub
+ benchMain.start();
+ }
+
+ });
+ worker.start();
+ }
+ };
+
+ private View.OnClickListener settingProfile = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ Intent intent = new Intent(getApplicationContext(), ProfileSettingActivity.class);
+ startActivity(intent);
+ }
+ };
+}
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.gctest;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import android.util.Log;
+import android.util.Xml;
+
+public class Profile {
+ private final String mTag = "AndroidGCTest";
+ public class ProfileData {
+ private int mId;
+ private String mName;
+ private int mTotalSize;
+ private int mBucketSize;
+ private int mLosThreshold;
+ private float[] mSizeDist;
+ private float[] mLosElementDist;
+ private float[][] mLifetime;
+ private boolean mThreadMode;
+ private int mThreadNum;
+ private int mIterationNum;
+
+ public ProfileData(int id, String name) {
+ mId = id;
+ mName = name;
+ }
+ public String getName() { return mName; }
+ public int getTotalSize() { return mTotalSize; }
+ public int getBucketSize() { return mBucketSize; }
+ public int getLosThreshold() { return mLosThreshold; }
+ public float[] getSizeDistribution() { return mSizeDist; }
+ public float[] getLosElementDist() { return mLosElementDist; }
+ public float[][] getLifetime() { return mLifetime; }
+ public boolean getThreadMode() { return mThreadMode; }
+ public int getThreadNum() { return mThreadMode? 1 : mThreadNum; }
+ public int getIterationNum() { return mIterationNum; }
+
+ public void setName(String name) { mName = name; }
+ public void setTotalSize(int total_size) { mTotalSize = total_size; }
+ public void setBucketSize(int bucket_size) { mBucketSize = bucket_size; }
+ public void setLosThreshold(int los_threshold) { mLosThreshold = los_threshold; }
+ public void setSizeDistribution(float[] size_dist) { mSizeDist = size_dist; }
+ public void setLosElementDist(float[] los_element_dist) {
+ mLosElementDist = los_element_dist;
+ }
+ public void setLifetime(float[][] lifetime) { mLifetime = lifetime; }
+ public void setThreadMode(boolean singleThread) { mThreadMode = singleThread; }
+ public void setThreadNum(int thread_num) {
+ mThreadNum = mThreadMode? 1 : thread_num;
+ }
+ public void setIterationNum(int iteration_num) { mIterationNum = iteration_num; }
+ }
+
+ public boolean mInit = false;
+ int mCurrentProfileId;
+ public ArrayList<ProfileData> mData = null;
+
+ private static Profile instance_;
+ private Profile() {
+ mCurrentProfileId = -1;
+ mInit = false;
+ }
+ public static Profile getInstance() {
+ if (instance_ == null)
+ instance_ = new Profile();
+ return instance_;
+ }
+
+ private boolean initProfileData(InputStream input) {
+ ProfileData newProfile = null;
+ XmlPullParser parser=Xml.newPullParser();
+ try {
+ parser.setInput(new InputStreamReader(input));
+ int eventType = parser.getEventType();
+ float[] floatValues = null;
+ String itemName, name;
+ int idx0 = -1, idx1 = 0;
+ while (eventType != XmlPullParser.END_DOCUMENT) {
+ switch(eventType) {
+ case XmlPullParser.START_DOCUMENT:
+ mData = new ArrayList<ProfileData>();
+ break;
+ case XmlPullParser.START_TAG:
+ name = parser.getName();
+ if (name.matches("profile")) {
+ newProfile = new ProfileData(
+ Integer.parseInt(parser.getAttributeValue(0)),
+ parser.getAttributeValue(1));
+ } else if (name.matches("item")) {
+ itemName = parser.getAttributeValue(0);
+ if (itemName.matches("total_size")) {
+ newProfile.mTotalSize = Integer.parseInt(parser.nextText());
+ } else if (itemName.matches("bucket_size")) {
+ newProfile.mBucketSize = Integer.parseInt(parser.nextText());
+ } else if (itemName.matches("los_threshold")) {
+ newProfile.mLosThreshold = Integer.parseInt(parser.nextText());
+ } else if (itemName.matches("thread-mode")) {
+ newProfile.mThreadMode = Integer.parseInt(parser.nextText()) == 1;
+ } else if (itemName.matches("thread-num")) {
+ newProfile.mThreadNum = Integer.parseInt(parser.nextText());
+ } else if (itemName.matches("iteration-times")) {
+ newProfile.mIterationNum = Integer.parseInt(parser.nextText());
+ }
+ } else if (name.matches("float-array-2d")) {
+ if ("lifetime".equals(parser.getAttributeValue(0))) {
+ newProfile.mLifetime = new float[Integer.parseInt(
+ parser.getAttributeValue(1))][];
+ idx0 = 0;
+ }
+ } else if(name.matches("float-array")) {
+ itemName = parser.getAttributeValue(0);
+ if (itemName.matches("size_dist")) {
+ newProfile.mSizeDist = new float[Integer.parseInt(
+ parser.getAttributeValue(1))];
+ floatValues = newProfile.mSizeDist;
+ } else if (itemName.matches("los_element_dist")) {
+ newProfile.mLosElementDist = new float[Integer.parseInt(
+ parser.getAttributeValue(1))];
+ floatValues = newProfile.mLosElementDist;
+ } else if (idx0 >= 0) {
+ newProfile.mLifetime[idx0] = new float[Integer.parseInt(
+ parser.getAttributeValue(1))];
+ floatValues = newProfile.mLifetime[idx0];
+ idx0++;
+ }
+ idx1 = 0;
+ } else if(name.matches("value")) {
+ if (floatValues == null) {
+ Log.i(mTag, "error in parsing profile.xml");
+ return false;
+ }
+ floatValues[idx1++] = Float.parseFloat(parser.nextText());
+ }
+ break;
+ case XmlPullParser.END_TAG:
+ name = parser.getName();
+ if ("profile".equals(name))
+ mData.add(newProfile);
+ else if ("float-array-2d".equals(name))
+ idx0 = -1;
+ break;
+ default:
+ break;
+ }
+ eventType = parser.next();
+ }
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ return false;
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ return false;
+ } catch (IOException e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ public ProfileData getProfile(String name) {
+ if (!mInit)
+ return null;
+ for (int i = 0; i < mData.size(); i++) {
+ ProfileData data = mData.get(i);
+ if (data.mName.matches(name)) {
+ mCurrentProfileId = data.mId;
+ return data;
+ }
+ }
+ return null;
+ }
+
+ public boolean parseProfileData(InputStream rawProfileFile) {
+ mInit = initProfileData(rawProfileFile);
+ return mInit;
+ }
+
+ public boolean initialized() {
+ return mInit;
+ }
+
+ public void setCurrentProfileData(String name) {
+ if (!mInit)
+ return;
+ for (int i = 0; i < mData.size(); i++) {
+ ProfileData data = mData.get(i);
+ if (data.mName.matches(name)) {
+ mCurrentProfileId = data.mId;
+ break;
+ }
+ }
+ }
+
+ public ProfileData getCurrentProfileData() {
+ if (!mInit)
+ return null;
+ for (int i = 0; i < mData.size(); i++)
+ if (mData.get(i).mId == mCurrentProfileId)
+ return mData.get(i);
+ return null;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.gctest;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+
+public class ProfileSettingActivity extends Activity {
+ private final String mTag = "AndroidGCTest";
+ private Button mConfirmButton = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_profile_config);
+ mConfirmButton = (Button)findViewById(R.id.button_confirm);
+ mConfirmButton.setOnClickListener(settingProfile);
+ Profile profile = Profile.getInstance();
+ showProfileData(profile.getCurrentProfileData());
+ }
+ private View.OnClickListener settingProfile = new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ int heapSize, bucketSize, largeObjectSize;
+ float[] sizeDist = null;
+ float[][] lifetimeDist = null;
+ float[] largeSizeDist = null;
+ boolean singleThread = false;
+ int thread_num = 0, exe_time = 1;
+ heapSize = Integer.parseInt(((EditText)findViewById(
+ R.id.total_size_v)).getText().toString());
+ bucketSize = Integer.parseInt(((EditText)findViewById(
+ R.id.bucket_size_v)).getText().toString());
+ largeObjectSize = Integer.parseInt(((EditText)findViewById(
+ R.id.los_threshold_v)).getText().toString());
+ exe_time = Integer.parseInt(((EditText)findViewById(
+ R.id.exe_time_v)).getText().toString());
+ thread_num = Integer.parseInt(((EditText)findViewById(
+ R.id.thread_num)).getText().toString());
+
+ sizeDist = new float[AndroidGCTestMain.OBJECT_SIZE_TYPE];
+ sizeDist[0] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_16_v)).getText().toString());
+ sizeDist[1] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_32_v)).getText().toString());
+ sizeDist[2] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_64_v)).getText().toString());
+ sizeDist[3] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_128_v)).getText().toString());
+ sizeDist[4] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_256_v)).getText().toString());
+ sizeDist[5] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_512_v)).getText().toString());
+ sizeDist[6] = Float.parseFloat(((EditText)findViewById(
+ R.id.size_dist_los_v)).getText().toString());
+
+ String[][] lifetimeStr = new String[AndroidGCTestMain.OBJECT_SIZE_TYPE][];
+ lifetimeDist = new float[AndroidGCTestMain.OBJECT_SIZE_TYPE][];
+ lifetimeStr[AndroidGCTestMain.OBJECT_16_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_16_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ lifetimeStr[AndroidGCTestMain.OBJECT_32_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_32_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ lifetimeStr[AndroidGCTestMain.OBJECT_64_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_64_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ lifetimeStr[AndroidGCTestMain.OBJECT_128_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_128_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ lifetimeStr[AndroidGCTestMain.OBJECT_256_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_256_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ lifetimeStr[AndroidGCTestMain.OBJECT_512_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_512_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ lifetimeStr[AndroidGCTestMain.OBJECT_LARGE_BYTE] = ((EditText)findViewById(
+ R.id.lifetime_los_v))
+ .getText().toString().replaceAll(", ", ",").split(",");
+ for (int i = 0; i < AndroidGCTestMain.OBJECT_SIZE_TYPE; i++) {
+ int len = lifetimeStr[i].length;
+ lifetimeDist[i] = new float[len];
+ for (int j = 0; j < len; j++) {
+ lifetimeDist[i][j] = Float.parseFloat(lifetimeStr[i][j]);
+ }
+ }
+
+ largeSizeDist = new float[4];
+ largeSizeDist[0] = Float.parseFloat(((EditText)findViewById(
+ R.id.los_dist_byte_v))
+ .getText().toString());
+ largeSizeDist[1] = Float.parseFloat(((EditText)findViewById(
+ R.id.los_dist_char_v))
+ .getText().toString());
+ largeSizeDist[2] = Float.parseFloat(((EditText)findViewById(
+ R.id.los_dist_int_v))
+ .getText().toString());
+ largeSizeDist[3] = Float.parseFloat(((EditText)findViewById(
+ R.id.los_dist_long_v))
+ .getText().toString());
+
+ singleThread = ((CheckBox)findViewById(R.id.single_thread)).isChecked();
+ Profile profile = Profile.getInstance();
+ Profile.ProfileData profileData = profile.getCurrentProfileData();
+ profileData.setTotalSize(heapSize);
+ profileData.setBucketSize(bucketSize);
+ profileData.setLosThreshold(largeObjectSize);
+ profileData.setSizeDistribution(sizeDist);
+ profileData.setLifetime(lifetimeDist);
+ profileData.setLosElementDist(largeSizeDist);
+ profileData.setThreadMode(singleThread);
+ profileData.setThreadNum(thread_num);
+ profileData.setIterationNum(exe_time);
+ Intent intent = new Intent(getApplicationContext(), MainActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
+ startActivity(intent);
+ }
+ };
+
+ private void showProfileData(Profile.ProfileData data) {
+ ((EditText)findViewById(R.id.total_size_v))
+ .setText(String.valueOf(data.getTotalSize()));
+ ((EditText)findViewById(R.id.bucket_size_v))
+ .setText(String.valueOf(data.getBucketSize()));
+ ((EditText)findViewById(R.id.los_threshold_v))
+ .setText(String.valueOf(data.getLosThreshold()));
+
+ int i = 0;
+ float[] size_dist = data.getSizeDistribution();
+ ((EditText)findViewById(R.id.size_dist_16_v)).setText(String.valueOf(size_dist[i++]));
+ ((EditText)findViewById(R.id.size_dist_32_v)).setText(String.valueOf(size_dist[i++]));
+ ((EditText)findViewById(R.id.size_dist_64_v)).setText(String.valueOf(size_dist[i++]));
+ ((EditText)findViewById(R.id.size_dist_128_v)).setText(String.valueOf(size_dist[i++]));
+ ((EditText)findViewById(R.id.size_dist_256_v)).setText(String.valueOf(size_dist[i++]));
+ ((EditText)findViewById(R.id.size_dist_512_v)).setText(String.valueOf(size_dist[i++]));
+ ((EditText)findViewById(R.id.size_dist_los_v)).setText(String.valueOf(size_dist[i++]));
+
+ i = 0;
+ float[] los_element_dist = data.getLosElementDist();
+ ((EditText)findViewById(R.id.los_dist_byte_v))
+ .setText(String.valueOf(los_element_dist[i++]));
+ ((EditText)findViewById(R.id.los_dist_char_v))
+ .setText(String.valueOf(los_element_dist[i++]));
+ ((EditText)findViewById(R.id.los_dist_int_v))
+ .setText(String.valueOf(los_element_dist[i++]));
+ ((EditText)findViewById(R.id.los_dist_long_v))
+ .setText(String.valueOf(los_element_dist[i++]));
+
+ String[] t = new String[]{"", "", "", "", "", "", ""};
+ float[][] lifetime = data.getLifetime();
+ for (i = 0; i < AndroidGCTestMain.OBJECT_SIZE_TYPE; i++) {
+ for (int j = 0; j < lifetime[i].length; j++) {
+ if (j != 0)
+ t[i] += ",";
+ t[i] += String.valueOf(lifetime[i][j]);
+ }
+ }
+ i = 0;
+ ((EditText)findViewById(R.id.lifetime_16_v)).setText(t[i++]);
+ ((EditText)findViewById(R.id.lifetime_32_v)).setText(t[i++]);
+ ((EditText)findViewById(R.id.lifetime_64_v)).setText(t[i++]);
+ ((EditText)findViewById(R.id.lifetime_128_v)).setText(t[i++]);
+ ((EditText)findViewById(R.id.lifetime_256_v)).setText(t[i++]);
+ ((EditText)findViewById(R.id.lifetime_512_v)).setText(t[i++]);
+ ((EditText)findViewById(R.id.lifetime_los_v)).setText(t[i++]);
+
+ ((CheckBox)findViewById(R.id.single_thread)).setChecked(data.getThreadMode());
+
+ EditText thread_num_view = (EditText)findViewById(R.id.thread_num);
+ thread_num_view.setText(String.valueOf(data.getThreadNum()));
+ ((EditText)findViewById(R.id.exe_time_v))
+ .setText(String.valueOf(data.getIterationNum()));
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.gctest;
+
+import org.achartengine.ChartFactory;
+import org.achartengine.GraphicalView;
+import org.achartengine.chart.PointStyle;
+import org.achartengine.model.XYMultipleSeriesDataset;
+import org.achartengine.model.XYSeries;
+import org.achartengine.renderer.XYMultipleSeriesRenderer;
+import org.achartengine.renderer.XYSeriesRenderer;
+
+import android.util.Log;
+import android.app.Activity;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.view.KeyEvent;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.LinearLayout.LayoutParams;
+
+public class ResultActivity extends Activity {
+ private final String mTag = "AndroidGCTest";
+ private long[] mThreadExeTime = null;
+ private long mWorkloadExeTime = 0;
+ private int[] mHeapFootprint = null;
+ private long[] mHeapBytesAllocated = null;
+ private float[] mGcPauseTime = null;
+ private float[] mGcTotalTime = null;
+ private String[] mGcCause = null;
+ private boolean mVmType; // true for ART, false for Dalvik
+
+ public static final String KEY_WORKLOAD_COMPLETE_TIME = "workload_completion_time";
+ public static final String KEY_THREAD_COMPLETE_TIME = "thread_completion_time";
+ public static final String KEY_VM_TYPE = "vm_type";
+ public static final String KEY_HEAP_FOOTPRINT = "heap_footprint";
+ public static final String KEY_BYTES_LIVING = "bytes_living";
+ public static final String KEY_GC_PAUSE_TIME = "gc_pause_time";
+ public static final String KEY_GC_COMPLETION_TIME = "gc_completion_time";
+ public static final String KEY_GC_CAUSE = "gc_cause";
+
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_result);
+
+ Bundle b = getIntent().getBundleExtra("result_data");
+ if (b == null) {
+ Log.i(mTag, "no result_data bundle!");
+ }
+
+ if (b.containsKey(KEY_VM_TYPE)) {
+ mVmType = b.getBoolean(KEY_VM_TYPE);
+ } else {
+ Log.i(mTag, "no " + KEY_VM_TYPE);
+ }
+
+ if (b.containsKey(KEY_WORKLOAD_COMPLETE_TIME)) {
+ mWorkloadExeTime = b.getLong(KEY_WORKLOAD_COMPLETE_TIME);
+ if (mWorkloadExeTime == 0) {
+ Log.i(mTag, "cannot read " + KEY_WORKLOAD_COMPLETE_TIME);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_WORKLOAD_COMPLETE_TIME);
+ }
+
+ if (b.containsKey(KEY_THREAD_COMPLETE_TIME)) {
+ mThreadExeTime = b.getLongArray(KEY_THREAD_COMPLETE_TIME);
+ if (mThreadExeTime == null) {
+ Log.i(mTag, "cannot read " + KEY_THREAD_COMPLETE_TIME);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_THREAD_COMPLETE_TIME);
+ }
+
+ if (b.containsKey(KEY_HEAP_FOOTPRINT)) {
+ mHeapFootprint = b.getIntArray(KEY_HEAP_FOOTPRINT);
+ if (mHeapFootprint == null) {
+ Log.i(mTag, "cannot read " + KEY_HEAP_FOOTPRINT);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_HEAP_FOOTPRINT);
+ }
+
+ if (b.containsKey(KEY_BYTES_LIVING)) {
+ mHeapBytesAllocated = b.getLongArray(KEY_BYTES_LIVING);
+ if (mHeapBytesAllocated == null) {
+ Log.i(mTag, "cannot read " + KEY_BYTES_LIVING);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_BYTES_LIVING);
+ }
+
+ if (b.containsKey(KEY_GC_PAUSE_TIME)) {
+ mGcPauseTime = b.getFloatArray(KEY_GC_PAUSE_TIME);
+ if (mGcPauseTime == null) {
+ Log.i(mTag, "cannot read " + KEY_GC_PAUSE_TIME);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_GC_PAUSE_TIME);
+ }
+
+ if (b.containsKey(KEY_GC_COMPLETION_TIME)) {
+ mGcTotalTime = b.getFloatArray(KEY_GC_COMPLETION_TIME);
+ if (mGcTotalTime == null) {
+ Log.i(mTag, "cannot read " + KEY_GC_COMPLETION_TIME);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_GC_COMPLETION_TIME);
+ }
+
+ if (b.containsKey(KEY_GC_CAUSE)) {
+ mGcCause = b.getStringArray(KEY_GC_CAUSE);
+ if (mGcCause == null) {
+ Log.i(mTag, "cannot read " + KEY_GC_CAUSE);
+ }
+ } else {
+ Log.i(mTag, "no " + KEY_GC_CAUSE);
+ }
+
+ TextView vm_type = (TextView)findViewById(R.id.vm_type);
+ vm_type.setText("Current runtime engine is " + (mVmType? "ART" : "Dalvik")
+ + ", workload completes in " + mWorkloadExeTime + " ms");
+ Button exeTimeButton = (Button)findViewById(R.id.button_exe_time);
+ exeTimeButton.setClickable(true);
+ exeTimeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ mCurrentDataset.clear();
+ mCurrentRenderer.removeAllRenderers();
+ buildExeTimeInfoChart();
+ mChartView.repaint();
+ }
+ });
+
+ Button heapButton = (Button)findViewById(R.id.button_heap);
+ heapButton.setClickable(true);
+ heapButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ mCurrentDataset.clear();
+ mCurrentRenderer.removeAllRenderers();
+ buildHeapInfoChart();
+ mChartView.repaint();
+ }
+ });
+
+ Button gcButton = (Button)findViewById(R.id.button_gc);
+ gcButton.setClickable(true);
+ gcButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ // TODO Auto-generated method stub
+ mCurrentDataset.clear();
+ mCurrentRenderer.removeAllRenderers();
+ buildGcInfoChart();
+ mChartView.repaint();
+ }
+ });
+ mCurrentRenderer.setApplyBackgroundColor(true);
+ mCurrentRenderer.setBackgroundColor(Color.argb(100, 50, 50, 50));
+ mCurrentRenderer.setAxisTitleTextSize(16);
+ mCurrentRenderer.setChartTitleTextSize(20);
+ mCurrentRenderer.setLabelsTextSize(15);
+ mCurrentRenderer.setLegendTextSize(15);
+ mCurrentRenderer.setMargins(new int[] { 20, 30, 15, 0 });
+ mCurrentRenderer.setZoomButtonsVisible(true);
+ mCurrentRenderer.setPointSize(5);
+ }
+ private XYMultipleSeriesDataset mCurrentDataset = new XYMultipleSeriesDataset();
+ private XYMultipleSeriesRenderer mCurrentRenderer = new XYMultipleSeriesRenderer();
+
+ private GraphicalView mChartView;
+ private void buildExeTimeInfoChart() {
+ Log.i(mTag, "buildExeTimeInfoChart");
+ // workload execution time
+ XYSeries series = new XYSeries("Workload Execution Time");
+ for (int i = 0; i < mThreadExeTime.length; i++) {
+ series.add(i, mThreadExeTime[i]);
+ }
+ mCurrentDataset.addSeries(series);
+ XYSeriesRenderer renderer = new XYSeriesRenderer();
+ // set some renderer properties
+ renderer.setPointStyle(PointStyle.CIRCLE);
+ renderer.setFillPoints(true);
+ renderer.setDisplayChartValues(true);
+ renderer.setDisplayChartValuesDistance(10);
+ renderer.setLineWidth(2.0f);
+ mCurrentRenderer.addSeriesRenderer(renderer);
+ mCurrentRenderer.setChartTitle("Workload Execution Time (ms)");
+ mCurrentRenderer.setYAxisMin(0);
+ mCurrentRenderer.setYAxisMax(mWorkloadExeTime*1.05);
+ mCurrentRenderer.setXAxisMin(0);
+ mCurrentRenderer.setXAxisMax(mThreadExeTime.length);
+ }
+
+ private void buildHeapInfoChart() {
+ Log.i(mTag, "buildHeapInfoChart");
+ // Heap footprint and bytes_allocated
+ double max = 0d;
+ XYSeries series2 = new XYSeries("Heap Footprint");
+ XYSeries series3 = new XYSeries("Bytes Allocated");
+ for (int i = 0; i < mHeapFootprint.length; i++) {
+ series2.add(i, mHeapFootprint[i]);
+ series3.add(i, mHeapBytesAllocated[i]);
+ if (max < mHeapFootprint[i])
+ max = mHeapFootprint[i];
+ if (max < mHeapBytesAllocated[i])
+ max = mHeapBytesAllocated[i];
+ }
+ mCurrentDataset.addSeries(series2);
+ mCurrentDataset.addSeries(series3);
+ XYSeriesRenderer renderer = new XYSeriesRenderer();
+ // set some renderer properties
+ renderer.setPointStyle(PointStyle.CIRCLE);
+ renderer.setFillPoints(true);
+ renderer.setDisplayChartValues(false);
+ renderer.setDisplayChartValuesDistance(10);
+ renderer.setColor(Color.RED);
+ renderer.setLineWidth(1.0f);
+ mCurrentRenderer.addSeriesRenderer(renderer);
+ renderer = new XYSeriesRenderer();
+ // set some renderer properties
+ renderer.setPointStyle(PointStyle.CIRCLE);
+ renderer.setFillPoints(true);
+ renderer.setDisplayChartValues(false);
+ renderer.setDisplayChartValuesDistance(10);
+ renderer.setColor(Color.BLUE);
+ renderer.setLineWidth(1.0f);
+ mCurrentRenderer.addSeriesRenderer(renderer);
+ mCurrentRenderer.setChartTitle("Heap Footprint/Bytes allocated (kB)");
+ mCurrentRenderer.setYAxisMin(0);
+ mCurrentRenderer.setYAxisMax(max*1.05);
+ mCurrentRenderer.setXAxisMin(0);
+ mCurrentRenderer.setXAxisMax(mHeapFootprint.length);
+ }
+
+ private void buildGcInfoChart() {
+ Log.i(mTag, "buildGcInfoChart");
+ // GC status
+ XYSeries series3 = new XYSeries("GC pause time");
+ double max = 0d;
+ for (int i = 0; i < mGcPauseTime.length; i++) {
+ series3.add(i, mGcPauseTime[i]);
+ if (max < mGcPauseTime[i])
+ max = mGcPauseTime[i];
+ }
+ mCurrentDataset.addSeries(series3);
+ XYSeriesRenderer renderer = new XYSeriesRenderer();
+ // set some renderer properties
+ renderer.setPointStyle(PointStyle.CIRCLE);
+ renderer.setFillPoints(true);
+ renderer.setDisplayChartValues(false);
+ renderer.setDisplayChartValuesDistance(10);
+ renderer.setColor(Color.BLUE);
+ renderer.setLineWidth(1.5f);
+ mCurrentRenderer.addSeriesRenderer(renderer);
+ mCurrentRenderer.setChartTitle("Gc Pause Time (ms)");
+ mCurrentRenderer.setYAxisMin(0);
+ mCurrentRenderer.setYAxisMax(max*1.05);
+ mCurrentRenderer.setXAxisMin(0);
+ mCurrentRenderer.setXAxisMax(mGcPauseTime.length);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ if (mChartView == null) {
+ buildExeTimeInfoChart();
+ LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
+ mChartView = ChartFactory.getLineChartView(this,
+ mCurrentDataset, mCurrentRenderer);
+ layout.addView(mChartView, new LayoutParams(LayoutParams.WRAP_CONTENT,
+ LayoutParams.WRAP_CONTENT));
+ } else {
+ mChartView.repaint();
+ }
+ }
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_BACK) {
+ mCurrentDataset = null;
+ mCurrentRenderer = null;
+ mThreadExeTime = null;
+ mWorkloadExeTime = 0;
+ mHeapFootprint = null;
+ mHeapBytesAllocated = null;
+ mGcPauseTime = null;
+ mGcTotalTime = null;
+ mGcCause = null;
+ Runtime.getRuntime().runFinalization();
+ Runtime.getRuntime().gc();
+ }
+ return super.onKeyUp(keyCode, event);
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path
+ android:fillColor="#3DDC84"
+ android:pathData="M0,0h108v108h-108z" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M9,0L9,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,0L19,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,0L29,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,0L39,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,0L49,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,0L59,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,0L69,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,0L79,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M89,0L89,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M99,0L99,108"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,9L108,9"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,19L108,19"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,29L108,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,39L108,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,49L108,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,59L108,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,69L108,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,79L108,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,89L108,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M0,99L108,99"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,29L89,29"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,39L89,39"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,49L89,49"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,59L89,59"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,69L89,69"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M19,79L89,79"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M29,19L29,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M39,19L39,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M49,19L49,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M59,19L59,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M69,19L69,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+ <path
+ android:fillColor="#00000000"
+ android:pathData="M79,19L79,89"
+ android:strokeWidth="0.8"
+ android:strokeColor="#33FFFFFF" />
+</vector>
--- /dev/null
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:aapt="http://schemas.android.com/aapt"
+ android:width="108dp"
+ android:height="108dp"
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+ <path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
+ <aapt:attr name="android:fillColor">
+ <gradient
+ android:endX="85.84757"
+ android:endY="92.4963"
+ android:startX="42.9492"
+ android:startY="49.59793"
+ android:type="linear">
+ <item
+ android:color="#44000000"
+ android:offset="0.0" />
+ <item
+ android:color="#00000000"
+ android:offset="1.0" />
+ </gradient>
+ </aapt:attr>
+ </path>
+ <path
+ android:fillColor="#FFFFFF"
+ android:fillType="nonZero"
+ android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
+ android:strokeWidth="1"
+ android:strokeColor="#00000000" />
+</vector>
\ No newline at end of file
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/activity_main"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context=".MainActivity" >
+
+ <SeekBar
+ android:id="@+id/seek_bar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_centerInParent="true" />
+
+ <LinearLayout
+ android:id="@+id/workload_setting_layout"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:baselineAligned="false"
+ android:orientation="horizontal"
+ android:layout_above="@id/seek_bar" >
+
+ <LinearLayout
+ android:layout_width="200dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:orientation="vertical" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="10dp"
+ android:textSize="18sp"
+ android:text="@string/profile_list_dest" />
+ <Spinner
+ android:id="@+id/profile_list_view"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginLeft="20dp" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:orientation="vertical" >
+ <Button
+ android:id="@+id/button_set"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/set_profile_button_desc" />
+
+ <Button
+ android:id="@+id/button_start"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:text="@string/start_button_desc" />
+
+ <TextView
+ android:id="@+id/workload_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:textSize="20sp"
+ android:text="@string/workload_status_desc" />
+ </LinearLayout>
+ </LinearLayout>
+
+
+ <LinearLayout
+ android:id="@+id/workload_result_layout"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/seek_bar"
+ android:layout_centerHorizontal="true"
+ android:orientation="vertical" >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="@string/runtime_desc"
+ android:textSize="20sp" />
+
+ <TextView
+ android:id="@+id/runtime_info"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="20sp" />
+
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="@string/execution_time_desc"
+ android:textSize="20sp" />
+
+ <TextView
+ android:id="@+id/execution_time"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textColor="@color/result_color"
+ android:textSize="24sp" />
+
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/button_result"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/show_result_button_desc" />
+
+ </LinearLayout>
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/activity_profile_config"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context=".ProfileSettingActivity" >
+
+ <Button
+ android:id="@+id/button_confirm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:text="@string/setting_confirm_button_desc" />
+
+ <ScrollView
+ android:id="@+id/scrollView1"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/button_confirm" >
+
+ <LinearLayout
+ android:id="@+id/config_table"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:layoutMode="clipBounds"
+ android:orientation="vertical" >
+
+
+ <TableLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:shrinkColumns="0" >
+
+ <TableRow
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:text="@string/total_size_desc" />
+
+ <EditText
+ android:id="@+id/total_size_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="left"
+ android:inputType="number"
+ android:text="@string/total_size_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:text="@string/bucket_size_desc" />
+
+ <EditText
+ android:id="@+id/bucket_size_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="left"
+ android:inputType="number"
+ android:text="@string/bucket_size_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:text="@string/los_threshold_desc" />
+
+ <EditText
+ android:id="@+id/los_threshold_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="left"
+ android:inputType="number"
+ android:text="@string/los_threshold_default" />
+ </TableRow>
+
+ </TableLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:gravity="left"
+ android:singleLine="true"
+ android:text="@string/object_size_dist_desc" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/size_desc_16"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:gravity="center"
+ android:text="@string/object_size_16_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_16_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_16"
+ android:layout_below="@id/size_desc_16"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_16_default" />
+
+ <TextView
+ android:id="@+id/size_desc_32"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/size_desc_16"
+ android:gravity="center"
+ android:text="@string/object_size_32_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_32_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_32"
+ android:layout_below="@id/size_desc_32"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_32_default" />
+
+ <TextView
+ android:id="@+id/size_desc_64"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/size_desc_32"
+ android:gravity="center"
+ android:text="@string/object_size_64_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_64_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_64"
+ android:layout_below="@id/size_desc_64"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_64_default" />
+
+ <TextView
+ android:id="@+id/size_desc_128"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/size_desc_64"
+ android:gravity="center"
+ android:text="@string/object_size_128_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_128_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_128"
+ android:layout_below="@id/size_desc_128"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_128_default" />
+
+ <TextView
+ android:id="@+id/size_desc_256"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/size_desc_128"
+ android:gravity="center"
+ android:text="@string/object_size_256_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_256_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_256"
+ android:layout_below="@id/size_desc_256"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_256_default" />
+
+ <TextView
+ android:id="@+id/size_desc_512"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/size_desc_256"
+ android:gravity="center"
+ android:text="@string/object_size_512_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_512_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_512"
+ android:layout_below="@id/size_desc_512"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_512_default" />
+
+ <TextView
+ android:id="@+id/size_desc_los"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/size_desc_512"
+ android:gravity="center"
+ android:text="@string/object_size_los_desc" />
+
+ <EditText
+ android:id="@+id/size_dist_los_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/size_desc_los"
+ android:layout_below="@id/size_desc_los"
+ android:inputType="numberDecimal"
+ android:text="@string/size_dist_los_default" />
+ </RelativeLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:gravity="left"
+ android:singleLine="true"
+ android:text="@string/los_dist_desc" />
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <TextView
+ android:id="@+id/los_dist_desc_byte"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentTop="true"
+ android:gravity="center"
+ android:text="@string/los_dist_byte_desc" />
+
+ <EditText
+ android:id="@+id/los_dist_byte_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/los_dist_desc_byte"
+ android:layout_below="@id/los_dist_desc_byte"
+ android:inputType="numberDecimal"
+ android:text="@string/los_dist_byte_default" />
+
+ <TextView
+ android:id="@+id/los_dist_desc_char"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/los_dist_desc_byte"
+ android:gravity="center"
+ android:text="@string/los_dist_char_desc" />
+
+ <EditText
+ android:id="@+id/los_dist_char_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/los_dist_desc_char"
+ android:layout_below="@id/los_dist_desc_char"
+ android:inputType="numberDecimal"
+ android:text="@string/los_dist_char_default" />
+
+ <TextView
+ android:id="@+id/los_dist_desc_int"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/los_dist_desc_char"
+ android:gravity="center"
+ android:text="@string/los_dist_int_desc" />
+
+ <EditText
+ android:id="@+id/los_dist_int_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/los_dist_desc_int"
+ android:layout_below="@id/los_dist_desc_int"
+ android:inputType="numberDecimal"
+ android:text="@string/los_dist_int_default" />
+
+ <TextView
+ android:id="@+id/los_dist_desc_long"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="25dp"
+ android:layout_toRightOf="@id/los_dist_desc_int"
+ android:gravity="center"
+ android:text="@string/los_dist_long_desc" />
+
+ <EditText
+ android:id="@+id/los_dist_long_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignLeft="@id/los_dist_desc_long"
+ android:layout_below="@id/los_dist_desc_long"
+ android:inputType="numberDecimal"
+ android:text="@string/los_dist_long_default" />
+ </RelativeLayout>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:gravity="center"
+ android:text="@string/lifetime_desc" />
+
+ <TableLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_16_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_16_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_16_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_32_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_32_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_32_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_64_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_64_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_64_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_128_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_128_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_128_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_256_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_256_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_256_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_512_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_512_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_512_default" />
+ </TableRow>
+
+ <TableRow
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/object_size_los_desc" />
+
+ <EditText
+ android:id="@+id/lifetime_los_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="text"
+ android:text="@string/lifetime_los_default" />
+ </TableRow>
+
+ </TableLayout>
+
+ <CheckBox
+ android:id="@+id/single_thread"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ android:text="@string/single_thread_desc" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/thread_num_desc" />
+
+ <EditText
+ android:id="@+id/thread_num"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="number"
+ android:text="@string/thread_num_default" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/exe_time_desc" />
+
+ <EditText
+ android:id="@+id/exe_time_v"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="number"
+ android:text="@string/exe_time_default" />
+
+ </LinearLayout>
+ </ScrollView>
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/activity_result"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context=".ResultActivity" >
+
+ <TextView
+ android:id="@+id/vm_type"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:textSize="20sp"
+ android:text="@string/vm_type">
+ </TextView>
+
+ <LinearLayout
+ android:id="@+id/buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/vm_type"
+ android:layout_centerHorizontal="true"
+ android:orientation="horizontal" >
+
+ <Button
+ android:id="@+id/button_exe_time"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="@string/complete_time_desc" />
+
+ <Button
+ android:id="@+id/button_heap"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="@string/heap_desc" />
+
+ <Button
+ android:id="@+id/button_gc"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:text="@string/gc_desc" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/chart"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/buttons"
+ android:layout_marginTop="20dp"
+ android:layout_centerHorizontal="true"
+ android:orientation="horizontal" >
+ </LinearLayout>
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/action_button"
+ android:orderInCategory="100"
+ android:showAsAction="collapseActionView"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+ <monochrome android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@drawable/ic_launcher_background" />
+ <foreground android:drawable="@drawable/ic_launcher_foreground" />
+ <monochrome android:drawable="@drawable/ic_launcher_foreground" />
+</adaptive-icon>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<profile id="0" name="default">
+ <item name="total_size">100</item>
+ <item name="bucket_size">1</item>
+ <item name="los_threshold">12</item>
+ <float-array name="size_dist" count="7">
+ <value>0.0436</value>
+ <value>0.5465</value>
+ <value>0.2103</value>
+ <value>0.1499</value>
+ <value>0.0275</value>
+ <value>0.0125</value>
+ <value>0.0097</value>
+ </float-array>
+ <float-array-2d name="lifetime" count="7">
+ <float-array name="16b" count="4">
+ <value>0.0865</value>
+ <value>0.5404</value>
+ <value>0.2887</value>
+ <value>0.0865</value>
+ </float-array>
+ <float-array name="32b" count="4">
+ <value>0.0469</value>
+ <value>0.7724</value>
+ <value>0.1460</value>
+ <value>0.0346</value>
+ </float-array>
+ <float-array name="64b" count="4">
+ <value>0.1154</value>
+ <value>0.5982</value>
+ <value>0.1880</value>
+ <value>0.0984</value>
+ </float-array>
+ <float-array name="128b" count="4">
+ <value>0.0662</value>
+ <value>0.7851</value>
+ <value>0.1077</value>
+ <value>0.0411</value>
+ </float-array>
+ <float-array name="256b" count="4">
+ <value>0.0520</value>
+ <value>0.8778</value>
+ <value>0.0503</value>
+ <value>0.0198</value>
+ </float-array>
+ <float-array name="512b" count="4">
+ <value>0.1628</value>
+ <value>0.7137</value>
+ <value>0.0821</value>
+ <value>0.0414</value>
+ </float-array>
+ <float-array name="los" count="4">
+ <value>0.0923</value>
+ <value>0.7117</value>
+ <value>0.1769</value>
+ <value>0.0192</value>
+ </float-array>
+ </float-array-2d>
+ <float-array name="los_element_dist" count="4">
+ <value>0.90</value>
+ <value>0.07</value>
+ <value>0.02</value>
+ <value>0.01</value>
+ </float-array>
+ <item name="thread-mode">0</item>
+ <item name="thread-num">0</item>
+ <item name="iteration-times">10</item>
+</profile>
--- /dev/null
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <!-- Base application theme. -->
+ <style name="Base.Theme.AndroidGCTest" parent="Theme.Material3.DayNight.NoActionBar">
+ <!-- Customize your dark theme here. -->
+ <!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
+ </style>
+</resources>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="black">#FF000000</color>
+ <color name="white">#FFFFFFFF</color>
+</resources>
\ No newline at end of file
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">AndroidGCTest</string>
+ <string name="action_settings">Setting</string>
+ <string name="button_desc">Start</string>
+
+ <string name="total_size_desc">Total object size(MB)</string>
+ <string name="total_size_default">100</string>
+
+ <string name="bucket_size_desc">Bucket size(MB)</string>
+ <string name="bucket_size_default">1</string>
+
+ <string name="los_threshold_desc">Large Object Size(KB)</string>
+ <string name="los_threshold_default">12</string>
+
+ <string name="fragment_desc">Placeholder Degree (1 - 10)</string>
+ <string name="fragment_default">6</string>
+
+ <string name="object_size_16_desc">16byte</string>
+ <string name="object_size_32_desc">32byte</string>
+ <string name="object_size_64_desc">64byte</string>
+ <string name="object_size_128_desc">128byte</string>
+ <string name="object_size_256_desc">256byte</string>
+ <string name="object_size_512_desc">512byte</string>
+ <string name="object_size_los_desc">Large Object</string>
+ <string name="object_size_smaollobject_desc">Small Object</string>
+
+ <string name="object_size_dist_desc">Object Size Distribution</string>
+ <string name="size_dist_16_default">0.0436</string>
+ <string name="size_dist_32_default">0.5465</string>
+ <string name="size_dist_64_default">0.2103</string>
+ <string name="size_dist_128_default">0.1499</string>
+ <string name="size_dist_256_default">0.0275</string>
+ <string name="size_dist_512_default">0.0125</string>
+ <string name="size_dist_los_default">0.0097</string>
+
+ <string name="los_dist_desc">Large Object Element Type Distribution</string>
+ <string name="los_dist_byte_desc">Byte Array</string>
+ <string name="los_dist_char_desc">Char Array</string>
+ <string name="los_dist_int_desc">Int Array</string>
+ <string name="los_dist_long_desc">Long Array</string>
+ <string name="los_dist_byte_default">0.90</string>
+ <string name="los_dist_char_default">0.07</string>
+ <string name="los_dist_int_default">0.02</string>
+ <string name="los_dist_long_default">0.01</string>
+
+ <string name="lifetime_desc">Object Lifetime (long lived ratio, die immediately ratio,...)</string>
+ <string name="lifetime_16_default">0.0865,0.5404,0.2887,0.0865</string>
+ <string name="lifetime_32_default">0.0469,0.7724,0.1460,0.0346</string>
+ <string name="lifetime_64_default">0.1154,0.5982,0.1880,0.0984</string>
+ <string name="lifetime_128_default">0.0662,0.7851,0.1077,0.0411</string>
+ <string name="lifetime_256_default">0.0520,0.8778,0.0503,0.0198</string>
+ <string name="lifetime_512_default">0.1628,0.7137,0.0821,0.0414</string>
+ <string name="lifetime_los_default">0.0923,0.7117,0.1769,0.0192</string>
+ <string name="lifetime_smallobject_default">0.0883,0.7146,0.1438,0.0533</string>
+
+ <string name="single_thread_desc">Run in single thread?</string>
+ <string name="thread_num_desc">Thread # (0 means setting #thread as #CPU)</string>
+ <string name="thread_num_default">0</string>
+
+ <string name="exe_time_default">100</string>
+ <string name="exe_time_desc">set the iteration times of stress test phase, iterating 100 times takes ~160s on Nexus 5/ART</string>
+ <!-- <string name="los_threads_desc">Allocate large object in all threads?</string> -->
+
+ <string name="complete_time_desc">Complete Time</string>
+ <string name="heap_desc">Heap Footprint</string>
+ <string name="gc_desc">Gc Pause Time</string>
+ <string name="runtime_desc">Device: </string>
+ <string name="execution_time_desc">Execution time:</string>
+ <string name="show_result_button_desc">Show result details</string>
+ <string name="set_profile_button_desc">Setting</string>
+ <string name="start_button_desc">Start</string>
+ <string name="setting_confirm_button_desc">Confirm changes</string>
+ <string name="profile_list_dest">Select a profile</string>
+ <string name="workload_status_desc">Click "Setting" to config profile, click "Start" to run workload</string>
+ <string name="outofmemory_desc">OutOfMemory! Please config profile or Java Runtime and run again.</string>
+
+ <string name="vm_type">vm type</string>
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+ <color name="result_color">#ff7f27</color>
+
+</resources>
--- /dev/null
+<resources xmlns:tools="http://schemas.android.com/tools">
+ <!-- Base application theme. -->
+ <style name="Base.Theme.AndroidGCTest" parent="Theme.Material3.DayNight.NoActionBar">
+ <!-- Customize your light theme here. -->
+ <!-- <item name="colorPrimary">@color/my_light_primary</item> -->
+ </style>
+
+ <style name="Theme.AndroidGCTest" parent="Base.Theme.AndroidGCTest" />
+</resources>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ Sample backup rules file; uncomment and customize as necessary.
+ See https://developer.android.com/guide/topics/data/autobackup
+ for details.
+ Note: This file is ignored for devices older that API 31
+ See https://developer.android.com/about/versions/12/backup-restore
+-->
+<full-backup-content>
+ <!--
+ <include domain="sharedpref" path="."/>
+ <exclude domain="sharedpref" path="device.xml"/>
+-->
+</full-backup-content>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?><!--
+ Sample data extraction rules file; uncomment and customize as necessary.
+ See https://developer.android.com/about/versions/12/backup-restore#xml-changes
+ for details.
+-->
+<data-extraction-rules>
+ <cloud-backup>
+ <!-- TODO: Use <include> and <exclude> to control what is backed up.
+ <include .../>
+ <exclude .../>
+ -->
+ </cloud-backup>
+ <!--
+ <device-transfer>
+ <include .../>
+ <exclude .../>
+ </device-transfer>
+ -->
+</data-extraction-rules>
\ No newline at end of file
--- /dev/null
+package com.android.gctest;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
--- /dev/null
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+alias(libs.plugins.android.application) apply false
+}
\ No newline at end of file
--- /dev/null
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. For more details, visit
+# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
--- /dev/null
+[versions]
+agp = "8.5.0"
+junit = "4.13.2"
+junitVersion = "1.2.1"
+espressoCore = "3.6.1"
+appcompat = "1.7.0"
+material = "1.12.0"
+activity = "1.9.0"
+constraintlayout = "2.1.4"
+
+[libraries]
+junit = { group = "junit", name = "junit", version.ref = "junit" }
+ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
+espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
+appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
+material = { group = "com.google.android.material", name = "material", version.ref = "material" }
+activity = { group = "androidx.activity", name = "activity", version.ref = "activity" }
+constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
+
+[plugins]
+android-application = { id = "com.android.application", version.ref = "agp" }
+
--- /dev/null
+#Tue Jul 16 16:27:48 KST 2024
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
--- /dev/null
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
--- /dev/null
+@rem\r
+@rem Copyright 2015 the original author or authors.\r
+@rem\r
+@rem Licensed under the Apache License, Version 2.0 (the "License");\r
+@rem you may not use this file except in compliance with the License.\r
+@rem You may obtain a copy of the License at\r
+@rem\r
+@rem https://www.apache.org/licenses/LICENSE-2.0\r
+@rem\r
+@rem Unless required by applicable law or agreed to in writing, software\r
+@rem distributed under the License is distributed on an "AS IS" BASIS,\r
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+@rem See the License for the specific language governing permissions and\r
+@rem limitations under the License.\r
+@rem\r
+\r
+@if "%DEBUG%" == "" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%" == "" set DIRNAME=.\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.\r
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if "%ERRORLEVEL%" == "0" goto execute\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto execute\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if "%ERRORLEVEL%"=="0" goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1\r
+exit /b 1\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
--- /dev/null
+pluginManagement {
+ repositories {
+ google {
+ content {
+ includeGroupByRegex("com\\.android.*")
+ includeGroupByRegex("com\\.google.*")
+ includeGroupByRegex("androidx.*")
+ }
+ }
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.name = "AndroidGCTest"
+include ':app'
--- /dev/null
+<!--\r
+***********************************************************************************************\r
+<Build.Directory.targets>\r
+WARNING: DO NOT MODIFY this file. Incorrect changes to this file will make it\r
+ impossible to load or build your projects from the IDE.\r
+\r
+***********************************************************************************************\r
+-->\r
+\r
+<Project> \r
+ <Target Name="BuildDotnet" AfterTargets="TizenPackage" >\r
+ <Message Text="Tizen Build starts here ------------" Importance="high"/>\r
+ <Message Text="$(MSBuildProjectDirectory)" Importance="high"/>\r
+ <PropertyGroup>\r
+ <WorkspaceFolder>$([System.IO.Path]::GetDirectoryName($(MSBuildProjectDirectory)))</WorkspaceFolder>\r
+ </PropertyGroup>\r
+ <Message Text="Workspace: '$(WorkspaceFolder)'" Importance="high" />\r
+\r
+ <Exec Command="C:\tizen-studio\tools\tizen-core\tz.exe pack -S $(ProjectDir) $(WorkspaceFolder)"> </Exec>\r
+ </Target>\r
+</Project>\r
--- /dev/null
+using System;\r
+using System.Collections.Generic;\r
+using System.Diagnostics;\r
+using System.IO;\r
+using System.Security.Claims;\r
+using System.Threading;\r
+using Tizen.Applications;\r
+using Tizen.Content.MediaContent;\r
+using Tizen.Messaging.Messages;\r
+using Tizen;\r
+using Tizen.NUI.Components;\r
+using TizenGCTest;\r
+using Microsoft.VisualBasic;\r
+using System.Linq;\r
+using System.Runtime.InteropServices;\r
+using System.Reflection;\r
+using System.Text;\r
+using Tizen.NUI;\r
+using Tizen.NUI.BaseComponents;\r
+using static System.Net.Mime.MediaTypeNames;\r
+\r
+namespace TizenGCTest\r
+{\r
+ public class TreeNode\r
+ {\r
+ public TreeNode left, right;\r
+ public TreeNode(TreeNode l, TreeNode r)\r
+ {\r
+ left = l;\r
+ right = r;\r
+ }\r
+ public TreeNode() { }\r
+ public int Count()\r
+ {\r
+ int c = 1;\r
+ if (left != null)\r
+ c += left.Count();\r
+ if (right != null)\r
+ c += right.Count();\r
+ return c;\r
+ }\r
+ }\r
+\r
+ class TreeNode32 : TreeNode\r
+ { // object size = 24\r
+ private long payload1;\r
+ public TreeNode32(TreeNode32 l, TreeNode32 r) : base(l, r) { }\r
+ public TreeNode32() { }\r
+ }\r
+\r
+ class TreeNode64 : TreeNode\r
+ { // object size = 40\r
+ private long payload1, payload2, payload3;\r
+ public TreeNode64(TreeNode64 l, TreeNode64 r) : base(l, r) { }\r
+ public TreeNode64() { }\r
+ }\r
+\r
+ class TreeNode128 : TreeNode\r
+ { // object size = 96\r
+ private long payload1, payload2, payload3, payload4, payload5;\r
+ private long payload6, payload7, payload8, payload9, payload10;\r
+ public TreeNode128(TreeNode128 l, TreeNode128 r) : base(l, r) { }\r
+ public TreeNode128() { }\r
+ }\r
+\r
+ class TreeNode256 : TreeNode\r
+ { // object size = 192\r
+ private long payload1, payload2, payload3, payload4, payload5;\r
+ private long payload6, payload7, payload8, payload9, payload10;\r
+ private long payload11, payload12, payload13, payload14, payload15;\r
+ private long payload16, payload17, payload18, payload19, payload20;\r
+ private long payload21, payload22;\r
+ public TreeNode256(TreeNode256 l, TreeNode256 r) : base(l, r) { }\r
+ public TreeNode256() { }\r
+ }\r
+\r
+ class TreeNode512 : TreeNode\r
+ { // object size = 336\r
+ private long payload1, payload2, payload3, payload4, payload5;\r
+ private long payload6, payload7, payload8, payload9, payload10;\r
+ private long payload11, payload12, payload13, payload14, payload15;\r
+ private long payload16, payload17, payload18, payload19, payload20;\r
+ private long payload101, payload102, payload103, payload104, payload105;\r
+ private long payload106, payload107, payload108, payload109, payload100;\r
+ private long payload111, payload112, payload113, payload114, payload115;\r
+ private long payload116, payload117, payload118, payload119, payload120;\r
+ public TreeNode512(TreeNode512 l, TreeNode512 r) : base(l, r) { }\r
+ public TreeNode512() { }\r
+ }\r
+\r
+ public class LinkNode\r
+ {\r
+ public LinkNode Next { get; set; }\r
+ public TreeNode TreeNode { get; set; }\r
+\r
+ public LinkNode(TreeNode n)\r
+ {\r
+ TreeNode = n;\r
+ }\r
+\r
+ public LinkNode() { }\r
+ }\r
+\r
+ class LivedLink\r
+ {\r
+ public LinkNode TreeHead { get; set; }\r
+ public LivedLink() { TreeHead = null; }\r
+ public void insertNode(TreeNode newTree)\r
+ {\r
+ if (TreeHead == null)\r
+ {\r
+ TreeHead = new LinkNode(newTree);\r
+ TreeHead.Next = null;\r
+ }\r
+ else\r
+ {\r
+ LinkNode newNode = new LinkNode(newTree);\r
+ newNode.Next = TreeHead;\r
+ TreeHead = newNode;\r
+ }\r
+ }\r
+ }\r
+\r
+ public class GCTest\r
+ {\r
+ private const String mTag = "TizenGCTest";\r
+\r
+ // size of small objects\r
+ public const int OBJECT_16_BYTE = 0;\r
+ public const int OBJECT_32_BYTE = 1;\r
+ public const int OBJECT_64_BYTE = 2;\r
+ public const int OBJECT_128_BYTE = 3;\r
+ public const int OBJECT_256_BYTE = 4;\r
+ public const int OBJECT_512_BYTE = 5;\r
+ public const int OBJECT_LARGE_BYTE = 6;\r
+ public const int OBJECT_SIZE_TYPE = 7;\r
+ private int[] mObjectSize = new int[] { 16, 24, 40, 96, 192, 336 };\r
+\r
+ // size of large object, default is 12KByte\r
+ private int mLargeObjectSize = 0;\r
+ // array element type distribution for large object\r
+ // {1-byte array, 2-byte array, 4-byte array, 8-byte array}\r
+ private float[] mLargeObjectDistribution = null;\r
+\r
+ // allocation configuration\r
+ // total allocate size\r
+ private int mTotalAllocateSize = 0;\r
+ // total allocate size by one thread\r
+ private int mTotalAllocSizePerThread = 0;\r
+\r
+ // unit for tree allocation/deletion operation.\r
+ // mBucketSize is also the unit to measure object lifetime.\r
+ // Benchmark allocates mBucketSize of data -> deletes some data\r
+ // -> allocates mBucketSize of Data\r
+ private int mBucketSize = 0;\r
+\r
+ // allocated object size distribution\r
+ // {[1-16], [17-32], [33-64], [65, 128], [129, 256], [257, 512], >12K}\r
+ private float[] mSizeDistribution = null;\r
+\r
+ // allocated object lifetime:\r
+ // mLifetime[X][0] is long lived object percentage of object size X,\r
+ // mLifetime[X][1] is percentage of object die immediately,\r
+ // mLifetime[X][2] is percentage of object die in next period after\r
+ // creation period ...\r
+ private float[][] mLifetime = null;\r
+\r
+ private int mLongLiveSmallObjectSize;\r
+\r
+ // a big array to store random values to decide object size of next allocated object\r
+ private byte[][] mObjectSizeRandom = null;\r
+ // a big array to store random values to decide lifetime of next allocated object\r
+ private byte[][] mLifetimeRandom = null;\r
+ private int mShortLiveTreeCount;\r
+ private int mTotalNodeCount;\r
+ private const int mTreeCountParallel = 4;\r
+\r
+ private int[] mLargeArrayLength = null;\r
+ private int[] mLargeArrayNum = null;\r
+ private int[] mLargeArrayInter = null;\r
+ private int mLongLiveLargeObjectSize;\r
+ private int[][] mDieNumLargeObject = null;\r
+\r
+ // thread mode configuration\r
+ private int mThreadNum;\r
+ private bool mSingleThread = false;\r
+\r
+ private long[] mStartTime = null;\r
+ private long[] mEndTime = null;\r
+ private long[] mElapseTime = null;\r
+ private int[] mHeapFootprint = null;\r
+ private long[] mHeapBytesAllocated = null;\r
+\r
+ private long mTotalGcCount;\r
+ private long mTotalGcTime;\r
+ private long mTotalBlockingGcCount;\r
+ private long mTotalBlockingGcTime;\r
+ public String[] GC_CAUSE_ART = new String[]{"Alloc", "Background", "Explicit", "NativeAlloc", "CollectorTransition", "DisableMovingGc", "HomogeneousSpaceCompact", "HeapTrim"};\r
+ public String[] GC_CAUSE_DALVIK = new String[]{"GC_FOR_ALLOC","GC_CONCURRENT", "GC_EXPLICIT", "GC_BEFORE_OOM"};\r
+ private int[] mGcCauseCount = null;\r
+ private float[] mGcPauseTime = null;\r
+ private float[] mGcTotalTime = null;\r
+ private String[] mGcCause = null;\r
+\r
+ private bool isArt;\r
+ private bool mWorkloadComplete;\r
+ private int mIterNum = 100;\r
+\r
+ private StreamWriter fileOutput;\r
+ private BenchThread[] mTestThreads;\r
+ //private Thread[] mThreads;\r
+ private Thread t0, t1, t2, t3;\r
+ private bool mOutOfMemory;\r
+ private bool flag0 = false, flag1 = false, flag2 = false, flag3 = false;\r
+\r
+ private readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);\r
+\r
+ public TextLabel text;\r
+\r
+ private void init()\r
+ {\r
+ // thread number;\r
+ if (mSingleThread)\r
+ {\r
+ mThreadNum = 1;\r
+ }\r
+ else if (mThreadNum == 0)\r
+ {\r
+ //mThreadNum = Runtime.getRuntime().availableProcessors();\r
+ mThreadNum = Environment.ProcessorCount;\r
+ }\r
+ if (mThreadNum == 0)\r
+ {\r
+ mThreadNum = 1;\r
+ }\r
+\r
+ if (mSizeDistribution == null)\r
+ {\r
+ mSizeDistribution = new float[]{0.0436f,0.5465f,0.2103f,0.1499f,\r
+ 0.0275f,0.0125f,0.0097f};\r
+ }\r
+ //if (mLifetime == null)\r
+ {\r
+ mLifetime = new float[][] {\r
+ new float[] { 0.0865f, 0.5404f, 0.2887f, 0.0865f },\r
+ new float[] { 0.0469f, 0.7724f, 0.1460f, 0.0346f },\r
+ new float[] { 0.1154f, 0.5982f, 0.1880f, 0.0984f },\r
+ new float[] { 0.0662f, 0.7851f, 0.1077f, 0.0411f },\r
+ new float[] { 0.0520f, 0.8778f, 0.0503f, 0.0198f },\r
+ new float[] { 0.1628f, 0.7137f, 0.0821f, 0.0414f },\r
+ new float[] { 0.0923f, 0.7117f, 0.1769f, 0.0192f }// large object lifetime\r
+ };\r
+ \r
+ }\r
+\r
+ if (mLargeObjectDistribution == null)\r
+ {\r
+ mLargeObjectDistribution = new float[] { 0.9f, 0.07f, 0.02f, 0.01f };\r
+ }\r
+\r
+ if (mTotalAllocateSize == 0)\r
+ {\r
+ mTotalAllocateSize = 100 * 1024 * 1024;\r
+ }\r
+ mTotalAllocSizePerThread = mTotalAllocateSize / mThreadNum;\r
+\r
+ if (mBucketSize == 0)\r
+ {\r
+ mBucketSize = 1 * 1024 * 1024;\r
+ }\r
+\r
+ if (mLargeObjectSize == 0)\r
+ {\r
+ mLargeObjectSize = 12 * 1024;\r
+ }\r
+\r
+ Log.Info(mTag, "Allocate Size: " + (mTotalAllocateSize / 1024) + " kB");\r
+ Log.Info(mTag, "BucketSize: " + (mBucketSize / 1024) + " kB");\r
+ Log.Info(mTag, "Large object size: " + (mLargeObjectSize / 1024) + " kB");\r
+ Log.Info(mTag, "Single Thread: " + mSingleThread);\r
+ Log.Info(mTag, "Thread number: " + mThreadNum);\r
+ Log.Info(mTag, "Stress test part iterates " + mIterNum + " times");\r
+\r
+ string curDate = DateTime.Now.ToString();\r
+ try\r
+ {\r
+ using (StreamWriter fileOutput = new StreamWriter("/tmp/TizenGCTest-result.txt", true))\r
+ {\r
+ fileOutput.WriteLine();\r
+ fileOutput.WriteLine(curDate);\r
+\r
+ fileOutput.WriteLine("Workload configuration:");\r
+ fileOutput.WriteLine("\tAllocate Size: " + (mTotalAllocateSize / 1024) + " kB");\r
+ fileOutput.WriteLine("\tBucketSize: " + (mBucketSize / 1024) + " kB");\r
+ fileOutput.WriteLine("\tLarge object size: " + (mLargeObjectSize / 1024) + " kB");\r
+ fileOutput.WriteLine("\tThread mode: " + (mSingleThread ? "Single-Thread" : "Multi-Thread"));\r
+ fileOutput.WriteLine("\t: " + mThreadNum);\r
+ fileOutput.WriteLine("\tStress test part iterates " + mIterNum + " times");\r
+ }\r
+ }\r
+ catch (IOException e)\r
+ {\r
+ Log.Info(mTag, "Cannot open /tmp/TizenGCTest-result.txt" + e.Message);\r
+ }\r
+\r
+ int smallObjectSize, largeObjectSize;\r
+ largeObjectSize = (int)(mTotalAllocSizePerThread * mSizeDistribution[OBJECT_LARGE_BYTE]);\r
+ smallObjectSize = mTotalAllocSizePerThread - largeObjectSize;\r
+\r
+ float[] countDistr = new float[OBJECT_LARGE_BYTE];\r
+ float nodeSize = 0.0f;\r
+ int[] sizeThreshold = new int[OBJECT_LARGE_BYTE];\r
+ int lifetimeLen = mLifetime[0].Length;\r
+ int[][] lifetimeThreshold = new int[OBJECT_LARGE_BYTE][];\r
+ for (int i = 0; i < OBJECT_LARGE_BYTE; i++)\r
+ {\r
+ lifetimeThreshold[i] = new int[lifetimeLen];\r
+ }\r
+ float sum = 0.0f;\r
+ for (int i = 0; i < OBJECT_LARGE_BYTE; i++)\r
+ {\r
+ countDistr[i] = mSizeDistribution[i]\r
+ / (1 - mSizeDistribution[OBJECT_LARGE_BYTE]) / mObjectSize[i];\r
+ sum += countDistr[i];\r
+ }\r
+\r
+ mLongLiveSmallObjectSize = 0;\r
+ float sum1 = 0.0f;\r
+ for (int i = 0; i < OBJECT_LARGE_BYTE; i++)\r
+ {\r
+ sum1 += countDistr[i];\r
+ sizeThreshold[i] = (int)(sum1 * 1000 / sum + 0.5);\r
+ nodeSize += mObjectSize[i] * countDistr[i] / sum;\r
+\r
+ float sum2 = 0.0f;\r
+ for (int j = 1; j < lifetimeLen; j++)\r
+ {\r
+ sum2 += mLifetime[i][j];\r
+ lifetimeThreshold[i][j - 1] = (int)(sum2 * 1000 + 0.5);\r
+ }\r
+ lifetimeThreshold[i][lifetimeLen - 1] = 1000;\r
+\r
+ mLongLiveSmallObjectSize += (int)(mTotalAllocSizePerThread * mSizeDistribution[i] * mLifetime[i][0]);\r
+ }\r
+ sizeThreshold[OBJECT_512_BYTE] = 1000;\r
+\r
+\r
+ mShortLiveTreeCount = (int)(smallObjectSize / mBucketSize + 0.5);\r
+ mTotalNodeCount = (int)(mBucketSize / nodeSize * 1.11);\r
+\r
+ mObjectSizeRandom = new byte[mThreadNum][];\r
+ mLifetimeRandom = new byte[mThreadNum][];\r
+ for (int i = 0; i < mThreadNum; i++)\r
+ {\r
+ mObjectSizeRandom[i] = new byte[mTotalNodeCount];\r
+ mLifetimeRandom[i] = new byte[mTotalNodeCount];\r
+ }\r
+\r
+ Random r_size = new Random();\r
+ Random r_lifetime = new Random(mThreadNum);\r
+ for (int i = 0; i < mThreadNum; i++)\r
+ {\r
+ r_size = new Random(i);\r
+ r_lifetime = new Random(i + mThreadNum);\r
+ for (int j = 0; j < mTotalNodeCount; j++)\r
+ {\r
+ int vs = r_size.Next(1000);\r
+ int vl = r_lifetime.Next(1000);\r
+ for (int k = 0; k < OBJECT_LARGE_BYTE; k++)\r
+ {\r
+ if (vs < sizeThreshold[k])\r
+ {\r
+ mObjectSizeRandom[i][j] = (byte)(OBJECT_16_BYTE + k);\r
+ for (int l = 0; l < lifetimeLen; l++)\r
+ {\r
+ if (vl < lifetimeThreshold[k][l])\r
+ {\r
+ mLifetimeRandom[i][j] = (byte)l;\r
+ //Log.Info(mTag, "mLifetimeRandom["+i+"]["+j+"] : " + l);\r
+ break;\r
+ }\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ mLongLiveLargeObjectSize = (int)(largeObjectSize * mLifetime[OBJECT_LARGE_BYTE][0]);\r
+ mDieNumLargeObject = new int[4][];\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ mDieNumLargeObject[i] = new int[lifetimeLen - 1];\r
+ }\r
+ mLargeArrayInter = new int[4];\r
+ mLargeArrayLength = new int[4];\r
+ mLargeArrayNum = new int[4];\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ mLargeArrayLength[i] = (int)((largeObjectSize * mLargeObjectDistribution[i]\r
+ / mLargeObjectSize) + 0.5);\r
+ if (mLargeArrayLength[i] == 0)\r
+ {\r
+ mLargeArrayInter[i] = mShortLiveTreeCount + 1;\r
+ mLargeArrayNum[i] = 0;\r
+ continue;\r
+ }\r
+ if (mShortLiveTreeCount > mLargeArrayLength[i])\r
+ {\r
+ mLargeArrayInter[i] = mShortLiveTreeCount / mLargeArrayLength[i];\r
+ mLargeArrayNum[i] = 1;\r
+ mLargeArrayLength[i] = mShortLiveTreeCount / mLargeArrayInter[i] + 1;\r
+ }\r
+ else\r
+ {\r
+ mLargeArrayInter[i] = 1;\r
+ mLargeArrayNum[i] = (int)(mLargeArrayLength[i] / (float)mShortLiveTreeCount + 0.5);\r
+ mLargeArrayLength[i] = mLargeArrayNum[i] * mShortLiveTreeCount;\r
+ }\r
+\r
+ sum = 0.0f;\r
+ for (int j = 1; j < lifetimeLen; j++)\r
+ {\r
+ sum += mLifetime[OBJECT_LARGE_BYTE][j];\r
+ mDieNumLargeObject[i][j - 1] = (int)(mLargeArrayNum[i] * sum);\r
+ }\r
+ }\r
+ text = new TextLabel();\r
+ text.TextColor = Color.White;\r
+ Window.Instance.GetDefaultLayer().Add(text);\r
+ Log.Info(mTag, "init done");\r
+ }\r
+\r
+ private void clearInitData()\r
+ {\r
+ Log.Info(mTag, "clear auxiliary data to run workload");\r
+ mLifetime = null;\r
+ mLargeObjectDistribution = null;\r
+ mSizeDistribution = null;\r
+ mObjectSizeRandom = null;\r
+ mLifetimeRandom = null;\r
+ mLargeArrayInter = null;\r
+ mLargeArrayLength = null;\r
+ mLargeArrayNum = null;\r
+ mDieNumLargeObject = null;\r
+ //Runtime.getRuntime().runFinalization();\r
+ //Runtime.getRuntime().gc();\r
+ GC.Collect();\r
+ GC.WaitForPendingFinalizers();\r
+ }\r
+\r
+ public GCTest()\r
+ {\r
+ init();\r
+ }\r
+ public GCTest(/*MainActivity activity,*/ int heapSize, int bucketSize, int largeObjectSize,\r
+ float[] sizeDistr, float[][] lifetimeDistr, float[] largeObjectSizeDist,\r
+ bool singleThread, int thread_num, int exeTime)\r
+ {\r
+ //mActivity = activity;\r
+ mTotalAllocateSize = heapSize * 1024 * 1024;\r
+ mBucketSize = bucketSize * 1024 * 1024;\r
+ mLargeObjectSize = largeObjectSize * 1024;\r
+ mSizeDistribution = sizeDistr;\r
+ mLifetime = lifetimeDistr;\r
+ mLargeObjectDistribution = largeObjectSizeDist;\r
+ mSingleThread = singleThread;\r
+ mThreadNum = mSingleThread ? 1 : thread_num;\r
+ mIterNum = exeTime > 0 ? exeTime : 100;\r
+ init();\r
+ }\r
+\r
+\r
+ private void freeArrays(byte[][] byteArray, char[][] charArray, int[][] intArray,\r
+ long[][] longArray, int[] arrayIdx, int treeCount)\r
+ {\r
+ int len = mDieNumLargeObject[0].Length;\r
+ int died, release, phase;\r
+\r
+ phase = treeCount % mLargeArrayInter[0];\r
+ if (byteArray != null && phase <= len)\r
+ {\r
+ int curIdx = arrayIdx[0] - mLargeArrayNum[0];\r
+ while (curIdx >= 0 && phase <= len)\r
+ {\r
+ if (phase == 0)\r
+ died = 0;\r
+ else\r
+ died = mDieNumLargeObject[0][phase - 1];\r
+ if (phase == len)\r
+ {\r
+ if (byteArray[curIdx + died] != null)\r
+ {\r
+ for (int i = died; i < mLargeArrayNum[0]; i++)\r
+ byteArray[curIdx + i] = null;\r
+ }\r
+ break;\r
+ }\r
+ release = mDieNumLargeObject[0][phase];\r
+ for (int i = died; i < release; i++)\r
+ {\r
+ if (i >= mLargeArrayNum[0])\r
+ break;\r
+ byteArray[curIdx + i] = null;\r
+ }\r
+ curIdx -= mLargeArrayNum[0];\r
+ phase += mLargeArrayInter[0];\r
+ }\r
+ }\r
+\r
+ phase = treeCount % mLargeArrayInter[1];\r
+ if (charArray != null && phase < mLargeArrayNum[1])\r
+ {\r
+ int curIdx = arrayIdx[1] - mLargeArrayNum[1];\r
+ while (curIdx >= 0 && phase <= len)\r
+ {\r
+ if (phase == 0)\r
+ died = 0;\r
+ else\r
+ died = mDieNumLargeObject[1][phase - 1];\r
+ if (phase == len)\r
+ {\r
+ if (charArray[curIdx + died] != null)\r
+ {\r
+ for (int i = died; i < mLargeArrayNum[1]; i++)\r
+ charArray[curIdx + i] = null;\r
+ }\r
+ break;\r
+ }\r
+ release = mDieNumLargeObject[1][phase];\r
+ for (int i = died; i < release; i++)\r
+ {\r
+ if (i >= mLargeArrayNum[1])\r
+ break;\r
+ charArray[curIdx + i] = null;\r
+ }\r
+ curIdx -= mLargeArrayNum[1];\r
+ phase += mLargeArrayInter[1];\r
+ }\r
+ }\r
+\r
+ phase = treeCount % mLargeArrayInter[2];\r
+ if (intArray != null && phase < mLargeArrayNum[2])\r
+ {\r
+ int curIdx = arrayIdx[2] - mLargeArrayNum[2];\r
+ while (curIdx >= 0 && phase <= len)\r
+ {\r
+ if (phase == 0)\r
+ died = 0;\r
+ else\r
+ died = mDieNumLargeObject[2][phase - 1];\r
+ if (phase == len)\r
+ {\r
+ if (intArray[curIdx + died] != null)\r
+ {\r
+ for (int i = died; i < mLargeArrayNum[2]; i++)\r
+ intArray[curIdx + i] = null;\r
+ }\r
+ break;\r
+ }\r
+ release = mDieNumLargeObject[2][phase];\r
+ for (int i = died; i < release; i++)\r
+ {\r
+ if (i >= mLargeArrayNum[2])\r
+ break;\r
+ intArray[curIdx + i] = null;\r
+ }\r
+ curIdx -= mLargeArrayNum[2];\r
+ phase += mLargeArrayInter[2];\r
+ }\r
+ }\r
+\r
+ phase = treeCount % mLargeArrayInter[3];\r
+ if (longArray != null && phase < mLargeArrayNum[3])\r
+ {\r
+ int curIdx = arrayIdx[3] - mLargeArrayNum[3];\r
+ while (curIdx >= 0 && phase <= len)\r
+ {\r
+ if (phase == 0)\r
+ died = 0;\r
+ else\r
+ died = mDieNumLargeObject[3][phase - 1];\r
+ if (phase == len)\r
+ {\r
+ if (longArray[curIdx + died] != null)\r
+ {\r
+ for (int i = died; i < mLargeArrayNum[3]; i++)\r
+ longArray[curIdx + i] = null;\r
+ }\r
+ break;\r
+ }\r
+ release = mDieNumLargeObject[3][phase];\r
+ for (int i = died; i < release; i++)\r
+ {\r
+ if (i >= mLargeArrayNum[3])\r
+ break;\r
+ longArray[curIdx + i] = null;\r
+ }\r
+ curIdx -= mLargeArrayNum[3];\r
+ phase += mLargeArrayInter[3];\r
+ }\r
+ }\r
+ }\r
+\r
+ private void makeTreesLongLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount)\r
+ {\r
+ while (true)\r
+ {\r
+ if (allocSize <= 0)\r
+ {\r
+ trees = null;\r
+ return;\r
+ }\r
+\r
+ int len = trees.Length;\r
+ TreeNode[] nextTrees = new TreeNode[len * 2];\r
+ byte random;\r
+ for (int i = 0; i < len; i++)\r
+ {\r
+ TreeNode node = null;\r
+ random = mObjectSizeRandom[myId][nodeCount[0]];\r
+ switch (random)\r
+ {\r
+ case OBJECT_16_BYTE:\r
+ node = new TreeNode();\r
+ break;\r
+ case OBJECT_32_BYTE:\r
+ node = new TreeNode32();\r
+ break;\r
+ case OBJECT_64_BYTE:\r
+ node = new TreeNode64();\r
+ break;\r
+ case OBJECT_128_BYTE:\r
+ node = new TreeNode128();\r
+ break;\r
+ case OBJECT_256_BYTE:\r
+ node = new TreeNode256();\r
+ break;\r
+ case OBJECT_512_BYTE:\r
+ node = new TreeNode512();\r
+ break;\r
+ }\r
+ trees[i].left = node;\r
+ nextTrees[2 * i] = node;\r
+ allocSize -= mObjectSize[random];\r
+ nodeCount[0]++;\r
+ if (nodeCount[0] == mTotalNodeCount)\r
+ nodeCount[0] = 0;\r
+\r
+ random = mObjectSizeRandom[myId][nodeCount[0]];\r
+ switch (random)\r
+ {\r
+ case OBJECT_16_BYTE:\r
+ node = new TreeNode();\r
+ break;\r
+ case OBJECT_32_BYTE:\r
+ node = new TreeNode32();\r
+ break;\r
+ case OBJECT_64_BYTE:\r
+ node = new TreeNode64();\r
+ break;\r
+ case OBJECT_128_BYTE:\r
+ node = new TreeNode128();\r
+ break;\r
+ case OBJECT_256_BYTE:\r
+ node = new TreeNode256();\r
+ break;\r
+ case OBJECT_512_BYTE:\r
+ node = new TreeNode512();\r
+ break;\r
+ }\r
+ trees[i].right = node;\r
+ nextTrees[2 * i + 1] = node;\r
+ allocSize -= mObjectSize[random];\r
+ nodeCount[0]++;\r
+ if (nodeCount[0] == mTotalNodeCount)\r
+ nodeCount[0] = 0;\r
+\r
+ if (allocSize <= 0)\r
+ {\r
+ trees = null;\r
+ break;\r
+ }\r
+ }\r
+ trees = null;\r
+ trees = nextTrees;\r
+ }\r
+ }\r
+\r
+ private void makeTreesShortLive(TreeNode[] trees, int allocSize, int myId, int[] nodeCount)\r
+ {\r
+ int lifetimeLen = mLifetime[0].Length;\r
+ int[] curTreeIdx = new int[lifetimeLen];\r
+ int[] nextTreeIdx = new int[lifetimeLen];\r
+ TreeNode[][] curTrees = new TreeNode[lifetimeLen][];\r
+ TreeNode[][] nextTrees = new TreeNode[lifetimeLen][];\r
+ for (int i = 0; i < lifetimeLen; i++)\r
+ {\r
+ curTrees[i] = new TreeNode[1];\r
+ curTrees[i][0] = trees[i];\r
+ curTreeIdx[i] = 0;\r
+ }\r
+\r
+ while (true)\r
+ {\r
+ if (allocSize <= 0)\r
+ {\r
+ trees = null;\r
+ return;\r
+ }\r
+\r
+ byte rs = mObjectSizeRandom[myId][nodeCount[0]];\r
+ TreeNode node = null;\r
+ switch (rs)\r
+ {\r
+ case OBJECT_16_BYTE:\r
+ node = new TreeNode();\r
+ break;\r
+ case OBJECT_32_BYTE:\r
+ node = new TreeNode32();\r
+ break;\r
+ case OBJECT_64_BYTE:\r
+ node = new TreeNode64();\r
+ break;\r
+ case OBJECT_128_BYTE:\r
+ node = new TreeNode128();\r
+ break;\r
+ case OBJECT_256_BYTE:\r
+ node = new TreeNode256();\r
+ break;\r
+ case OBJECT_512_BYTE:\r
+ node = new TreeNode512();\r
+ break;\r
+ }\r
+\r
+ byte rl = mLifetimeRandom[myId][nodeCount[0]];\r
+ if (nextTrees[rl] == null)\r
+ {\r
+ nextTrees[rl] = new TreeNode[curTrees[rl].Length << 1];\r
+ nextTreeIdx[rl] = 0;\r
+ nextTrees[rl][0] = node;\r
+ }\r
+ else\r
+ {\r
+ nextTrees[rl][++nextTreeIdx[rl]] = node;\r
+ }\r
+ TreeNode parent = curTrees[rl][curTreeIdx[rl]];\r
+ if (parent.left == null)\r
+ {\r
+ parent.left = node;\r
+ }\r
+ else\r
+ {\r
+ parent.right = node;\r
+ curTreeIdx[rl]++;\r
+ if (curTreeIdx[rl] == curTrees[rl].Length)\r
+ {\r
+ curTrees[rl] = nextTrees[rl];\r
+ nextTrees[rl] = null;\r
+ curTreeIdx[rl] = 0;\r
+ }\r
+ }\r
+\r
+ allocSize -= mObjectSize[rs];\r
+ nodeCount[0]++;\r
+ if (nodeCount[0] == mTotalNodeCount) nodeCount[0] = 0;\r
+ }\r
+ }\r
+\r
+ public bool allocTrace(int myId)\r
+ {\r
+ switch(myId) {\r
+ case 0:\r
+ if (flag0) return false;\r
+ else flag0 = true;\r
+ break;\r
+ case 1:\r
+ if (flag1) return false;\r
+ else flag1 = true;\r
+ break;\r
+ case 2:\r
+ if (flag2) return false;\r
+ else flag2 = true;\r
+ break;\r
+ case 3:\r
+ if (flag3) return false;\r
+ else flag3 = true;\r
+ break;\r
+ }\r
+ \r
+ // long-lived data\r
+ Log.Info(mTag, "Thread-" + myId + " ----- Build long lived trees -----");\r
+\r
+ LivedLink longLiveTreeLink = new LivedLink();\r
+ TreeNode[] trees = new TreeNode[mTreeCountParallel];\r
+ int[] nodeCount = new int[] { 0 };\r
+\r
+ for (int i = 0; i < mTreeCountParallel; i++)\r
+ {\r
+ TreeNode node = new TreeNode();\r
+ longLiveTreeLink.insertNode(node);\r
+ trees[i] = node;\r
+ }\r
+\r
+ makeTreesLongLive(trees, mLongLiveSmallObjectSize, myId, nodeCount);\r
+\r
+ trees = null;\r
+\r
+ Log.Info(mTag, "Thread-" + myId + " ----- Build long lived byte array -----");\r
+ int longLiveArrayCount = (int)(mLongLiveLargeObjectSize / mLargeObjectSize + 0.5);\r
+ if (longLiveArrayCount <= 0)\r
+ longLiveArrayCount = 1;\r
+ byte[][] longLiveByteArrays = new byte[longLiveArrayCount][];\r
+ for (int i = 0; i < longLiveArrayCount; i++)\r
+ {\r
+ longLiveByteArrays[i] = new byte[mLargeObjectSize];\r
+ for (int j = 0; j < mLargeObjectSize; j += 100)\r
+ longLiveByteArrays[i][j] = (byte)0xff;\r
+ }\r
+\r
+ // stress test\r
+ Log.Info(mTag, "Thread-" + myId + " ----- Stress test -----");\r
+ //Debug.MemoryInfo memInfo = new Debug.MemoryInfo();\r
+\r
+ int lifetimeLen = mLifetime[0].Length;\r
+ TreeNode[][] shortLiveTrees = new TreeNode[lifetimeLen][];\r
+ for (int i = 0; i < lifetimeLen; i++)\r
+ {\r
+ shortLiveTrees[i] = new TreeNode[lifetimeLen];\r
+ }\r
+\r
+ byte[][] shortLiveByteArray = null;\r
+ char[][] shortLiveCharArray = null;\r
+ int[][] shortLiveIntArray = null;\r
+ long[][] shortLiveLongArray = null;\r
+\r
+ nodeCount[0] = 0;\r
+ int round = 0;\r
+\r
+ for (int iter = 0; iter < mIterNum; iter++)\r
+ {\r
+ //Log.Info(mTag, "Run " + myId + " - iter : " + iter);\r
+ if (mOutOfMemory)\r
+ break;\r
+ int[] allocIdx = new int[] { 0, 0, 0, 0 };\r
+\r
+ if (mLargeArrayLength[0] != 0)\r
+ shortLiveByteArray = new byte[mLargeArrayLength[0]][];\r
+ if (mLargeArrayLength[1] != 0)\r
+ shortLiveCharArray = new char[mLargeArrayLength[1]][];\r
+ if (mLargeArrayLength[2] != 0)\r
+ shortLiveIntArray = new int[mLargeArrayLength[2]][];\r
+ if (mLargeArrayLength[3] != 0)\r
+ shortLiveLongArray = new long[mLargeArrayLength[3]][];\r
+\r
+ int treeCount = 0;\r
+ while (treeCount < mShortLiveTreeCount)\r
+ {\r
+ int treesIdx = round % lifetimeLen;\r
+ round++;\r
+ for (int i = 0; i < lifetimeLen; i++)\r
+ {\r
+ TreeNode node = new TreeNode();\r
+ shortLiveTrees[treesIdx][i] = node;\r
+ }\r
+ makeTreesShortLive(shortLiveTrees[treesIdx], mBucketSize, myId, nodeCount);\r
+\r
+ for (int i = 0; i < lifetimeLen; i++)\r
+ {\r
+ int idx = (treesIdx - i + lifetimeLen) % lifetimeLen;\r
+ shortLiveTrees[idx][i] = null;\r
+ }\r
+\r
+ if ((mLargeArrayLength[0] > 0) && ((treeCount % mLargeArrayInter[0]) == 0))\r
+ {\r
+ for (int n = 0; n < mLargeArrayNum[0]; n++)\r
+ shortLiveByteArray[allocIdx[0] + n] = new byte[mLargeObjectSize];\r
+ allocIdx[0] += mLargeArrayNum[0];\r
+ }\r
+\r
+ if ((mLargeArrayLength[1] > 0) && ((treeCount % mLargeArrayInter[1]) == 0))\r
+ {\r
+ for (int n = 0; n < mLargeArrayNum[1]; n++)\r
+ shortLiveCharArray[allocIdx[1] + n] = new char[mLargeObjectSize / 2];\r
+ allocIdx[1] += mLargeArrayNum[1];\r
+ }\r
+\r
+ if ((mLargeArrayLength[2] > 0) && ((treeCount % mLargeArrayInter[2]) == 0))\r
+ {\r
+ for (int n = 0; n < mLargeArrayNum[2]; n++)\r
+ shortLiveIntArray[allocIdx[2] + n] = new int[mLargeObjectSize / 4];\r
+ allocIdx[2] += mLargeArrayNum[2];\r
+ }\r
+\r
+ if ((mLargeArrayLength[3] > 0) && ((treeCount % mLargeArrayInter[3]) == 0))\r
+ {\r
+ for (int n = 0; n < mLargeArrayNum[3]; n++)\r
+ shortLiveLongArray[allocIdx[3] + n] = new long[mLargeObjectSize / 8];\r
+ allocIdx[3] += mLargeArrayNum[3];\r
+ }\r
+\r
+ freeArrays(shortLiveByteArray, shortLiveCharArray, shortLiveIntArray,\r
+ shortLiveLongArray, allocIdx, treeCount);\r
+\r
+ treeCount++;\r
+ }\r
+\r
+ if (myId == 0)\r
+ {\r
+ //Debug.getMemoryInfo(memInfo);\r
+ //mHeapFootprint[iter] = memInfo.dalvikPss;\r
+ mHeapFootprint[iter] = (int)GC.GetGCMemoryInfo().HeapSizeBytes;\r
+ //if (getRuntimeStatMethod != null)\r
+ //mHeapBytesAllocated[iter] = (GetRuntimeStat("gc.bytes-allocated") - GetRuntimeStat("gc.bytes-freed")) / 1024;\r
+ //else\r
+ mHeapBytesAllocated[iter] = (GC.GetTotalMemory(false) / 1024);\r
+\r
+ //Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkProgress);\r
+ //m.arg1 = iter + 1;\r
+ //mActivity.getHandler().sendMessage(m);\r
+\r
+ text.Text = (((iter + 1) *100) / mIterNum) + "%";\r
+ Log.Info(mTag, text.Text);\r
+ \r
+ }\r
+ }\r
+\r
+ if (longLiveTreeLink.TreeHead.TreeNode != null\r
+ && longLiveByteArrays[0][100] == (byte)0xff\r
+ && longLiveByteArrays[longLiveArrayCount - 1][200] == (byte)0xff)\r
+ {\r
+ mEndTime[myId] = (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;\r
+ mElapseTime[myId] = mEndTime[myId] - mStartTime[myId];\r
+ return true;\r
+ }\r
+\r
+ return false;\r
+ }\r
+\r
+ public class BenchThread\r
+ {\r
+ private static int myId;\r
+ private static GCTest gcParent;\r
+ public ThreadStart thread;\r
+\r
+ public BenchThread(int id, GCTest parent)\r
+ {\r
+ myId = id;\r
+ gcParent = parent;\r
+ thread += Run;\r
+ }\r
+\r
+ private void Run()\r
+ {\r
+ gcParent.mElapseTime[myId] = 0;\r
+ gcParent.mStartTime[myId] = (long)(DateTime.UtcNow - gcParent.Jan1st1970).TotalMilliseconds;\r
+ try\r
+ {\r
+ if (!gcParent.allocTrace(myId))\r
+ {\r
+ Log.Info(mTag, "Error in thread-" + myId);\r
+ }\r
+ }\r
+ catch (OutOfMemoryException e)\r
+ {\r
+ gcParent.mOutOfMemory = true;\r
+ Log.Info(mTag, "Thread-" + myId + " meets OutOfMemory");\r
+ //Message m = mActivity.GetHandler().ObtainMessage(MainActivity.BenchmarkOutOfMemoryError);\r
+ //m.Arg1 = myId;\r
+ //mActivity.GetHandler().SendMessage(m);\r
+ }\r
+ }\r
+ }\r
+\r
+ public void start()\r
+ {\r
+ /*if (getRuntimeStatMethod == null)\r
+ {\r
+ try\r
+ {\r
+ Type c = Type.GetType("Android.OS.Debug");\r
+ if (c != null)\r
+ getRuntimeStatMethod = c.GetMethod("GetRuntimeStat", new Type[] { typeof(string) });\r
+ }\r
+ catch (TypeLoadException e)\r
+ {\r
+ Log.Warn(mTag, "Cannot find Android.OS.Debug class");\r
+ }\r
+ catch (MissingMethodException e)\r
+ {\r
+ Log.Warn(mTag, "No GetRuntimeStat method in Android.OS.Debug");\r
+ }\r
+ }*/\r
+\r
+ var info1_1 = GC.GetGCMemoryInfo(GCKind.Ephemeral);\r
+ Log.Info(mTag, "Generation: " + info1_1.Generation);\r
+\r
+ var info2_1 = GC.GetGCMemoryInfo();\r
+ Log.Info(mTag, "Generation: " + info2_1.Generation);\r
+\r
+ mElapseTime = new long[mThreadNum];\r
+ mStartTime = new long[mThreadNum];\r
+ mEndTime = new long[mThreadNum];\r
+ mHeapFootprint = new int[mIterNum];\r
+ mHeapBytesAllocated = new long[mIterNum];\r
+ isArt = false;\r
+ //string vmVersion = System.getProperty("java.vm.version");\r
+ //isArt = !string.IsNullOrEmpty(vmVersion) && vmVersion.StartsWith("2");\r
+ //string androidVersion = Build.VERSION.RELEASE;\r
+ //string deviceName = Build.MODEL;\r
+ //string deviceDesc = deviceName + "/" + "android-" + androidVersion + ", runtime: " + (isArt ? "ART" : "Dalvik");\r
+ //mTotalGcCount = info2_1.Index; //GetRuntimeStat("gc.gc-count");\r
+ //mTotalGcTime = (long)info2_1.PauseDurations[0].TotalMilliseconds; //GetRuntimeStat("gc.gc-time");\r
+ //mTotalBlockingGcCount = info1.Index; //GetRuntimeStat("gc.blocking-count");\r
+ //mTotalBlockingGcTime = info1.PauseDurations[0].Milliseconds; //GetRuntimeStat("gc.blocking-gc-time");\r
+ if (isArt)\r
+ {\r
+ mGcCauseCount = new int[] { 0, 0, 0, 0, 0, 0, 0, 0 };\r
+ }\r
+ else\r
+ {\r
+ mGcCauseCount = new int[] { 0, 0, 0, 0 };\r
+ }\r
+\r
+ mWorkloadComplete = false;\r
+ //ClearLogcat();\r
+ //Thread logcat = new Thread(new ThreadStart(readLogcat));\r
+ //logcat.Start();\r
+\r
+ mOutOfMemory = false;\r
+ mTestThreads = new BenchThread[mThreadNum];\r
+ for (int i = 1; i < mThreadNum; i++)\r
+ {\r
+ mTestThreads[i] = new BenchThread(i, this);\r
+ //mThreads[i] = new Thread(mTestThreads[i].thread);\r
+ if (i == 1)\r
+ {\r
+ t1 = new Thread(mTestThreads[i].thread);\r
+ t1.Start();\r
+ }\r
+ else if (i == 2)\r
+ {\r
+ t2 = new Thread(mTestThreads[i].thread);\r
+ t2.Start();\r
+ }\r
+ else if (i == 3)\r
+ {\r
+ t3 = new Thread(mTestThreads[i].thread);\r
+ t3.Start();\r
+ }\r
+ Thread.Sleep(100);\r
+ }\r
+\r
+ mElapseTime[0] = 0;\r
+ mStartTime[0] = (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;\r
+ try\r
+ {\r
+ if (!allocTrace(0))\r
+ {\r
+ Log.Info(mTag, "Error in thread-0");\r
+ }\r
+ }\r
+ catch (OutOfMemoryException e)\r
+ {\r
+ mOutOfMemory = true;\r
+ Log.Info(mTag, "Thread-0 meets OutOfMemory");\r
+\r
+ //Message m = mActivity.GetHandler().ObtainMessage(MainActivity.BenchmarkOutOfMemoryError);\r
+ //m.Arg1 = 0;\r
+ //mActivity.GetHandler().SendMessage(m);\r
+ }\r
+ mEndTime[0] = (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;\r
+ mElapseTime[0] = mEndTime[0] - mStartTime[0];\r
+\r
+ for (int i = 1; i < mThreadNum; i++)\r
+ {\r
+ try\r
+ {\r
+ //mThreads[i].Join();\r
+ if (i == 1)\r
+ {\r
+ t1.Join();\r
+ }\r
+ else if (i == 2)\r
+ {\r
+ t2.Join();\r
+ }\r
+ else if (i == 3)\r
+ {\r
+ t3.Join();\r
+ }\r
+ Thread.Sleep(100);\r
+ }\r
+ catch (ThreadInterruptedException e)\r
+ {\r
+ Log.Info(mTag, "Waiting thread " + i + " finish interrupted by " + e.Message);\r
+ }\r
+ }\r
+ Thread.Sleep(1000);\r
+ mWorkloadComplete = true;\r
+ GC.Collect();\r
+ GC.WaitForPendingFinalizers();\r
+\r
+ try\r
+ {\r
+ //logcat.Join();\r
+ }\r
+ catch (ThreadInterruptedException e)\r
+ {\r
+ Log.Info(mTag, "Waiting logcat finish interrupted by " + e.Message);\r
+ }\r
+ if (mOutOfMemory)\r
+ {\r
+ try\r
+ {\r
+ if (fileOutput != null)\r
+ {\r
+ fileOutput.WriteLine("\nOutOfMemory! Please config profile or " + "Java Runtime and run again!\n");\r
+ fileOutput.Flush();\r
+ fileOutput.Close();\r
+ }\r
+ }\r
+ catch (IOException e)\r
+ {\r
+ Log.Info(mTag, "Cannot write to /tmp/TizenGCTest-result.txt" + e.Message);\r
+ }\r
+ }\r
+ else\r
+ {\r
+ var info1_2 = GC.GetGCMemoryInfo(GCKind.Ephemeral);\r
+ print1(info1_2);\r
+\r
+ var info2_2 = GC.GetGCMemoryInfo();\r
+ print2(info2_2, info2_1);\r
+\r
+ String pauseDesc = "";\r
+ /*String[] causes;\r
+ if (isArt)\r
+ causes = GC_CAUSE_ART;\r
+ else\r
+ causes = GC_CAUSE_DALVIK;\r
+ for (int i = 0; i < causes.Length; i++)\r
+ {\r
+ Log.Info(mTag, mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat");\r
+ gcDesc += "\n" + mGcCauseCount[i] + " GCs for " + causes[i] + " from logcat";\r
+ }*/\r
+ /*for (int i = 0; i < mGcPauseTime.Length; i++)\r
+ {\r
+ String gc_time = "GC-" + i + ": " + mGcCause[i] + ", pause "\r
+ + mGcPauseTime[i] + "ms, total " + mGcTotalTime[i] + "ms";\r
+ pauseDesc += "\n" + gc_time;\r
+ Log.Info(mTag, gc_time);\r
+ }*/\r
+ try\r
+ {\r
+ if (fileOutput != null)\r
+ {\r
+ //fileOutput.WriteLine("\nDevice config:\n\t" + deviceDesc);\r
+ fileOutput.WriteLine("\nDevice config:\n\t");\r
+ //fileOutput.WriteLine(completionTime);\r
+ fileOutput.WriteLine("Heap status after each iteration (footprint, bytes allocated):\n");\r
+ for (int j = 0; j < mIterNum; j++)\r
+ {\r
+ fileOutput.WriteLine("\t" + mHeapFootprint[j] + " kB, " + mHeapBytesAllocated[j] + " kB");\r
+ }\r
+ //fileOutput.WriteLine(gcDesc);\r
+ fileOutput.WriteLine(pauseDesc);\r
+ fileOutput.Flush();\r
+ fileOutput.Close();\r
+ }\r
+ }\r
+ catch (IOException e)\r
+ {\r
+ Log.Info(mTag, "Cannot write to /tmp/TizenGCTest-result.txt " + e.Message);\r
+ }\r
+ /*if (mActivity != null)\r
+ {\r
+ Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkDone);\r
+ Bundle b = new Bundle();\r
+ b.putBoolean(ResultActivity.KEY_VM_TYPE, isArt);\r
+ b.putString("device", deviceDesc);\r
+ b.putLongArray(ResultActivity.KEY_THREAD_COMPLETE_TIME, mElapseTime);\r
+ b.putLong(ResultActivity.KEY_WORKLOAD_COMPLETE_TIME, maxTime);\r
+ b.putLongArray(ResultActivity.KEY_BYTES_LIVING, mHeapBytesAllocated);\r
+ b.putIntArray(ResultActivity.KEY_HEAP_FOOTPRINT, mHeapFootprint);\r
+ b.putFloatArray(ResultActivity.KEY_GC_PAUSE_TIME, mGcPauseTime);\r
+ b.putFloatArray(ResultActivity.KEY_GC_COMPLETION_TIME, mGcTotalTime);\r
+ b.putStringArray(ResultActivity.KEY_GC_CAUSE, mGcCause);\r
+ m.setData(b);\r
+ mActivity.getHandler().sendMessage(m);\r
+ }*/\r
+ }\r
+ mElapseTime = null;\r
+ mHeapFootprint = null;\r
+ mHeapBytesAllocated = null;\r
+ mGcPauseTime = null;\r
+ mGcTotalTime = null;\r
+ mGcCause = null;\r
+\r
+ clearInitData();\r
+ }\r
+\r
+ private void print1(GCMemoryInfo info2)\r
+ {\r
+ mTotalGcCount = info2.Index; //GetRuntimeStat("gc.gc-count") - mTotalGcCount;\r
+ mTotalGcTime = (long)info2.PauseDurations[0].TotalMilliseconds; //GetRuntimeStat("gc.gc-time") - mTotalGcTime;\r
+ //mTotalBlockingGcCount = GetRuntimeStat("gc.blocking-gc-count") - mTotalBlockingGcCount;\r
+ //mTotalBlockingGcTime = info2.PauseDurations[0].Milliseconds - info1.PauseDurations[0].Milliseconds; //GetRuntimeStat("gc.blocking-gc-time") - mTotalBlockingGcTime;\r
+ print(info2);\r
+ }\r
+ private void print2(GCMemoryInfo info2, GCMemoryInfo info1)\r
+ {\r
+ mTotalGcCount = info2.Index - info1.Index; //GetRuntimeStat("gc.gc-count") - mTotalGcCount;\r
+ mTotalGcTime = (long)info2.PauseDurations[0].TotalMilliseconds - (long)info1.PauseDurations[0].TotalMilliseconds; //GetRuntimeStat("gc.gc-time") - mTotalGcTime;\r
+ //mTotalBlockingGcCount = GetRuntimeStat("gc.blocking-gc-count") - mTotalBlockingGcCount;\r
+ //mTotalBlockingGcTime = info2.PauseDurations[0].Milliseconds - info1.PauseDurations[0].Milliseconds; //GetRuntimeStat("gc.blocking-gc-time") - mTotalBlockingGcTime;\r
+ print(info2);\r
+ }\r
+\r
+ private void print(GCMemoryInfo info2)\r
+ {\r
+ long maxTime = 0;\r
+ //string completionTime = "";\r
+ for (int i = 0; i < mThreadNum; i++)\r
+ {\r
+ if (maxTime < mElapseTime[i])\r
+ {\r
+ maxTime = mElapseTime[i];\r
+ }\r
+ Log.Info(mTag, "Thread-" + i + " completion time: " + mElapseTime[i].ToString() + "ms");\r
+ //completionTime += "Thread-" + i + " completion time: " + mElapseTime[i].ToString() + "ms\n";\r
+ }\r
+\r
+ String totalTime = "TizenGCTest is done by " + mThreadNum\r
+ + " threads. Completion time is " + maxTime + "ms";\r
+ Log.Info(mTag, totalTime);\r
+ //completionTime += totalTime + "\n";\r
+ //String gcDesc = "Total GC count: " + mTotalGcCount;\r
+ //gcDesc += "\nTotal GC time: " + mTotalGcTime + "ms";\r
+ //gcDesc += "\nTotal Blocking GC count: " + mTotalBlockingGcCount;\r
+ //gcDesc += "\nTotal Blocking GC time: " + mTotalBlockingGcTime + "ms";\r
+ Log.Info(mTag, "Total GC count: " + mTotalGcCount);\r
+ Log.Info(mTag, "Total GC time: " + mTotalGcTime + "ms");\r
+ //Log.Info(mTag, "Total Blocking GC count: " + mTotalBlockingGcCount);\r
+ //Log.Info(mTag, "Total Blocking GC time: " + mTotalBlockingGcTime + "ms");\r
+\r
+ long totalAfter = 0;\r
+ long totalBefore = 0;\r
+ foreach (var ginfo in info2.GenerationInfo)\r
+ {\r
+ totalAfter += ginfo.SizeAfterBytes;\r
+ totalBefore += ginfo.SizeBeforeBytes;\r
+ }\r
+ Log.Info(mTag, "HeapSizeBytes: " + info2.HeapSizeBytes + ", " + GC.GetTotalMemory(false) + " / GenInfo After : " + totalAfter + ", Before : " + totalBefore);\r
+ Log.Info(mTag, "TotalCommittedBytes: " + info2.TotalCommittedBytes);\r
+ Log.Info(mTag, "Generation: " + info2.Generation);\r
+ Log.Info(mTag, "TotalAvailableMemoryBytes: " + info2.TotalAvailableMemoryBytes);\r
+ Log.Info(mTag, "FinalizationPendingCount: " + info2.FinalizationPendingCount);\r
+ Log.Info(mTag, "Concurrent: " + info2.Concurrent);\r
+ Log.Info(mTag, "Compacted: " + info2.Compacted);\r
+ Log.Info(mTag, "Index: " + info2.Index);\r
+ Log.Info(mTag, "FragmentedBytes: " + info2.FragmentedBytes);\r
+ Log.Info(mTag, "HighMemoryLoadThresholdBytes: " + info2.HighMemoryLoadThresholdBytes);\r
+ Log.Info(mTag, "MemoryLoadBytes: " + info2.MemoryLoadBytes);\r
+ }\r
+\r
+ public void stop()\r
+ {\r
+ }\r
+\r
+ private void ClearLogcat()\r
+ {\r
+ try\r
+ {\r
+ Process process = Process.Start(new ProcessStartInfo("dlogutil", "-c"));\r
+ try\r
+ {\r
+ process.WaitForExit();\r
+ }\r
+ catch (ThreadInterruptedException e)\r
+ {\r
+ Log.Error(mTag, "Clear logcat fails, interrupted by " + e.Message);\r
+ }\r
+ Log.Info(mTag, "Clear logcat before workload running");\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ Log.Error(mTag, "Clear logcat fails, " + e.Message);\r
+ }\r
+ }\r
+\r
+ private void readLogcat()\r
+ {\r
+ string cmd = "dlogutil TizenGCTest STDOUT STDERR";\r
+ List<float> gcPauseTimeList = new List<float>();\r
+ List<float> gcTotalTimeList = new List<float>();\r
+ List<string> gcCauseList = new List<string>();\r
+ int loggerGcCount = 0;\r
+ try\r
+ {\r
+ Process process = Process.Start(new ProcessStartInfo("cmd", "/c " + cmd) { RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false });\r
+ Stream inStream = process.StandardOutput.BaseStream;\r
+ Stream errorStream = process.StandardError.BaseStream;\r
+ int error = errorStream.ReadByte();\r
+ if (error > 0)\r
+ {\r
+ byte[] errorMsg = new byte[error];\r
+ errorStream.Read(errorMsg, 0, error);\r
+ Log.Info(mTag, "executing logcat return error message: " + Encoding.UTF8.GetString(errorMsg));\r
+ }\r
+ StreamReader inReader = new StreamReader(inStream);\r
+ string line;\r
+ while (!mWorkloadComplete && (line = inReader.ReadLine()) != null)\r
+ {\r
+ if (mWorkloadComplete)\r
+ break;\r
+\r
+ int idx = line.IndexOf(": ");\r
+ if (idx == -1)\r
+ continue;\r
+ line = line.Substring(idx + 2);\r
+ bool isGCLog = false;\r
+ String gcCause = "";\r
+ if (isArt)\r
+ {\r
+ for (int i = 0; i < GC_CAUSE_ART.Length; i++)\r
+ {\r
+ if ((line.Contains("mark sweep") || line.Contains("marksweep")\r
+ || line.Contains("mark compact"))\r
+ && line.StartsWith(GC_CAUSE_ART[i]))\r
+ {\r
+ isGCLog = true;\r
+ mGcCauseCount[i]++;\r
+ idx = line.IndexOf(" GC ");\r
+ if (idx > 0)\r
+ gcCause = line.Substring(0, idx);\r
+ else\r
+ {\r
+ Log.Info(mTag, "Error: cannot find ' GC ' from this log, " + line);\r
+ continue;\r
+ }\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ else\r
+ {\r
+ for (int i = 0; i < GC_CAUSE_DALVIK.Length; i++)\r
+ {\r
+ if (line.StartsWith(GC_CAUSE_DALVIK[i]))\r
+ {\r
+ isGCLog = true;\r
+ mGcCauseCount[i]++;\r
+ gcCause = GC_CAUSE_DALVIK[i];\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if (!isGCLog)\r
+ continue;\r
+ loggerGcCount++;\r
+\r
+ int idx0 = line.IndexOf("paused ");\r
+ int idx1 = line.IndexOf(" total ");\r
+ if (idx0 == -1 || idx1 == -1)\r
+ {\r
+ Log.Info(mTag, "Cannot find pause or total completion time from the GC log "\r
+ + line);\r
+ continue;\r
+ }\r
+\r
+ String pauseTimeStr = line.Substring(idx0 + 7, idx1);\r
+ String totalTimeStr = line.Substring(idx1 + 7);\r
+ float completeTime = 0.0f;\r
+ float pauseTime = 0.0f;\r
+ idx = totalTimeStr.IndexOf("ms");\r
+ int timeToSec = 1000;\r
+ if (idx == -1)\r
+ {\r
+ idx = totalTimeStr.IndexOf("us");\r
+ timeToSec = 1000000;\r
+ }\r
+ if (idx == -1)\r
+ {\r
+ idx = totalTimeStr.IndexOf("s");\r
+ timeToSec = 1;\r
+ }\r
+ if (idx == -1)\r
+ {\r
+ Log.Info(mTag, "Cannot identify total complete time format, " + line);\r
+ continue;\r
+ }\r
+ completeTime = float.Parse(totalTimeStr.Substring(0, idx)) * 1000 / timeToSec;\r
+ string[] pauseTimes = pauseTimeStr.Split(new string[] { "+ ", ", " }, StringSplitOptions.RemoveEmptyEntries);\r
+ for (int i = 0; i < pauseTimes.Length; i++)\r
+ {\r
+ string tmp = pauseTimes[i];\r
+ idx = tmp.IndexOf("ms");\r
+ if (idx > 0)\r
+ {\r
+ pauseTime += float.Parse(tmp.Substring(0, idx));\r
+ }\r
+ else\r
+ {\r
+ idx = tmp.IndexOf("us");\r
+ if (idx > 0)\r
+ {\r
+ pauseTime += float.Parse(tmp.Substring(0, idx)) / 1000;\r
+ }\r
+ else\r
+ {\r
+ Log.Info(mTag, "Cannot identify pause time format, " + line);\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ gcPauseTimeList.Add(pauseTime);\r
+ gcTotalTimeList.Add(completeTime);\r
+ gcCauseList.Add(gcCause);\r
+ }\r
+ errorStream.Close();\r
+ inReader.Close();\r
+ process.Kill();\r
+ Log.Info(mTag, "workload complete, stop reading logcat");\r
+ mGcTotalTime = new float[loggerGcCount];\r
+ mGcPauseTime = new float[loggerGcCount];\r
+ mGcCause = new String[loggerGcCount];\r
+ for (int i = 0; i < gcPauseTimeList.Count; i++)\r
+ {\r
+ mGcTotalTime[i] = gcTotalTimeList[i];\r
+ mGcPauseTime[i] = gcPauseTimeList[i];\r
+ mGcCause[i] = gcCauseList[i];\r
+ }\r
+ }\r
+ catch (OutOfMemoryException e)\r
+ {\r
+ mOutOfMemory = true;\r
+ Log.Info(mTag, "logcat thread meets OutOfMemory");\r
+ //Message m = mActivity.getHandler().obtainMessage(MainActivity.BenchmarkOutOfMemoryError);\r
+ //m.arg1 = -1;\r
+ //mActivity.getHandler().sendMessage(m);\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ Log.Info(mTag, "Cannot run logcat " + e.Message);\r
+ }\r
+ gcPauseTimeList.Clear();\r
+ gcPauseTimeList = null;\r
+ gcTotalTimeList.Clear();\r
+ gcTotalTimeList = null;\r
+ gcCauseList.Clear();\r
+ gcCauseList = null;\r
+ Log.Info(mTag, "logcat done");\r
+ }\r
+\r
+ //private static MethodInfo getRuntimeStatMethod = null;\r
+ /*private long GetRuntimeStat(string statName)\r
+ {\r
+ if (getRuntimeStatMethod == null)\r
+ {\r
+ return 0;\r
+ }\r
+ string valueStr;\r
+ try\r
+ {\r
+ valueStr = (string)getRuntimeStatMethod.Invoke(null, new object[] { statName });\r
+ }\r
+ catch (Exception e)\r
+ {\r
+ Log.Warn(mTag, "Failed to invoke GetRuntimeStat");\r
+ return 0;\r
+ }\r
+ if (valueStr != null)\r
+ {\r
+ return long.Parse(valueStr);\r
+ }\r
+ return 0;\r
+ }*/\r
+ }\r
+}\r
--- /dev/null
+using System;\r
+using System.Collections;\r
+using System.Collections.Generic;\r
+using System.IO;\r
+using System.Linq;\r
+using System.Text;\r
+using System.Threading.Tasks;\r
+using System.Xml;\r
+using Tizen.Content.MediaContent;\r
+using Tizen;\r
+using static Tizen.NUI.Shader;\r
+using static TizenGCTest.Profile;\r
+using System.Xml.Linq;\r
+using System.Text.RegularExpressions;\r
+using Tizen.Pims.Contacts.ContactsViews;\r
+using static Tizen.Applications.ApplicationInfoFilter;\r
+\r
+namespace TizenGCTest\r
+{\r
+ public class Profile\r
+ {\r
+ private const String mTag = "TizenGCTest";\r
+ public class ProfileData\r
+ {\r
+ private int mId;\r
+ private string mName;\r
+ private int mTotalSize;\r
+ private int mBucketSize;\r
+ private int mLosThreshold;\r
+ private float[] mSizeDist;\r
+ private float[] mLosElementDist;\r
+ private float[][] mLifetime;\r
+ private float[] mLifetime2;\r
+ private bool mThreadMode;\r
+ private int mThreadNum;\r
+ private int mIterationNum;\r
+\r
+ public ProfileData(int id, string name)\r
+ {\r
+ mId = id;\r
+ mName = name;\r
+ }\r
+\r
+ public int GetId()\r
+ {\r
+ return mId;\r
+ }\r
+\r
+ public string GetName()\r
+ {\r
+ return mName;\r
+ }\r
+\r
+ public int GetTotalSize()\r
+ {\r
+ return mTotalSize;\r
+ }\r
+\r
+ public int GetBucketSize()\r
+ {\r
+ return mBucketSize;\r
+ }\r
+\r
+ public int GetLosThreshold()\r
+ {\r
+ return mLosThreshold;\r
+ }\r
+\r
+ public float[] GetSizeDistribution()\r
+ {\r
+ return mSizeDist;\r
+ }\r
+\r
+ public float[] GetLosElementDist()\r
+ {\r
+ return mLosElementDist;\r
+ }\r
+\r
+ public float[][] GetLifetime()\r
+ {\r
+ return mLifetime;\r
+ }\r
+\r
+ public float[] GetLifetime2()\r
+ {\r
+ return mLifetime2;\r
+ }\r
+\r
+ public bool GetThreadMode()\r
+ {\r
+ return mThreadMode;\r
+ }\r
+\r
+ public int GetThreadNum()\r
+ {\r
+ return mThreadMode ? 1 : mThreadNum;\r
+ }\r
+\r
+ public int GetIterationNum()\r
+ {\r
+ return mIterationNum;\r
+ }\r
+\r
+ public void SetName(string name)\r
+ {\r
+ mName = name;\r
+ }\r
+\r
+ public void SetTotalSize(int totalSize)\r
+ {\r
+ mTotalSize = totalSize;\r
+ }\r
+\r
+ public void SetBucketSize(int bucketSize)\r
+ {\r
+ mBucketSize = bucketSize;\r
+ }\r
+\r
+ public void SetLosThreshold(int losThreshold)\r
+ {\r
+ mLosThreshold = losThreshold;\r
+ }\r
+\r
+ public void SetSizeDistribution(float[] sizeDist)\r
+ {\r
+ mSizeDist = sizeDist;\r
+ }\r
+\r
+ public void SetLosElementDist(float[] losElementDist)\r
+ {\r
+ mLosElementDist = losElementDist;\r
+ }\r
+\r
+ public void SetLifetime(float[][] lifetime)\r
+ {\r
+ mLifetime = lifetime;\r
+ }\r
+\r
+ public void SetLifetime2(float[] lifetime)\r
+ {\r
+ mLifetime2 = lifetime;\r
+ }\r
+\r
+ public void SetThreadMode(bool singleThread)\r
+ {\r
+ mThreadMode = singleThread;\r
+ }\r
+\r
+ public void SetThreadNum(int threadNum)\r
+ {\r
+ mThreadNum = mThreadMode ? 1 : threadNum;\r
+ }\r
+\r
+ public void SetIterationNum(int iterationNum)\r
+ {\r
+ mIterationNum = iterationNum;\r
+ }\r
+ }\r
+\r
+ private static Profile instance_ = null;\r
+ public bool mInit = false;\r
+ int mCurrentProfileId = -1;\r
+ public List<ProfileData> mData = null;\r
+\r
+ private Profile()\r
+ {\r
+ mCurrentProfileId = -1;\r
+ mInit = false;\r
+ }\r
+\r
+ public static Profile getInstance()\r
+ {\r
+ if (instance_ == null)\r
+ {\r
+ instance_ = new Profile();\r
+ }\r
+ return instance_;\r
+ }\r
+\r
+ private bool InitProfileData(String input)\r
+ {\r
+ ProfileData newProfile = null;\r
+ XmlReaderSettings settings = new XmlReaderSettings();\r
+ settings.DtdProcessing = DtdProcessing.Parse;\r
+ XmlReader parser = XmlReader.Create(input, settings);\r
+\r
+ try\r
+ {\r
+ float[] floatValues = null;\r
+ string itemName, name;\r
+ int idx0 = -1, idx1 = 0;\r
+ while (parser.Read())\r
+ {\r
+ switch (parser.NodeType)\r
+ {\r
+ case XmlNodeType.Element:\r
+\r
+ name = parser.Name;\r
+ if (name.Equals("profile"))\r
+ {\r
+ newProfile = new ProfileData(int.Parse(parser.GetAttribute(0)), parser.GetAttribute(1));\r
+ //Log.Info(mTag, "profile : " + parser.GetAttribute(0) + " " + parser.GetAttribute(1));\r
+ }\r
+ else if (name.Equals("item"))\r
+ {\r
+ itemName = parser.GetAttribute(0);\r
+ if (itemName.Equals("total_size"))\r
+ {\r
+ newProfile.SetTotalSize(int.Parse(parser.ReadElementContentAsString()));\r
+ //Log.Info(mTag, "item - total_size : " + newProfile.GetTotalSize());\r
+ }\r
+ else if (itemName.Equals("bucket_size"))\r
+ {\r
+ newProfile.SetBucketSize(int.Parse(parser.ReadElementContentAsString()));\r
+ //Log.Info(mTag, "item - bucket_size : " + newProfile.GetBucketSize());\r
+ }\r
+ else if (itemName.Equals("los_threshold"))\r
+ {\r
+ newProfile.SetLosThreshold(int.Parse(parser.ReadElementContentAsString()));\r
+ //Log.Info(mTag, "item - los_threshold : " + newProfile.GetLosThreshold());\r
+ }\r
+ else if (itemName.Equals("thread-mode"))\r
+ {\r
+ newProfile.SetThreadMode(int.Parse(parser.ReadElementContentAsString()) == 1);\r
+ //Log.Info(mTag, "item - thread-mode : " + newProfile.GetThreadMode());\r
+ }\r
+ else if (itemName.Equals("thread-num"))\r
+ {\r
+ newProfile.SetThreadNum(int.Parse(parser.ReadElementContentAsString()));\r
+ //Log.Info(mTag, "item - thread-num : " + newProfile.GetThreadNum());\r
+ }\r
+ else if (itemName.Equals("iteration-times"))\r
+ {\r
+ newProfile.SetIterationNum(int.Parse(parser.ReadElementContentAsString()));\r
+ //Log.Info(mTag, "item - iteration-times : " + newProfile.GetIterationNum());\r
+ }\r
+ }\r
+ else if (name.Equals("float-array-2d"))\r
+ {\r
+ if (parser.GetAttribute(0).Equals("lifetime"))\r
+ {\r
+ newProfile.SetLifetime(new float[int.Parse(parser.GetAttribute(1))][]);\r
+ idx0 = 0;\r
+ //Log.Info(mTag, "float-array-2d - lifetime : " + parser.GetAttribute(1));\r
+ }\r
+ }\r
+ else if (name.Equals("float-array"))\r
+ {\r
+ itemName = parser.GetAttribute(0);\r
+ if (itemName.Equals("size_dist"))\r
+ {\r
+ newProfile.SetSizeDistribution(new float[int.Parse(parser.GetAttribute(1))]);\r
+ floatValues = newProfile.GetSizeDistribution();\r
+ //Log.Info(mTag, "float-array - size_dist : " + floatValues.Length);\r
+ }\r
+ else if (itemName.Equals("los_element_dist"))\r
+ {\r
+ newProfile.SetLosElementDist(new float[int.Parse(parser.GetAttribute(1))]);\r
+ floatValues = newProfile.GetLosElementDist();\r
+ //Log.Info(mTag, "float-array - los_element_dist : " + floatValues.Length);\r
+ }\r
+ else if (idx0 >= 0)\r
+ {\r
+ float[][] lifetime = null;\r
+ lifetime = new float[int.Parse(parser.GetAttribute(1))][];\r
+ newProfile.SetLifetime(lifetime);\r
+ //floatValues = newProfile.GetLifetime()[idx0];\r
+ //Log.Info(mTag, "float-array - size_dist : " + floatValues.Length);\r
+\r
+ float[] lifetime2 = null;\r
+ lifetime2 = new float[int.Parse(parser.GetAttribute(1))];\r
+ newProfile.SetLifetime2(lifetime2);\r
+ floatValues = newProfile.GetLifetime2();\r
+ idx0++;\r
+ }\r
+ idx1 = 0;\r
+ }\r
+ else if (name.Equals("value"))\r
+ {\r
+ if (floatValues == null)\r
+ {\r
+ Log.Info(mTag, "error in parsing profile.xml");\r
+ return false;\r
+ }\r
+ floatValues[idx1++] = float.Parse(parser.ReadElementContentAsString());\r
+ //foreach (var value in floatValues)\r
+ //if (value != 0)\r
+ //Log.Info(mTag, "value : " + value);\r
+ }\r
+ break;\r
+ case XmlNodeType.EndElement:\r
+ name = parser.Name;\r
+ if (name.Equals("profile"))\r
+ {\r
+ mData = new List<ProfileData>\r
+ {\r
+ newProfile\r
+ };\r
+ }\r
+ else if (name.Equals("float-array-2d"))\r
+ {\r
+ idx0 = -1;\r
+ }\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ catch (XmlException e)\r
+ {\r
+ Log.Error(mTag, e.StackTrace);\r
+ return false;\r
+ }\r
+ catch (FormatException e)\r
+ {\r
+ Log.Error(mTag, e.StackTrace);\r
+ return false;\r
+ }\r
+ catch (IOException e)\r
+ {\r
+ Log.Error(mTag, e.StackTrace);\r
+ return false;\r
+ }\r
+\r
+ return true;\r
+ }\r
+\r
+ public ProfileData GetProfile(string name)\r
+ {\r
+ if (!mInit)\r
+ return null;\r
+ for (int i = 0; i < mData.Count; i++)\r
+ {\r
+ ProfileData data = mData[i];\r
+ if (data.GetName() == name)\r
+ {\r
+ mCurrentProfileId = data.GetId();\r
+ return data;\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ public bool ParseProfileData(String rawProfileFile)\r
+ {\r
+ mInit = InitProfileData(rawProfileFile);\r
+ return mInit;\r
+ }\r
+\r
+ public bool Initialized()\r
+ {\r
+ return mInit;\r
+ }\r
+\r
+ public void SetCurrentProfileData(string name)\r
+ {\r
+ if (!mInit)\r
+ return;\r
+ for (int i = 0; i < mData.Count; i++)\r
+ {\r
+ ProfileData data = mData[i];\r
+ if (data.GetName() == name)\r
+ {\r
+ mCurrentProfileId = data.GetId();\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ public ProfileData GetCurrentProfileData()\r
+ {\r
+ if (!mInit)\r
+ return null;\r
+ for (int i = 0; i < mData.Count; i++) {\r
+ ProfileData data = mData[i];\r
+ if (mData[i].GetId() == mCurrentProfileId)\r
+ return data;\r
+ }\r
+ return null;\r
+ }\r
+ }\r
+}\r
--- /dev/null
+using System;\r
+using System.Threading;\r
+using Tizen;\r
+using Tizen.NUI;\r
+using Tizen.NUI.Components;\r
+using Tizen.NUI.BaseComponents;\r
+using static TizenGCTest.Profile;\r
+\r
+namespace TizenGCTest\r
+{\r
+ class Program : NUIApplication\r
+ {\r
+ private const String mTag = "TizenGCTest";\r
+ private Profile mProfile = null;\r
+\r
+ protected override void OnCreate()\r
+ {\r
+ base.OnCreate();\r
+ Initialize();\r
+\r
+ mProfile = Profile.getInstance();\r
+\r
+ mProfile.ParseProfileData("/opt/usr/globalapps/org.tizen.example.TizenGCTest/res/profile.xml");\r
+\r
+ if (mProfile.Initialized())\r
+ {\r
+ string[] names = new string[mProfile.mData.Count];\r
+ for (int i = 0; i < mProfile.mData.Count; i++)\r
+ {\r
+ ProfileData d = mProfile.mData[i];\r
+ names[i] = d.GetName();\r
+ }\r
+ mProfile.SetCurrentProfileData("default");\r
+ }\r
+ else\r
+ {\r
+ Log.Info(mTag, "Cannot get profile data");\r
+ }\r
+\r
+ Log.Info(mTag, "TizenGCTest Start!!");\r
+ StartGC();\r
+ }\r
+\r
+\r
+ public void StartGC()\r
+ {\r
+ ProfileData profileData = mProfile.GetCurrentProfileData();\r
+ if (profileData == null)\r
+ {\r
+ Log.Error(mTag, "no profile data?!");\r
+ return;\r
+ }\r
+ GCTest gctest = new GCTest(profileData.GetTotalSize(), profileData.GetBucketSize(),\r
+ profileData.GetLosThreshold(), profileData.GetSizeDistribution(),\r
+ profileData.GetLifetime(), profileData.GetLosElementDist(),\r
+ profileData.GetThreadMode(), profileData.GetThreadNum(),\r
+ profileData.GetIterationNum());\r
+\r
+ GC.Collect();\r
+ GC.WaitForPendingFinalizers();\r
+\r
+ //var mRunning = true;\r
+ var worker = new Thread(() =>\r
+ {\r
+ gctest.start();\r
+ });\r
+ worker.Start();\r
+\r
+ }\r
+\r
+ void Initialize()\r
+ {\r
+ Window.Instance.KeyEvent += OnKeyEvent;\r
+\r
+ TextLabel text = new TextLabel("Hello Tizen NUI World");\r
+ text.HorizontalAlignment = HorizontalAlignment.Center;\r
+ text.VerticalAlignment = VerticalAlignment.Center;\r
+ text.TextColor = Color.Blue;\r
+ text.PointSize = 12.0f;\r
+ text.HeightResizePolicy = ResizePolicyType.FillToParent;\r
+ text.WidthResizePolicy = ResizePolicyType.FillToParent;\r
+ Window.Instance.GetDefaultLayer().Add(text);\r
+ \r
+ }\r
+\r
+ public void OnKeyEvent(object sender, Window.KeyEventArgs e)\r
+ {\r
+ if (e.Key.State == Key.StateType.Down && (e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))\r
+ {\r
+ Exit();\r
+ }\r
+ }\r
+\r
+ static void Main(string[] args)\r
+ {\r
+ var app = new Program();\r
+ app.Run(args);\r
+ }\r
+ }\r
+}\r
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+ <PropertyGroup>\r
+ <OutputType>Exe</OutputType>\r
+ <TargetFramework>net6.0-tizen</TargetFramework>\r
+ </PropertyGroup>\r
+\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">\r
+ <DebugType>portable</DebugType>\r
+ </PropertyGroup>\r
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">\r
+ <DebugType>None</DebugType>\r
+ </PropertyGroup>\r
+ <ItemGroup>\r
+ <Content Include="res\profile.xml" />\r
+ </ItemGroup>\r
+ <ItemGroup>\r
+ <Folder Include="lib\" />\r
+ </ItemGroup>\r
+\r
+</Project>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>\r
+<profile id="0" name="default">\r
+ <item name="total_size">100</item>\r
+ <item name="bucket_size">1</item>\r
+ <item name="los_threshold">12</item>\r
+ <float-array name="size_dist" count="7">\r
+ <value>0.0436</value>\r
+ <value>0.5465</value>\r
+ <value>0.2103</value>\r
+ <value>0.1499</value>\r
+ <value>0.0275</value>\r
+ <value>0.0125</value>\r
+ <value>0.0097</value>\r
+ </float-array>\r
+ <float-array-2d name="lifetime" count="7">\r
+ <float-array name="16b" count="4">\r
+ <value>0.0865</value>\r
+ <value>0.5404</value>\r
+ <value>0.2887</value>\r
+ <value>0.0865</value>\r
+ </float-array>\r
+ <float-array name="32b" count="4">\r
+ <value>0.0469</value>\r
+ <value>0.7724</value>\r
+ <value>0.1460</value>\r
+ <value>0.0346</value>\r
+ </float-array>\r
+ <float-array name="64b" count="4">\r
+ <value>0.1154</value>\r
+ <value>0.5982</value>\r
+ <value>0.1880</value>\r
+ <value>0.0984</value>\r
+ </float-array>\r
+ <float-array name="128b" count="4">\r
+ <value>0.0662</value>\r
+ <value>0.7851</value>\r
+ <value>0.1077</value>\r
+ <value>0.0411</value>\r
+ </float-array>\r
+ <float-array name="256b" count="4">\r
+ <value>0.0520</value>\r
+ <value>0.8778</value>\r
+ <value>0.0503</value>\r
+ <value>0.0198</value>\r
+ </float-array>\r
+ <float-array name="512b" count="4">\r
+ <value>0.1628</value>\r
+ <value>0.7137</value>\r
+ <value>0.0821</value>\r
+ <value>0.0414</value>\r
+ </float-array>\r
+ <float-array name="los" count="4">\r
+ <value>0.0923</value>\r
+ <value>0.7117</value>\r
+ <value>0.1769</value>\r
+ <value>0.0192</value>\r
+ </float-array>\r
+ </float-array-2d>\r
+ <float-array name="los_element_dist" count="4">\r
+ <value>0.90</value>\r
+ <value>0.07</value>\r
+ <value>0.02</value>\r
+ <value>0.01</value>\r
+ </float-array>\r
+ <item name="thread-mode">0</item>\r
+ <item name="thread-num">0</item>\r
+ <item name="iteration-times">10</item>\r
+</profile>\r
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns="http://tizen.org/ns/packages" api-version="9.0" package="org.tizen.example.TizenGCTest" version="1.0.0">
+ <profile name="common" />
+ <ui-application appid="org.tizen.example.TizenGCTest"
+ exec="TizenGCTest.dll"
+ type="dotnet-nui"
+ multiple="false"
+ taskmanage="true"
+ nodisplay="false"
+ launch_mode="single"
+ api-version="12">
+ <label>TizenGCTest</label>
+ <icon>TizenGCTest.png</icon>
+ <metadata key="http://tizen.org/metadata/prefer_dotnet_aot" value="true" />
+ </ui-application>
+</manifest>
--- /dev/null
+# csproj file path
+csproj_file: TizenGCTest.csproj
+
+# files monitored for dirty/modified status
+files:
+ - TizenGCTest.csproj
+ - TizenGCTest.cs
+ - tizen-manifest.xml
+ - shared/res/TizenGCTest.png
\ No newline at end of file
--- /dev/null
+#!/usr/bin/env python3
+import argparse, ast, math, os, re, statistics, subprocess, sys, threading
+from time import sleep
+from datetime import datetime
+
+# Global values.
+predefined_list = ["org.tizen.example.AppCommon.Tizen.Mobile",
+ "org.tizen.example.ApplicationControl.Tizen.Mobile",
+ "org.tizen.example.Puzzle.Tizen.Mobile",
+ "org.tizen.example.Settings.Tizen.Mobile",
+ "org.tizen.example.System_info.Tizen.Mobile",
+ "org.tizen.example.Xamarin.Hello.F_HUB.Tizen"]
+logfile = None
+dlogs = list()
+
+# Print text to a file.
+def log(text):
+ if not logfile:
+ return
+
+ with open(logfile, 'a') as f:
+ d = f"\n[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] "
+ f.write(d + d.join(str(text).splitlines()))
+
+# Execute a command and return the output as a string.
+def cmd(command):
+ return subprocess.run(command.split(), encoding='utf-8', stdout=subprocess.PIPE).stdout
+
+# Launch an application and return its pid.
+def launch(app_id, serial, standalone=False, pause=10):
+ raw = cmd(f"sdb -s {serial} shell app_launcher {'-e' if standalone else '-s'} {app_id}")
+ if 'successfully launched pid' not in raw:
+ raise Exception(f'Unable to launch {app_id}. Make sure the application is installed on the target device.')
+ sleep(pause)
+ return raw[raw.index('pid') + 6:raw.index('with') - 1]
+
+# Terminate apps if running.
+def terminate(app_ids, serial, pause=0):
+ for app_id in app_ids:
+ cmd(f'sdb -s {serial} shell app_launcher -t {app_id}')
+ # Check if we are failing due to an unhandled exception.
+ if sys.exc_info()[0] is None:
+ sleep(pause)
+
+# Colorize the text.
+def color(text):
+ return f'\033[93m{text}\033[0m' if os.name == 'posix' else text
+
+# Entry point for the dlog thread.
+def dlogger(serial):
+ cmd(f'sdb -s {serial} dlog -c')
+
+ command = f'sdb -s {serial} dlog -v time AUL LAUNCH'
+ with subprocess.Popen(command.split(), encoding='utf-8', stdout=subprocess.PIPE) as p:
+ for line in p.stdout:
+ dlogs.append(line.strip())
+
+# Filter dlogs with conditions.
+def read_dlogs(target=None, pid=0, grep:str=None):
+ ret = list()
+
+ for line in dlogs:
+ split = line.split(')')[0]
+ if target and target not in split:
+ continue
+ elif pid != 0 and str(pid) not in split.split('(')[1]:
+ continue
+ elif grep is None or re.search(grep, line):
+ ret.append(line)
+
+ return ret
+
+# Return a UNIX time in milliseconds from a formatted dlog text.
+def time_in_millis(text):
+ t = text.split()[1]
+ h = int(t[0:2])
+ m = int(t[3:5])
+ s = int(t[6:8])
+ millis = int(t[9:12])
+ offset = int(t[12:15])
+ return ((h - offset) * 3600 + m * 60 + s) % 86400 * 1000 + millis
+
+# Parse time values.
+def parse_stime(ret, app_id):
+ # Detect the launch request.
+ lines = read_dlogs('AUL', grep=f'[Rr]equest cmd\(0:APP_START\)( )?: appid\({app_id}\)')
+ if len(lines) == 0:
+ log(f'Error: parse_stime for app_id={app_id} has failed. No launch request.')
+ return
+ queued = time_in_millis(lines[-1])
+
+ # Get the Launching:done notification.
+ lines = read_dlogs('LAUNCH', grep=f'{app_id}:Application:Launching:done')
+ if len(lines) == 0:
+ log(f'Error: parse_stime for app_id={app_id} has failed. Unable to detect the app launch completion.')
+ return
+ done = time_in_millis(lines[-1])
+
+ ret[app_id]['stime'][-1] = done - queued
+ log(f"{app_id:40.40} {done - queued:8} ms (Launch)")
+
+# Parse memps to get PSS and RSS.
+def parse_memps(ret, serial, pid_map:map):
+ # pid_map is a map of {pid: app_id}.
+ raw = ''
+ app_ids = [ai for ai in pid_map.values() if len(ai) > 0]
+ retry_cnt = 3
+ while not all(ai in raw for ai in app_ids) and retry_cnt > 0:
+ raw = cmd(f'sdb -s {serial} shell memps -v')
+ retry_cnt -= 1
+ sleep(1)
+
+ # len(lines) == len(app_ids) if successful.
+ lines = [l for l in raw.splitlines() if any(ai in l for ai in app_ids)]
+ if len(lines) < len(app_ids):
+ log(f'Warning: Failed to get one or more app ids from memps.\n{lines}')
+
+ for line in lines:
+ if any(ai in line for ai in app_ids):
+ split = [x for x in line.split() if x]
+ ai = pid_map[split[0]] # from pid
+ shar = float(split[1]) + float(split[2])
+ prvt = float(split[3]) + float(split[4])
+ swap = float(split[10])
+ rss = shar + prvt + swap
+ ret[ai]['pss'][-1] = float(split[6])
+ ret[ai]['rss'][-1] = rss
+ ret[ai]['shar'][-1] = shar
+ ret[ai]['prvt'][-1] = prvt
+ ret[ai]['swap'][-1] = swap
+ ret[ai]['file'][-1] = float(split[1]) + float(split[3])
+ ret[ai]['dirt'][-1] = float(split[2]) + float(split[4])
+ log(f'{ai:40.40} {float(split[6]):8.0f} KB (PSS), {rss:8.0f} KB (RSS)')
+
+# Reduce the dimensionality of the given data.
+def trim(data, recent=False):
+ # If recent is True, only the latest (intermediate) values are taken.
+ # Otherwise, we first remove outlying values and then compute averages.
+ ret = dict((ai, dict()) for ai in data.keys()) # Create a new data structure.
+ for ai, d in data.items(): # d is a dictionary.
+ # Initialize the metadata.
+ ret[ai]['n'] = len(data[ai]['stime']) # N (original length)
+ ret[ai]['na'] = dict((k, 0) for k in d.keys()) # Zero-initialized N/A counts
+ ret[ai]['stdev'] = dict((k, 0) for k in d.keys()) # Zero-initialized standard deviations
+ for key, val in d.items():
+ if recent:
+ ret[ai][key] = val[-1]
+ else:
+ # Only swaps can be zero by nature. Otherwise, use only non-zero values.
+ v = val if key == 'swap' else [x for x in val if x > 0]
+ mean = statistics.mean(v) if len(v) > 0 else 0
+ stdev = statistics.stdev(v) if len(v) > 1 else 0
+ # Use sqrt(mean) as a correction threshold to discard outlying values.
+ cv = v if stdev <= math.sqrt(mean) else [x for x in v if (x >= mean - stdev) and (x <= mean + stdev)]
+ ret[ai][key] = statistics.mean(cv) if len(cv) > 0 else 0
+ ret[ai]['na'][key] = len(val) - len(cv)
+ ret[ai]['stdev'][key] = statistics.stdev(cv) if len(cv) > 1 else 0
+
+ # Compute averages.
+ keys = data[list(data.keys())[0]].keys()
+ mean = dict()
+ for key in keys:
+ val = [ret[ai][key] for ai in data.keys() if ret[ai][key] > 0 or key == 'swap'] # Only non-zeros are valid.
+ mean[key] = statistics.mean(val) if len(val) > 0 else 0
+ ret['Average'] = mean
+
+ return ret
+
+# Display the statistical metadata (N/A and STDEV) of the dataset.
+def report(data:map):
+ print(f"{'':40}{'STIME':>14}{'PSS':>14}{'RSS':>14}")
+ print(f"{'Application':40}{' N/A STDEV' * 3}")
+ for app_id in [ai for ai in data.keys() if ai != 'Average']:
+ empty = dict((k, 0) for k in data[app_id].keys()) # for backward compatibility (0 if no data)
+ na = data[app_id].get('na', empty)
+ stdev = data[app_id].get('stdev', empty)
+ b = f"{app_id:40.40}"
+ b += f"{na['stime']:>6}{stdev['stime']:>8.1f}"
+ b += f"{na['pss']:>6}{stdev['pss']:>8.1f}"
+ b += f"{na['rss']:>6}{stdev['rss']:>8.1f}"
+ print(b)
+
+# Display the dataset.
+def display(data:map, verbose=False):
+ b = f"{'Application':40}{'STIME':>6}{'PSS':>8}"
+ if verbose:
+ b += f"{'nSHARED (%)':>15}{'MULT':>6}{'PRIVATE':>9}{'CODE':>8}{'DATA':>8}"
+ b += f"{'RSS':>8}"
+ print(b)
+
+ for app_id in data.keys():
+ d = data[app_id]
+ b = f"{app_id:40.40}{d['stime']:6.0f}{d['pss']:8.0f}"
+ if verbose:
+ nshared = d['pss'] - d['prvt']
+ b += f"{nshared:9.0f}{nshared / d['pss'] * 100 if d['pss'] > 0 else 0:6.1f}" # nShared (net shared amount)
+ b += f"{(d['rss'] - d['prvt'] - d['swap']) / nshared if nshared > 0 else 0:6.1f}" # Mult
+ b += f"{d['prvt']:9.0f}{d['file']:8.0f}{d['dirt']:8.0f}"
+ b += f"{d['rss']:8.0f}"
+ print(b)
+
+ if verbose:
+ report(data)
+
+# Compare and display the two datasets.
+def compare(data1:map, data2:map, verbose=False):
+ if set(data1.keys()) != set(data2.keys()):
+ raise Exception('Unable to process data because the target app ids do not match.')
+
+ b = f"{'Application':40}{'STIME (ms)':^20}{'PSS (KB)':^24}"
+ if verbose:
+ b += f"{'RSS (KB)':^24}"
+ print(b)
+
+ for app_id in data1.keys():
+ d1 = data1[app_id]
+ d2 = data2[app_id]
+ stt_gain=f"{(d2['stime'] - d1['stime']) / d1['stime'] * 100 if d1['stime'] > 0 else 0:+5.1f}%"
+ pss_gain=f"{(d2['pss'] - d1['pss']) / d1['pss'] * 100 if d1['pss'] > 0 else 0:+5.1f}%"
+ rss_gain=f"{(d2['rss'] - d1['rss']) / d1['rss'] * 100 if d1['rss'] > 0 else 0:+5.1f}%"
+ b = f"{app_id:40.40}{d1['stime']:6.0f}{d2['stime']:6.0f}{stt_gain:>8}"
+ b += f"{d1['pss']:8.0f}{d2['pss']:8.0f}{pss_gain:>8}"
+ if verbose:
+ b += f"{d1['rss']:8.0f}{d2['rss']:8.0f}{rss_gain:>8}"
+ print(b)
+
+# The main data collection logic.
+def run(serial, app_ids=predefined_list, count=5, pause=10, standalone=False, individual=False, post:str=None):
+ # A permission is required to run 'memps -v'.
+ cmd(f'sdb -s {serial} root on')
+
+ # A dictionary of dictionaries containing output values as lists.
+ ret = dict((app_id, {
+ 'stime':[], # Traditional startup time in ms
+ 'pss':[], # Proportional set size in KB
+ 'rss':[], # Resident set size
+ 'shar':[], # Shared set size
+ 'prvt':[], # Private set size
+ 'swap':[], # Swap size
+ 'file':[], # File (clean) set size
+ 'dirt':[], # Dirty set size
+ }) for app_id in app_ids)
+
+ # Flush dlogs and terminate any running processes.
+ print('Preparing for the measurement...')
+ if not standalone:
+ # Restart the candidate process if running.
+ cmd(f'sdb -s {serial} shell killall dotnet-launcher dotnet-loader')
+ terminate(app_ids, serial, pause / 2)
+
+ # Start up the dlog thread.
+ # We need to create a dedicated thread because 'dlog -d' is unstable on FH4.0 targets.
+ dlog_thread = threading.Thread(target=dlogger, args=[serial], daemon=True)
+ dlog_thread.start()
+
+ for num_iter in range(count):
+ print(f'Iter {num_iter + 1}/{count}')
+
+ # Zero-initialize values.
+ for app_id in app_ids:
+ for v in ret[app_id].values():
+ v.append(0)
+
+ if individual:
+ for i in range(len(app_ids)):
+ app_id = app_ids[i]
+ print(f'({i + 1}/{len(app_ids)}) Launching {app_id:60.60}', end='\r')
+
+ try:
+ pid = launch(app_id, serial, standalone, pause)
+ parse_stime(ret, app_id)
+ parse_memps(ret, serial, {pid: app_id})
+ dlogs.clear()
+ finally:
+ terminate([app_id], serial, pause / 4)
+ else:
+ pid_map = dict() # {pid: app_id}
+ try:
+ for i in range(len(app_ids)):
+ app_id = app_ids[i]
+ print(f'({i + 1}/{len(app_ids)}) Launching {app_id:60.60}', end='\r')
+
+ pid = launch(app_id, serial, standalone, pause)
+ parse_stime(ret, app_id)
+ pid_map[pid] = app_id
+ dlogs.clear()
+
+ # The post-script is only supported in non-individual mode.
+ if post:
+ res = cmd(post)
+
+ parse_memps(ret, serial, pid_map)
+ finally:
+ terminate(app_ids, serial, pause / 2)
+
+ # Display the intermediate data.
+ print(f"{'':80}",end='\r')
+ display(trim(ret, True), False)
+
+ if post:
+ print(res)
+
+ return ret
+
+# Save the serialized data to a file.
+def export(data, outfile=None):
+ if not outfile:
+ return
+
+ with open(outfile, 'w') as f:
+ f.write(str(data))
+ print(f'\nSuccessfully exported as {outfile}.')
+
+# Check the sdb connection status and get a device serial number.
+def read_serial():
+ raw = subprocess.run('sdb devices'.split(), encoding='utf-8', stdout=subprocess.PIPE).stdout
+ lines = [l for l in raw.splitlines() if not l.startswith('* ')]
+ if len(lines) <= 1:
+ # No target found.
+ return None
+ elif len(lines) == 2:
+ return lines[1].split(' ')[0].split(':')[0].strip()
+ else:
+ # More than one target found.
+ serials = []
+ for idx in range(1, len(lines)):
+ serial = lines[idx].split(' ')[0].split(':')[0].replace('device', '').strip()
+ serials.append(serial)
+ print(f"[{idx}] {serial} - {lines[idx].split(' ')[-1].strip()}")
+ choice = input(f'Select a device [1-{len(lines) - 1}]: ')
+ return serials[int(choice) - 1].strip() if choice.isdigit() else None
+
+# Main entry point for command line usage.
+def main():
+ epilog = \
+ '''output columns:
+ STIME Startup time in ms
+ PSS Proportional set size in KB
+ nSHARED Net shared set size = PSS - PRIVATE
+ (%) The portion of nSHARED in PSS
+ MULT Net multiplier = (RSS - PRIVATE - SWAP) / nSHARED
+ PRIVATE Private set size
+ CODE File (clean) set size
+ DATA Dirty (data) set size
+ RSS Resident set size
+ N/A The number of omitted samples
+ STDEV Dispersion of the samples (standard deviation)'''
+
+ parser = argparse.ArgumentParser(description='Tizen .NET performance analysis utility', epilog=epilog, formatter_class=argparse.RawDescriptionHelpFormatter)
+ parser.add_argument('APP_ID', type=str, nargs='*', help='target app ids (default: predefined 6 applications)', default=predefined_list)
+ parser.add_argument('-s', metavar='SERIAL', type=str, help='specify a device serial number', default=None)
+ parser.add_argument('-n', metavar='NUM', type=int, help='number of iterations (default: 5)', default=5)
+ parser.add_argument('-t', metavar='SECONDS', type=int, help='minimum time interval between launches (default: 10)', default=10)
+ parser.add_argument('-v', help='print verbose debug information', action='store_true')
+ parser.add_argument('-e', '--standalone', help='launch apps in standalone mode', action='store_true')
+ parser.add_argument('-i', '--individual', help='measure each application individually', action='store_true')
+ parser.add_argument('-p', metavar='CMD', type=str, help='execute a post-script after launching all apps', default=None)
+ parser.add_argument('-o', metavar='OUTFILE', help='export output data to a file', default=None)
+ parser.add_argument('-f', metavar='FILE', help='display data from a file (do not measure)', default=None)
+ parser.add_argument('--last', help='display the most recent measurement data', action='store_true')
+ parser.add_argument('--compare', nargs=2, metavar=('A', 'B'), help='compare two data files', default=None)
+ args = parser.parse_args()
+
+ # Read args.file and exit (if not None).
+ if args.f:
+ with open(args.f, 'r') as f:
+ # Deserialize data from the file.
+ data = ast.literal_eval(f.read())
+ display(data, args.v)
+ exit(0)
+
+ # Read the last measurement data and exit (if --last).
+ if args.last:
+ with open('measure.log', 'r') as f:
+ for line in reversed(f.read().splitlines()):
+ raw = line.split(']')[1].strip()
+ if raw.startswith('{'):
+ data = ast.literal_eval(raw)
+ display(data, args.v)
+ export(data, args.o) # Allow exporting data to OUTFILE.
+ exit(0)
+ print('The requested data could not be found in measure.log.')
+ exit(1)
+
+ # Compare two input files and exit (if --compare).
+ if args.compare:
+ with open(args.compare[0], 'r') as f1, open(args.compare[1], 'r') as f2:
+ data1 = ast.literal_eval(f1.read())
+ data2 = ast.literal_eval(f2.read())
+ compare(data1, data2, args.v)
+ exit(0)
+
+ # Get a device serial number.
+ serial = args.s if args.s else read_serial()
+ if serial is None:
+ print('No connected device(s).')
+ exit(1)
+
+ # Set up a log file.
+ global logfile
+ logfile = 'measure.log'
+ log(' '.join(sys.argv))
+
+ # Record data.
+ raw = run(serial, args.APP_ID, args.n, args.t, args.standalone, args.individual, args.p)
+ data = trim(raw)
+
+ print('Final Result')
+ display(data, args.v)
+
+ # Create a backup.
+ log(data)
+
+ # Export data.
+ export(data, args.o)
+
+if __name__ == '__main__':
+ main()
r = round(((p / (len(tc_array) - n)) * 100), 2)
print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
# Uninstall the application and restore to original state
def clean():
cmd(f"uninstall org.tizen.example.Launcher_TC_AOT_01.Tizen")
return "PASS"
+# The `Launcher_TC_PLUGIN_11` application should not have a library of other architecture.
+def TC_11():
+ sln_name = "Launcher_TC_PLUGIN_11"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ if "OK" not in app_install(f"{tpk_path}"):
+ return f"FAIL : Install the application for {tpk_path}"
+
+ pkg_id = f"org.tizen.example.Launcher_TC_PLUGIN_11"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ device_abi = get_device_abi()
+ if "arm_32" == device_abi:
+ if not exist(f"{root_path}/lib/arm") or \
+ not exist(f"{root_path}/lib/armel") or \
+ exist(f"{root_path}/lib/aarch64") or \
+ exist(f"{root_path}/lib/arm64") or \
+ exist(f"{root_path}/lib/riscv32") or \
+ exist(f"{root_path}/lib/riscv64") or \
+ exist(f"{root_path}/lib/x64") or \
+ exist(f"{root_path}/lib/x86"):
+ return "FAIL"
+ elif "arm_64" == device_abi:
+ if exist(f"{root_path}/lib/arm") or \
+ exist(f"{root_path}/lib/armel") or \
+ not exist(f"{root_path}/lib/aarch64") or \
+ not exist(f"{root_path}/lib/arm64") or \
+ exist(f"{root_path}/lib/riscv32") or \
+ exist(f"{root_path}/lib/riscv64") or \
+ exist(f"{root_path}/lib/x64") or \
+ exist(f"{root_path}/lib/x86"):
+ return "FAIL"
+ elif "riscv_32" == device_abi:
+ if exist(f"{root_path}/lib/arm") or \
+ exist(f"{root_path}/lib/armel") or \
+ exist(f"{root_path}/lib/aarch64") or \
+ exist(f"{root_path}/lib/arm64") or \
+ not exist(f"{root_path}/lib/riscv32") or \
+ exist(f"{root_path}/lib/riscv64") or \
+ exist(f"{root_path}/lib/x64") or \
+ exist(f"{root_path}/lib/x86"):
+ return "FAIL"
+ elif "riscv_64" == device_abi:
+ if exist(f"{root_path}/lib/arm") or \
+ exist(f"{root_path}/lib/armel") or \
+ exist(f"{root_path}/lib/aarch64") or \
+ exist(f"{root_path}/lib/arm64") or \
+ exist(f"{root_path}/lib/riscv32") or \
+ not exist(f"{root_path}/lib/riscv64") or \
+ exist(f"{root_path}/lib/x64") or \
+ exist(f"{root_path}/lib/x86"):
+ return "FAIL"
+ elif "x86_64" == device_abi:
+ if exist(f"{root_path}/lib/arm") or \
+ exist(f"{root_path}/lib/armel") or \
+ exist(f"{root_path}/lib/aarch64") or \
+ exist(f"{root_path}/lib/arm64") or \
+ exist(f"{root_path}/lib/riscv32") or \
+ exist(f"{root_path}/lib/riscv64") or \
+ not exist(f"{root_path}/lib/x64") or \
+ exist(f"{root_path}/lib/x86"):
+ return "FAIL"
+ elif "x86" == device_abi:
+ if exist(f"{root_path}/lib/arm") or \
+ exist(f"{root_path}/lib/armel") or \
+ exist(f"{root_path}/lib/aarch64") or \
+ exist(f"{root_path}/lib/arm64") or \
+ exist(f"{root_path}/lib/riscv32") or \
+ exist(f"{root_path}/lib/riscv64") or \
+ exist(f"{root_path}/lib/x64") or \
+ not exist(f"{root_path}/lib/x86"):
+ return "FAIL"
+ else:
+ return "NONE - TC_11 is not supported on this platform"
+
+
+ return "PASS"
+
# Run the test
def run():
cmd(f"root on")
r = round(((p / (len(tc_array) - n)) * 100), 2)
print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
# Uninstall the application and restore to original state
def clean():
cmd(f"uninstall org.tizen.example.Launcher_TC_PLUGIN_01.Tizen")
cmd(f"uninstall org.tizen.example.Launcher_TC_PLUGIN_08.Tizen")
cmd(f"uninstall org.tizen.example.Launcher_TC_PLUGIN_09.Tizen")
cmd(f"uninstall org.tizen.example.Launcher_TC_PLUGIN_10.Tizen")
+ cmd(f"uninstall org.tizen.example.Launcher_TC_PLUGIN_11")
# Main entry point
def main():
else:
tc_array.append(funcMap[tc_num])
else:
- tc_array = [TC_01, TC_02, TC_03, TC_04, TC_05, TC_06, TC_07, TC_08, TC_09, TC_10]
+ tc_array = [TC_01, TC_02, TC_03, TC_04, TC_05, TC_06, TC_07, TC_08, TC_09, TC_10, TC_11]
global serial
if len(sys.argv) >= 2 and "TC_" not in sys.argv[1]:
funcMap = {
-'TC_01': TC_01, 'TC_02': TC_02, 'TC_03': TC_03, 'TC_04': TC_04, 'TC_05': TC_05, 'TC_06': TC_06, 'TC_07': TC_07, 'TC_08': TC_08, 'TC_09': TC_09, 'TC_10': TC_10,
+'TC_01': TC_01, 'TC_02': TC_02, 'TC_03': TC_03, 'TC_04': TC_04, 'TC_05': TC_05,
+'TC_06': TC_06, 'TC_07': TC_07, 'TC_08': TC_08, 'TC_09': TC_09, 'TC_10': TC_10, 'TC_11': TC_11,
'PLUGIN_TC_01': TC_01, 'PLUGIN_TC_02': TC_02, 'PLUGIN_TC_03': TC_03, 'PLUGIN_TC_04': TC_04, 'PLUGIN_TC_05': TC_05,
-'PLUGIN_TC_06': TC_06, 'PLUGIN_TC_07': TC_07, 'PLUGIN_TC_08': TC_08, 'PLUGIN_TC_09': TC_09, 'PLUGIN_TC_10': TC_10
+'PLUGIN_TC_06': TC_06, 'PLUGIN_TC_07': TC_07, 'PLUGIN_TC_08': TC_08, 'PLUGIN_TC_09': TC_09, 'PLUGIN_TC_10': TC_10, 'PLUGIN_TC_11': TC_11
}
r = round(((p / (len(tc_array) - n)) * 100), 2)
print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
# Uninstall the application and restore to original state
def clean():
cmd(f"uninstall org.tizen.example.Launcher_TC_PRELOAD_01.Tizen")
--- /dev/null
+#!/usr/bin/env python3
+import os, subprocess, sys, argparse
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
+
+from time import sleep
+from Utils import *
+
+
+module_name = "TAC"
+
+# The `Launcher_TC_TAC_01` application must have TAC applied.
+def TC_01():
+ sln_name = "Launcher_TC_TAC_01.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_01.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/4.6.0.967/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Xamarin.Forms.*.dll")
+ if (f"{RO_TAC_DIR}Xamarin.Forms/4.6.0.967/Xamarin.Forms.Platform.Tizen.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/4.6.0.967/Xamarin.Forms.Core.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/4.6.0.967/Xamarin.Forms.Platform.dll" not in raw):
+ return "FAIL : The Xamarin.Forms in the TAC should be loaded when running the application"
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_TAC_02` application must have TAC applied.
+def TC_02():
+ sln_name = "Launcher_TC_TAC_02.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_00.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/4.8.0.1364/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Newtonsoft.Json/13.0.1/ -name *.dll -not -name *.ni.dll")
+ lines3 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2)+len(lines3):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Xamarin.Forms.*.dll")
+ if (f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1364/Xamarin.Forms.Platform.Tizen.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1364/Xamarin.Forms.Core.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1364/Xamarin.Forms.Platform.dll" not in raw):
+ return "FAIL : The Xamarin.Forms in the TAC should be loaded when running the application"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Newtonsoft.Json.dll")
+ if f"{RO_TAC_DIR}Newtonsoft.Json/13.0.1/Newtonsoft.Json.dll" not in raw:
+ return "FAIL : The Newtonsoft.Json in the TAC should be loaded when running the application"
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_TAC_03` application is normally TAC applied when updating.
+def TC_03():
+ sln_name = "Launcher_TC_TAC_03.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_00.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/4.8.0.1687/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}sqlite-net-base/1.7.335/ -name *.dll -not -name *.ni.dll")
+ lines3 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}SQLitePCLRaw.core/2.0.3/ -name *.dll -not -name *.ni.dll")
+ lines4 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2)+len(lines3)+len(lines4):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ if exist(f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1364/ -name *.dll"):
+ return f"FAIL : The Xamarin.Forms/4.8.0.1364 nuget should not exist in {RO_TAC_DIR}"
+
+ if exist(f"{RO_TAC_DIR}Newtonsoft.Json/13.0.1/ -name *.dll"):
+ return f"FAIL : The Newtonsoft.Json/13.0.1 nuget should not exist in {RO_TAC_DIR}"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Xamarin.Forms.*.dll")
+ if (f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1687/Xamarin.Forms.Platform.Tizen.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1687/Xamarin.Forms.Core.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1687/Xamarin.Forms.Platform.dll" not in raw):
+ return "FAIL : The Xamarin.Forms in the TAC should be loaded when running the application"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep SQLite-net.dll")
+ if f"{RO_TAC_DIR}sqlite-net-base/1.7.335/SQLite-net.dll" not in raw:
+ return "FAIL : The sqlite-net-base in the TAC should be loaded when running the application"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep SQLitePCLRaw.core.dll")
+ if f"{RO_TAC_DIR}SQLitePCLRaw.core/2.0.3/SQLitePCLRaw.core.dll" not in raw:
+ return "FAIL : The SQLitePCLRaw.core in the TAC should be loaded when running the application"
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_TAC_04` application should not apply TAC when updating.
+def TC_04():
+ sln_name = "Launcher_TC_TAC_04.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_00.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should not exist"
+
+ if exist(f"{RO_TAC_DIR}Xamarin.Forms/4.8.0.1364/ -name *.dll"):
+ return f"FAIL : The Xamarin.Forms/4.8.0.1364 nuget should not exist in {RO_TAC_DIR}"
+
+ if exist(f"{RO_TAC_DIR}Newtonsoft.Json/13.0.1/ -name *.dll"):
+ return f"FAIL : The Newtonsoft.Json/13.0.1 nuget should not exist in {RO_TAC_DIR}"
+
+ if exist(f"{RO_TAC_DIR}sqlite-net-base/1.7.335/ -name *.dll"):
+ return f"FAIL : The sqlite-net-base/1.7.335 nuget should not exist in {RO_TAC_DIR}"
+
+ if exist(f"{RO_TAC_DIR}SQLitePCLRaw.core/2.0.3/ -name *.dll"):
+ return f"FAIL : The SQLitePCLRaw.core/2.0.3 nuget should not exist in {RO_TAC_DIR}"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Xamarin.Forms.*.dll")
+ if (f"{root_path}/bin/Xamarin.Forms.Platform.Tizen.dll" not in raw) or \
+ (f"{root_path}/bin/Xamarin.Forms.Core.dll" not in raw) or \
+ (f"{root_path}/bin/Xamarin.Forms.Platform.dll" not in raw):
+ return "FAIL : The Xamarin.Forms in the application should be loaded when running the application"
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_TAC_05`, `Launcher_TC_TAC_06` applications using the same nuget are normally TAC applied.
+def TC_05():
+ sln_name = "Launcher_TC_TAC_05.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id1 = f"org.tizen.example.Launcher_TC_TAC_05.Tizen"
+
+ root_path = get_root_path(f"{pkg_id1}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id1}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/5.0.0.1558-pre3/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ sln_name = "Launcher_TC_TAC_06.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id2 = f"org.tizen.example.Launcher_TC_TAC_06.Tizen"
+
+ root_path = get_root_path(f"{pkg_id2}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id2}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/5.0.0.1558-pre3/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ cmd(f"shell tpk-backend --force-remove --preload -d {pkg_id1}")
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/5.0.0.1558-pre3/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id2}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id2}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Xamarin.Forms.*.dll")
+ if (f"{RO_TAC_DIR}Xamarin.Forms/5.0.0.1558-pre3/Xamarin.Forms.Platform.Tizen.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/5.0.0.1558-pre3/Xamarin.Forms.Core.dll" not in raw) or \
+ (f"{RO_TAC_DIR}Xamarin.Forms/5.0.0.1558-pre3/Xamarin.Forms.Platform.dll" not in raw):
+ return "FAIL : The Xamarin.Forms in the TAC should be loaded when running the application"
+
+ cmd(f"shell app_launcher -t {pkg_id2}")
+
+ return "PASS"
+
+# The `Launcher_TC_TAC_07` application is normally TAC applied when uninstall.
+def TC_06():
+ sln_name = "Launcher_TC_TAC_07.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_07.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}Xamarin.Forms/4.4.0.991864/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ cmd(f"shell tpk-backend --force-remove --preload -d {pkg_id}")
+
+ if exist(f"{RO_TAC_DIR}Xamarin.Forms/4.4.0.991864/ -name *.dll"):
+ return f"FAIL : The Xamarin.Forms/4.4.0.991864 nuget should not exist in {RO_TAC_DIR}"
+
+ return "PASS"
+
+# The `Launcher_TC_TAC_08` application should be applied to TAC, but The `Launcher_TC_TAC_09` application should not be applied to TAC.
+def TC_07():
+ raw = cmd(f"shell find {FRAMEWORK_DIR}/XSF.*")
+ if "XSF.dll" in raw:
+ cmd(f"shell mv {FRAMEWORK_DIR}/XSF.dll {FRAMEWORK_DIR}/XSF.dll2")
+ elif "XSF.ni.dll" in raw:
+ cmd(f"shell mv {FRAMEWORK_DIR}/XSF.ni.dll {FRAMEWORK_DIR}/XSF.ni.dll2")
+
+ sln_name = "Launcher_TC_TAC_08.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_08.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink/ -name *.dll -not -name *.ni.dll")
+ lines1 = [l for l in raw.splitlines()]
+ raw = cmd(f"shell find {RO_TAC_DIR}XSF/1.0.0.0/ -name *.dll -not -name *.ni.dll")
+ lines2 = [l for l in raw.splitlines()]
+ if len(lines1) != len(lines2):
+ return "FAIL : The number of .dll in the .tac_symlink and .dll in the TAC must match"
+
+ raw = cmd(f"shell ls -alZ {root_path}/bin/.tac_symlink/*.dll")
+ lines = [l for l in raw.splitlines() if ".ni.dll" not in l]
+ for dll in lines:
+ origin_path = dll.split("->")[1].strip()
+ if not exist(f"{origin_path}"):
+ return "FAIL : The original file of the symbolic link must exist"
+
+ sln_name = "Launcher_TC_TAC_09.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_09.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ raw = cmd(f"shell find {root_path}/bin/.tac_symlink -name XSF.dll -not -name XSF.ni.dll")
+ lines = [l for l in raw.splitlines()]
+ if len(lines) != 0:
+ return "FAIL : The version is the same Nuget, but the SHA value is different"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep XSF.dll")
+ if f"{root_path}/bin/XSF.dll" not in raw:
+ return "FAIL : The XSF in the application should be loaded when running the application"
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The Launcher_TC_TAC_10 application should match the information of nuget with the value of TAC DB.
+def TC_08():
+ sln_name = "Launcher_TC_TAC_10.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_10.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if not exist(f"{root_path}/bin/.tac_symlink"):
+ return "FAIL : The .tac_symlink folder should exist"
+
+ raw = subprocess.run((f"sdb -s {serial} shell sqlite3 {RO_TAC_DIR}.TAC.App.list.db").split(), stdout=subprocess.PIPE, input=f"select * from TAC;\n.q\n", encoding="utf-8").stdout
+ lines = [l for l in raw.splitlines() if f"{pkg_id}" in l]
+ for rcd in lines:
+ is_exist = False
+ if ("Xamarin.Forms/4.8.0.1560" in rcd) or \
+ ("Newtonsoft.Json/12.0.3" in rcd) or \
+ ("Google.Apis.Core/1.49.0" in rcd) or \
+ ("Google.Apis/1.49.0" in rcd):
+ is_exist = True
+ continue
+ if not is_exist:
+ return "FAIL : TAC database must have a valid value"
+
+ return "PASS"
+
+# The Launcher_TC_TAC_11 application must match the version of the nuget in .deps.json and the version of the nuget in TAC DB.
+def TC_09():
+ sln_name = "Launcher_TC_TAC_11.Tizen"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ raw = cmd(f"push {tpk_path} /usr/apps/.preload-tpk/")
+ if "1 file(s) pushed. 0 file(s) skipped." in raw:
+ cmd(f"shell install_preload_pkg")
+
+ pkg_id = f"org.tizen.example.Launcher_TC_TAC_11.Tizen"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ raw = subprocess.run((f"sdb -s {serial} shell sqlite3 {RO_TAC_DIR}.TAC.App.list.db").split(), stdout=subprocess.PIPE, input=f"select * from TAC;\n.q\n", encoding="utf-8").stdout
+ lines = [l for l in raw.splitlines() if f"{pkg_id}" in l]
+ for nuget in lines:
+ name = nuget.split("|")[3]
+ version = nuget.split("|")[4]
+ raw = cmd(f"shell cat {root_path}/{sln_name}.deps.json | grep {name}/")
+ if f"{version}" not in f"{raw}":
+ return "FAIL : "
+
+ return "PASS"
+
+# Run the test
+def run():
+ cmd(f"root on")
+ cmd(f"shell mount -o remount,rw /")
+
+ global tpk_list
+ tpk_list = search_tpk(f"{module_name}")
+
+ pn = run_tc_array(module_name, tc_array)
+ n = int(pn.split(":")[0])
+ f = int(pn.split(":")[1])
+ p = int(pn.split(":")[2])
+ r = 0.0
+ if (len(tc_array) - n) != 0:
+ r = round(((p / (len(tc_array) - n)) * 100), 2)
+ print(f"--- {module_name}_RO TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name}_RO | {p} | {f} | {n} | {r} |\n")
+
+# Uninstall the application and restore to original state
+def clean():
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_00.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_01.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_06.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_07.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_08.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_09.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_10.Tizen")
+ cmd(f"shell tpk-backend --force-remove --preload -d org.tizen.example.Launcher_TC_TAC_11.Tizen")
+
+ cmd(f"shell mv {FRAMEWORK_DIR}/XSF.dll2 {FRAMEWORK_DIR}/XSF.dll")
+ cmd(f"shell mv {FRAMEWORK_DIR}/XSF.ni.dll2 {FRAMEWORK_DIR}/XSF.ni.dll")
+
+# Main entry point
+def main():
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
+ parser.add_argument("TC_NUMBER", type=str, nargs="*", help="Individual excution")
+ args = parser.parse_args()
+
+ global tc_array
+ if args.TC_NUMBER and "TC_" in args.TC_NUMBER[0]:
+ tc_array = []
+ for tc_num in args.TC_NUMBER:
+ if tc_num not in funcMap:
+ print(f"There is no {tc_num} test.")
+ exit(1)
+ else:
+ tc_array.append(funcMap[tc_num])
+ else:
+ tc_array = [TC_01, TC_02, TC_03, TC_04, TC_05, TC_06, TC_07, TC_08, TC_09]
+
+ global serial
+ if len(sys.argv) >= 2 and "TC_" not in sys.argv[1]:
+ serial = read_serial(sys.argv[1])
+ else:
+ serial = read_serial(None)
+
+ if serial is None:
+ print("No connected device(s).")
+ exit(1)
+
+ device = get_device_type()
+ print(f"=== Dotnet-Launcher [{device}] Test Case - ({module_name}_RO) ===")
+
+ run()
+ clean()
+
+
+funcMap = {
+'TC_01': TC_01, 'TC_02': TC_02, 'TC_03': TC_03, 'TC_04': TC_04, 'TC_05': TC_05, 'TC_06': TC_06, 'TC_07': TC_07, 'TC_08': TC_08, 'TC_09': TC_09,
+'TAC_TC_01': TC_01, 'TAC_TC_02': TC_02, 'TAC_TC_03': TC_03, 'TAC_TC_04': TC_04, 'TAC_TC_05': TC_05,
+'TAC_TC_06': TC_06, 'TAC_TC_07': TC_07, 'TAC_TC_08': TC_08, 'TAC_TC_09': TC_09
+}
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ print("\nExit (Pressed Ctrl+C)")
+ exit(1)
r = 0.0
if (len(tc_array) - n) != 0:
r = round(((p / (len(tc_array) - n)) * 100), 2)
- print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ print(f"--- {module_name}_RW TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name}_RW | {p} | {f} | {n} | {r} |\n")
# Uninstall the application and restore to original state
def clean():
exit(1)
device = get_device_type()
- print(f"=== Dotnet-Launcher [{device}] Test Case - ({module_name}) ===")
+ print(f"=== Dotnet-Launcher [{device}] Test Case - ({module_name}_RW) ===")
run()
clean()
r = round(((p / (len(tc_array) - n)) * 100), 2)
print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
# Uninstall the application and restore to original state
def clean():
cmd(f"uninstall org.tizen.example.Launcher_TC_TLC_01.Tizen")
r = round(((p / (len(tc_array) - n)) * 100), 2)
print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
# Uninstall the application and restore to original state
def clean():
cmd(f"uninstall org.tizen.example.Launcher_TC_TOOL_01.Tizen")
--- /dev/null
+#!/usr/bin/env python3
+import os, subprocess, sys, argparse
+sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
+
+from time import sleep
+from Utils import *
+
+
+module_name = "EXCEPTION"
+
+# The `Launcher_TC_EXCEPTION_01` application(apptype : dotnet) should run in `candidate(dotnet-loader)` mode.
+def TC_01():
+ sln_name = "Launcher_TC_EXCEPTION_01"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ if "OK" not in app_install(f"{tpk_path}"):
+ return f"FAIL : Install the application for {tpk_path}"
+
+ pkg_id = "org.tizen.example.Launcher_TC_EXCEPTION_01"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ if "OK" not in prepare_candidate_process(f"dotnet-loader", f"{pkg_id}"):
+ return f"FAIL : Candidate process should have dotnet-loader"
+
+ pid = launch_and_get_pid(f"-s", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Launcher_TC_EXCEPTION_01")
+ if f"{root_path}/bin/Launcher_TC_EXCEPTION_01.dll" not in raw:
+ return "FAIL : The application is run as a candidate mode."
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep dotnet-loader")
+ if f"/usr/bin/dotnet-loader" not in raw:
+ return "FAIL : The application is run as a candidate mode."
+
+ raw = cmd(f"shell dlogutil STDOUT | grep {pid} &")
+ lines = [l for l in raw.splitlines() if "System.NullReferenceException:" in l]
+ for log in lines:
+ if "System.NullReferenceException: Object reference not set to an instance of an object." not in log:
+ return "FAIL : The application can use the try/catch block to catch the NullReferenceException."
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_EXCEPTION_01` application(apptype : dotnet) should run in `standalone(dotnet-launcher)` mode.
+def TC_02():
+ sln_name = "Launcher_TC_EXCEPTION_01"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ if "OK" not in app_install(f"{tpk_path}"):
+ return f"FAIL : Install the application for {tpk_path}"
+
+ pkg_id = "org.tizen.example.Launcher_TC_EXCEPTION_01"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Launcher_TC_EXCEPTION_01")
+ if f"{root_path}/bin/Launcher_TC_EXCEPTION_01.dll" not in raw:
+ return "FAIL : The application is run as a standalone mode"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep dotnet-launcher")
+ if f"/usr/bin/dotnet-launcher" not in raw:
+ return "FAIL : The application is run as a standalone mode."
+
+ raw = cmd(f"shell dlogutil STDOUT | grep {pid} &")
+ lines = [l for l in raw.splitlines() if "System.NullReferenceException:" in l]
+ for log in lines:
+ if "System.NullReferenceException: Object reference not set to an instance of an object." not in log:
+ return "FAIL : The application can use the try/catch block to catch the NullReferenceException."
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_EXCEPTION_02` application(apptype : dotnet-nui) should run in `candidate(dotnet-loader/dotnet-nui-loader)` mode.
+def TC_03():
+ sln_name = "Launcher_TC_EXCEPTION_02"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ if "OK" not in app_install(f"{tpk_path}"):
+ return f"FAIL : Install the application for {tpk_path}"
+
+ pkg_id = "org.tizen.example.Launcher_TC_EXCEPTION_02"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ loader = "dotnet-nui-loader"
+ if "NOT FOUND" in prepare_candidate_process(f"{loader}", f"{pkg_id}"):
+ loader = "dotnet-loader"
+ if "OK" not in prepare_candidate_process(f"{loader}", f"{pkg_id}"):
+ return f"FAIL : Candidate process should have {loader}"
+ elif "FAIL" not in prepare_candidate_process(f"{loader}", f"{pkg_id}"):
+ return f"FAIL : Candidate process should have {loader}"
+
+ pid = launch_and_get_pid(f"-s", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Launcher_TC_EXCEPTION_02")
+ if f"{root_path}/bin/Launcher_TC_EXCEPTION_02.dll" not in raw:
+ return "FAIL : The application is run as a candidate mode"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep {loader}")
+ if f"/usr/bin/{loader}" not in raw:
+ return "FAIL : The application is run as a candidate mode."
+
+ raw = cmd(f"shell dlogutil STDOUT | grep {pid} &")
+ lines = [l for l in raw.splitlines() if "System.NullReferenceException:" in l]
+ for log in lines:
+ if "System.NullReferenceException: Object reference not set to an instance of an object." not in log:
+ return "FAIL : The application can use the try/catch block to catch the NullReferenceException."
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# The `Launcher_TC_EXCEPTION_02` application(apptype : dotnet-nui) should run in `standalone(dotnet-launcher)` mode.
+def TC_04():
+ sln_name = "Launcher_TC_EXCEPTION_02"
+
+ tpk_path = get_tpk_path(tpk_list, f"{sln_name}")
+ if tpk_path == None:
+ return f"FAIL : Get the tpk path for {sln_name}"
+
+ if "OK" not in app_install(f"{tpk_path}"):
+ return f"FAIL : Install the application for {tpk_path}"
+
+ pkg_id = "org.tizen.example.Launcher_TC_EXCEPTION_02"
+
+ root_path = get_root_path(f"{pkg_id}")
+ if root_path == "None":
+ return f"FAIL : Get the root path for {pkg_id}"
+
+ pid = launch_and_get_pid(f"-e", f"{pkg_id}")
+ if 0 == pid:
+ return f"FAIL : Get the pid for {pkg_id}"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep Launcher_TC_EXCEPTION_02")
+ if f"{root_path}/bin/Launcher_TC_EXCEPTION_02.dll" not in raw:
+ return "FAIL : The application is run as a standalone mode"
+
+ raw = cmd(f"shell cat /proc/{pid}/smaps | grep dotnet-launcher")
+ if f"/usr/bin/dotnet-launcher" not in raw:
+ return "FAIL : The application is run as a standalone mode."
+
+ raw = cmd(f"shell dlogutil STDOUT | grep {pid} &")
+ lines = [l for l in raw.splitlines() if "System.NullReferenceException:" in l]
+ for log in lines:
+ if "System.NullReferenceException: Object reference not set to an instance of an object." not in log:
+ return "FAIL : The application can use the try/catch block to catch the NullReferenceException."
+
+ cmd(f"shell app_launcher -t {pkg_id}")
+
+ return "PASS"
+
+# Run the test
+def run():
+ cmd(f"root on")
+ cmd(f"shell mount -o remount,rw /")
+
+ global tpk_list
+ tpk_list = search_tpk(f"{module_name}")
+
+ pn = run_tc_array(module_name, tc_array)
+ n = int(pn.split(":")[0])
+ f = int(pn.split(":")[1])
+ p = int(pn.split(":")[2])
+ r = 0.0
+ if (len(tc_array) - n) != 0:
+ r = round(((p / (len(tc_array) - n)) * 100), 2)
+ print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
+# Uninstall the application and restore to original state
+def clean():
+ cmd(f"uninstall org.tizen.example.Launcher_TC_EXCEPTION_01")
+ cmd(f"uninstall org.tizen.example.Launcher_TC_EXCEPTION_02")
+
+# Main entry point
+def main():
+ parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter)
+ parser.add_argument("TC_NUMBER", type=str, nargs="*", help="Individual execution")
+ args = parser.parse_args()
+
+ global tc_array
+ if args.TC_NUMBER and "TC_" in args.TC_NUMBER[0]:
+ tc_array = []
+ for tc_num in args.TC_NUMBER:
+ if tc_num not in funcMap:
+ print(f"There is no {tc_num} test.")
+ exit(1)
+ else:
+ tc_array.append(funcMap[tc_num])
+ else:
+ tc_array = [TC_01, TC_02, TC_03, TC_04]
+ #skip TC_03(dotnet-nui-loader)
+
+ global serial
+ if len(sys.argv) >= 2 and "TC_" not in sys.argv[1]:
+ serial = read_serial(sys.argv[1])
+ else:
+ serial = read_serial(None)
+
+ if serial is None:
+ print("No connected device(s).")
+ exit(1)
+
+ device = get_device_type()
+ print(f"=== Dotnet-Launcher [{device}] Test Case - ({module_name}) ===")
+
+ run()
+ clean()
+
+
+funcMap = {
+'TC_01': TC_01, 'TC_02': TC_02, 'TC_03': TC_03, 'TC_04': TC_04,
+'EXCEPTION_TC_01': TC_01, 'EXCEPTION_TC_02': TC_02, 'EXCEPTION_TC_03': TC_03, 'EXCEPTION_TC_04': TC_04
+}
+
+
+if __name__ == "__main__":
+ try:
+ main()
+ except KeyboardInterrupt:
+ print("\nExit (Pressed Ctrl+C)")
+ exit(1)
r = round(((p / (len(tc_array) - n)) * 100), 2)
print(f"--- {module_name} TCT Result ---\nNONE : [{n}] / FAIL : [{f}] / PASS : [{p}] - [{r}%]\n")
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write(f"| {module_name} | {p} | {f} | {n} | {r} |\n")
+
# Uninstall the application and restore to original state
def clean():
cmd(f"uninstall org.tizen.example.Launcher_TC_LAUNCH_01.Tizen")
if ext == ".py" and \
"BuildTPK" not in full_filename and \
"Utils" not in full_filename and \
- "ALL" not in full_filename:
+ "ALL" not in full_filename and \
+ "candidate_mcj" not in full_filename:
script_lists.append(full_filename)
return script_lists
def run(serial):
+ with open(f"{RESULT_PATH}", "w") as file:
+ file.write("==== Dotnet Launcher Unit Test Result ====\n")
+ file.write("| MODULE | PASS | FAIL | NONE | RATIO |\n")
+ file.write("------------------------------------------\n")
+
device = get_device_type()
print(f"=== Dotnet-Launcher [{device}] Test Case ===")
subprocess.run((f"{tc} {serial}").split())
sleep(3)
+ with open(f"{RESULT_PATH}", "a+") as file:
+ file.write("------------------------------------------\n")
+ file.write("| MODULE | PASS | FAIL | NONE | RATIO |\n")
+
+
+def result(serial):
+ with open(f"{RESULT_PATH}", "r") as file:
+ result = file.read()
+ print(result)
+
def main():
serial = read_serial(None)
get_script_path("./")
run(serial)
+ result(serial)
if __name__ == "__main__":
FRAMEWORK_DIR = "/usr/share/dotnet.tizen/framework/"
PRELOAD_DIR = "/usr/share/dotnet.tizen/preload/"
IBCDATA_DIR = "/usr/share/dotnet.tizen/ibcdata/"
+RO_TAC_DIR = "/usr/share/dotnet.tizen/tac/"
DOTNET_DIR = "/opt/usr/dotnet/"
OWNER_DIR = "/home/owner/"
SPC_DLL = "System.Private.CoreLib.dll"
+RESULT_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), "result.log"))
# Check the sdb connection status and get a device serial number
def read_serial(serial):
raw = cmd(f"shell cat /etc/config/model-config.xml | grep tizen.org/feature/profile")
return raw.split(">")[1].split("<")[0]
+# Get the device type
+def get_platform_version():
+ raw = cmd(f"shell cat /etc/config/model-config.xml | grep tizen.org/feature/platform.version")
+ return raw.split(">")[1].split("<")[0]
+
# Create the System.Private.CoreLib native image
def create_spc_ni():
raw = cmd(f"shell find {RUNTIME_DIR} -name {SPC_DLL}.Backup")
# Prepare the candidate process
def prepare_candidate_process(loader, pkg_id):
- cmd(f"shell killall dotnet-launcher {loader}")
+ cmd(f"shell killall dotnet-launcher")
+ raw = cmd(f"shell killall {loader}")
+ if "no process found" in raw:
+ return "NOT FOUND"
sleep(30)
raw = cmd(f"shell ps -ef | grep {loader}")
line = [l for l in raw.splitlines() if "cpu_arch" in l]
return line[0].split(":")[1]
+# Get the device abi
+def get_device_abi():
+ raw = cmd("capability")
+ line = [l for l in raw.splitlines() if "core_abi" in l]
+ return line[0].split(":")[1]
+
# Check the library type
def check_library_arch(rootpath, library):
raw = cmd(f"pull {rootpath}/bin/{library} {library}")