Implement Skottie vs Lottie perf tool

Add PerfActivity to Skottie demo app, which can render
with both Lottie and Skottie players. Create bash script, which
runs 15 lottie files with both renderers, runs perfetto and
outputs performance metrics in json files.

Test: ran run_perf.sh and it outpus perf metrics
Change-Id: Ibc29d3a9dc7bfe79002bf91472e93883d746c03d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/296276
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Stan Iliev <stani@google.com>
This commit is contained in:
Stan Iliev 2020-06-23 10:58:39 -04:00 committed by Skia Commit-Bot
parent 3824f58843
commit 8ee607cbc1
18 changed files with 504 additions and 19 deletions

View File

@ -9,6 +9,8 @@ apply plugin: 'com.android.application'
dependencies {
implementation project("skottielib")
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'com.airbnb.android:lottie:3.4.1'
}
android {

View File

@ -0,0 +1,84 @@
# Copyright 2020 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
adb shell perfetto \
-c - --txt \
-o /data/misc/perfetto-traces/trace \
<<EOF
buffers: {
size_kb: 63488
fill_policy: RING_BUFFER
}
buffers: {
size_kb: 2048
fill_policy: RING_BUFFER
}
data_sources: {
config {
name: "android.power"
android_power_config {
battery_poll_ms: 500
battery_counters: BATTERY_COUNTER_CAPACITY_PERCENT
battery_counters: BATTERY_COUNTER_CHARGE
battery_counters: BATTERY_COUNTER_CURRENT
collect_power_rails: true
}
}
}
data_sources: {
config {
name: "linux.process_stats"
target_buffer: 1
process_stats_config {
scan_all_processes_on_start: true
proc_stats_poll_ms: 1000
}
}
}
data_sources: {
config {
name: "linux.sys_stats"
sys_stats_config {
stat_period_ms: 1000
stat_counters: STAT_CPU_TIMES
stat_counters: STAT_FORK_COUNT
}
}
}
data_sources: {
config {
name: "android.heapprofd"
target_buffer: 0
heapprofd_config {
sampling_interval_bytes: 4096
shmem_size_bytes: 8388608
}
}
}
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
atrace_categories: "gfx"
atrace_categories: "input"
atrace_categories: "view"
atrace_categories: "sched"
atrace_categories: "freq"
atrace_categories: "binder_driver"
atrace_categories: "am"
atrace_categories: "wm"
}
}
}
duration_ms: 10000
write_into_file: true
file_write_period_ms: 5000
max_file_size_bytes: 500000000
flush_period_ms: 30000
EOF
adb pull /data/misc/perfetto-traces/trace

View File

@ -0,0 +1,42 @@
# Copyright 2020 Google Inc.
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#!/bin/bash
mkdir -p out
# download perfetto trace_processor
if [ ! -f "trace_processor" ]; then
wget https://get.perfetto.dev/trace_processor
chmod +x trace_processor
fi
adb root
# get out of the lock screen
adb shell input keyevent MENU
adb shell input keyevent MENU
adb shell am force-stop org.skia.skottie
renderer_names=(lottie_hw lottie_sw skottie)
# iterate over lottie HW and skottie renderers
for renderer in {0,2}
do
echo "renderer " ${renderer_names[${renderer}]}
# iterate over each of the 15 lottie files
for file in {0..14}
do
echo "show file " ${file}
# start perfetto first (before the app) to give it a chance to capture startup metrics/shader compile and first frame rendering
./collect.sh &
perfetto_pid=$!
# give one second for the perfetto script to start
sleep 1
adb shell am start -n org.skia.skottie/.PerfActivity --ei renderer ${renderer} --ei file ${file}
#wait for perfetto to finish (~10s)
wait $perfetto_pid
adb shell am force-stop org.skia.skottie
./trace_processor --run-metrics=skottie_metric.sql --metrics-output=json trace > out/data_${renderer_names[${renderer}]}_${file}.json
mv trace out/trace_${renderer_names[${renderer}]}_${file}
done
done
echo All done

View File

@ -0,0 +1,61 @@
syntax = "proto2";
package perfetto.protos;
import "protos/perfetto/metrics/metrics.proto";
import "protos/perfetto/metrics/android/hwui_metric.proto";
// Android HWUI graphics performance and graphics memory usage metrics augmented with
// perf data which is specific to the Skottie player. Skottie app has an additional
// render thread named "SkottieAnimator" in the traces. Perf metrics are filtered for
// 'org.skia.skottie' process only.
message ProcessRenderInfoEx {
// original HWUI metric as defined by built-in perfetto proto.
optional ProcessRenderInfo hwui_process_info = 1;
// Number of times the Skottie GL thread rendered a frame and max/min/avg time for Skottie GL
// renderer to finish rendering in
// in nanoseconds. These values have 0 value for lottie player, because it does it renders only
// in RenderThread.
optional uint32 skottie_animator_count = 2;
optional int64 skottie_animator_max = 3;
optional int64 skottie_animator_min = 4;
optional double skottie_animator_avg = 5;
optional uint32 dequeue_buffer_count = 6;
optional int64 dequeue_buffer_max = 7;
optional int64 dequeue_buffer_min = 8;
optional double dequeue_buffer_avg = 9;
// The following 2 fields are useful to compare render thread performance between Lottie and
// Skottie players.
// Skottie metric is a sum of the time on RenderThread and SkottieAnimator threads, while Lottie
// is only the time on RenderThread.
optional double render_time_avg = 10; // draw_frame_avg + skottie_animator_avg
// "render_time_avg_no_dequeue" tries to compensate the time spent to wait for a new buffer.
// It equals draw_frame_avg + skottie_animator_avg - dequeue_buffer_avg.
optional double render_time_avg_no_dequeue = 11;
optional int64 ui_thread_cpu_time = 12; // CPU time spent on UI thread in nanoseconds
optional int64 rt_thread_cpu_time = 13; // CPU time spent on RenderThread in nanoseconds
optional int64 hwui_tasks_cpu_time = 14; // CPU time spent on hwuiTask0/1 threads in nanoseconds
optional int64 skottie_animator_cpu_time = 15; // CPU time spent on SkottieAnimator in ns
optional int64 total_cpu_time = 16; // Total CPU time in nanoseconds. Equals
// ui_thread_cpu_time + rt_thread_cpu_time + skottie_animator_cpu_time + hwui_tasks_cpu_time
optional int64 total_gpu_time = 17; // GPU time spent to render all content in nanoseconds.
// This one number is the "ultimate" benchmark to compare airbnb lottie vs skottie player.
// performance. It is the total time for any rendering related work on CPU and GPU combined.
optional int64 total_time = 18; // This is total_cpu_time + total_gpu_time in nanoseconds.
}
message SkottieMetric {
repeated ProcessRenderInfoEx process_info = 1;
}
extend TraceMetrics {
optional SkottieMetric skottie_metric = 450;
}

View File

@ -0,0 +1,204 @@
SELECT RUN_METRIC('android/android_hwui_metric.sql');
CREATE VIEW dequeue_buffer AS
SELECT
count(*) as dequeue_buffer_count,
max(dur) as dequeue_buffer_max,
min(dur) as dequeue_buffer_min,
avg(dur) as dequeue_buffer_avg,
sum(dur) as dequeue_buffer_sum,
thread_track.utid as render_thread_id
FROM slice
INNER JOIN thread_track ON (thread_track.id = slice.track_id)
WHERE slice.name='dequeueBuffer' AND slice.dur >= 0
GROUP BY thread_track.utid;
CREATE VIEW skottie_animator AS
SELECT
count(*) as skottie_animator_count,
max(dur) as skottie_animator_max,
min(dur) as skottie_animator_min,
avg(dur) as skottie_animator_avg,
sum(dur) as skottie_animator_sum,
thread.upid as process_upid
FROM slice
INNER JOIN thread_track ON (thread_track.id = slice.track_id)
INNER JOIN thread ON (thread.name='SkottieAnimator' AND thread.utid = thread_track.utid)
WHERE slice.name='Choreographer#doFrame' AND slice.dur >= 0
GROUP BY thread_track.utid;
CREATE VIEW total_cpu_time AS
SELECT
sum(sched_slice.dur) as cpu_time,
thread.upid as process_upid
FROM sched_slice
INNER JOIN process ON (process.upid = thread.upid)
INNER JOIN thread ON (
(thread.name LIKE 'hwuiTask%' OR thread.name=substr(process.name,-15) OR thread.name='RenderThread' OR thread.name='SkottieAnimator')
AND thread.utid = sched_slice.utid
)
WHERE sched_slice.dur >= 0
GROUP BY thread.upid;
CREATE VIEW cpu_time_rt_hwui_tasks AS
SELECT
sum(sched_slice.dur) as cpu_time,
thread.upid as process_upid
FROM sched_slice
INNER JOIN thread ON (thread.name LIKE 'hwuiTask%' AND thread.utid = sched_slice.utid)
WHERE sched_slice.dur >= 0
GROUP BY thread.upid;
CREATE VIEW cpu_time_ui_thread AS
SELECT
sum(sched_slice.dur) as cpu_time,
thread.upid as process_upid
FROM sched_slice
INNER JOIN process ON (process.upid = thread.upid)
INNER JOIN thread ON (thread.name=substr(process.name,-15) AND thread.utid = sched_slice.utid)
WHERE sched_slice.dur >= 0
GROUP BY thread.upid;
CREATE VIEW cpu_time_rt AS
SELECT
sum(sched_slice.dur) as cpu_time,
thread.upid as process_upid
FROM sched_slice
INNER JOIN thread ON (thread.name='RenderThread' AND thread.utid = sched_slice.utid)
WHERE sched_slice.dur >= 0
GROUP BY thread.upid;
CREATE VIEW cpu_time_skottie_animator AS
SELECT
sum(sched_slice.dur) as cpu_time,
thread.upid as process_upid
FROM sched_slice
INNER JOIN thread ON (thread.name='SkottieAnimator' AND thread.utid = sched_slice.utid)
WHERE sched_slice.dur >= 0
GROUP BY thread.upid;
CREATE VIEW hwui_gpu_completion2 AS
SELECT
count(*) as gpu_completion_count,
max(dur) as gpu_completion_max,
min(dur) as gpu_completion_min,
avg(dur) as gpu_completion_avg,
sum(dur) as gpu_completion_sum,
thread.upid as process_upid
FROM slice
INNER JOIN thread_track ON (thread_track.id = slice.track_id)
INNER JOIN thread ON (thread.name='GPU completion' AND thread.utid = thread_track.utid)
WHERE slice.name LIKE 'waiting for GPU completion%' AND slice.dur >= 0
GROUP BY thread_track.utid;
CREATE VIEW skottie_metric_output AS
SELECT SkottieMetric(
'process_info', (
SELECT RepeatedField(
ProcessRenderInfoEx(
'hwui_process_info',
ProcessRenderInfo(
'process_name', process_name,
'rt_cpu_time_ms', rt_cpu_time_ms,
'draw_frame_count', hwui_draw_frame.draw_frame_count,
'draw_frame_max', hwui_draw_frame.draw_frame_max,
'draw_frame_min', hwui_draw_frame.draw_frame_min,
'draw_frame_avg', hwui_draw_frame.draw_frame_avg,
'flush_count', hwui_flush_commands.flush_count,
'flush_max', hwui_flush_commands.flush_max,
'flush_min', hwui_flush_commands.flush_min,
'flush_avg', hwui_flush_commands.flush_avg,
'prepare_tree_count', hwui_prepare_tree.prepare_tree_count,
'prepare_tree_max', hwui_prepare_tree.prepare_tree_max,
'prepare_tree_min', hwui_prepare_tree.prepare_tree_min,
'prepare_tree_avg', hwui_prepare_tree.prepare_tree_avg,
'gpu_completion_count', hwui_gpu_completion2.gpu_completion_count,
'gpu_completion_max', hwui_gpu_completion2.gpu_completion_max,
'gpu_completion_min', hwui_gpu_completion2.gpu_completion_min,
'gpu_completion_avg', hwui_gpu_completion2.gpu_completion_avg,
'ui_record_count', hwui_ui_record.ui_record_count,
'ui_record_max', hwui_ui_record.ui_record_max,
'ui_record_min', hwui_ui_record.ui_record_min,
'ui_record_avg', hwui_ui_record.ui_record_avg,
'shader_compile_count', hwui_shader_compile.shader_compile_count,
'shader_compile_time', hwui_shader_compile.shader_compile_time,
'shader_compile_avg', hwui_shader_compile.shader_compile_avg,
'cache_hit_count', hwui_cache_hit.cache_hit_count,
'cache_hit_time', hwui_cache_hit.cache_hit_time,
'cache_hit_avg', hwui_cache_hit.cache_hit_avg,
'cache_miss_count', hwui_cache_miss.cache_miss_count,
'cache_miss_time', hwui_cache_miss.cache_miss_time,
'cache_miss_avg', hwui_cache_miss.cache_miss_avg,
'graphics_cpu_mem_max', CAST(hwui_graphics_cpu_mem.graphics_cpu_mem_max as INT64),
'graphics_cpu_mem_min', CAST(hwui_graphics_cpu_mem.graphics_cpu_mem_min as INT64),
'graphics_cpu_mem_avg', hwui_graphics_cpu_mem.graphics_cpu_mem_avg,
'graphics_gpu_mem_max', CAST(hwui_graphics_gpu_mem.graphics_gpu_mem_max as INT64),
'graphics_gpu_mem_min', CAST(hwui_graphics_gpu_mem.graphics_gpu_mem_min as INT64),
'graphics_gpu_mem_avg', hwui_graphics_gpu_mem.graphics_gpu_mem_avg,
'texture_mem_max', CAST(hwui_texture_mem.texture_mem_max as INT64),
'texture_mem_min', CAST(hwui_texture_mem.texture_mem_min as INT64),
'texture_mem_avg', hwui_texture_mem.texture_mem_avg,
'all_mem_max', CAST(hwui_all_mem.all_mem_max as INT64),
'all_mem_min', CAST(hwui_all_mem.all_mem_min as INT64),
'all_mem_avg', hwui_all_mem.all_mem_avg
),
'skottie_animator_count', ifnull(skottie_animator.skottie_animator_count, 0),
'skottie_animator_max', ifnull(skottie_animator.skottie_animator_max, 0),
'skottie_animator_min', ifnull(skottie_animator.skottie_animator_min, 0),
'skottie_animator_avg', ifnull(skottie_animator.skottie_animator_avg, 0.0),
'dequeue_buffer_count', dequeue_buffer.dequeue_buffer_count,
'dequeue_buffer_max', dequeue_buffer.dequeue_buffer_max,
'dequeue_buffer_min', dequeue_buffer.dequeue_buffer_min,
'dequeue_buffer_avg', dequeue_buffer.dequeue_buffer_avg,
'render_time_avg', ifnull(skottie_animator.skottie_animator_avg, 0.0) + hwui_draw_frame.draw_frame_avg,
'render_time_avg_no_dequeue', ifnull(skottie_animator.skottie_animator_avg, 0.0) + hwui_draw_frame.draw_frame_avg - ifnull(dequeue_buffer.dequeue_buffer_avg, 0.0),
'ui_thread_cpu_time', ifnull(cpu_time_ui_thread.cpu_time, 0),
'rt_thread_cpu_time', ifnull(cpu_time_rt.cpu_time, 0),
'hwui_tasks_cpu_time', ifnull(cpu_time_rt_hwui_tasks.cpu_time, 0),
'skottie_animator_cpu_time', ifnull(cpu_time_skottie_animator.cpu_time, 0),
'total_cpu_time', ifnull(total_cpu_time.cpu_time, 0),
'total_gpu_time', ifnull(hwui_gpu_completion2.gpu_completion_sum, 0),
'total_time', ifnull(total_cpu_time.cpu_time, 0) + ifnull(hwui_gpu_completion2.gpu_completion_sum, 0)
)
)
FROM hwui_processes
LEFT JOIN hwui_draw_frame ON (hwui_draw_frame.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN hwui_flush_commands ON (hwui_flush_commands.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN hwui_prepare_tree ON (hwui_prepare_tree.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN hwui_gpu_completion2 ON (hwui_gpu_completion2.process_upid = hwui_processes.process_upid)
LEFT JOIN hwui_ui_record ON (hwui_ui_record.process_upid = hwui_processes.process_upid)
LEFT JOIN hwui_shader_compile ON (hwui_shader_compile.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN hwui_cache_hit ON (hwui_cache_hit.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN hwui_cache_miss ON (hwui_cache_miss.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN hwui_graphics_cpu_mem ON (hwui_graphics_cpu_mem.process_upid = hwui_processes.process_upid)
LEFT JOIN hwui_graphics_gpu_mem ON (hwui_graphics_gpu_mem.process_upid = hwui_processes.process_upid)
LEFT JOIN hwui_texture_mem ON (hwui_texture_mem.process_upid = hwui_processes.process_upid)
LEFT JOIN hwui_all_mem ON (hwui_all_mem.process_upid = hwui_processes.process_upid)
LEFT JOIN skottie_animator ON (skottie_animator.process_upid = hwui_processes.process_upid)
LEFT JOIN dequeue_buffer ON (dequeue_buffer.render_thread_id = hwui_processes.render_thread_id)
LEFT JOIN total_cpu_time ON (total_cpu_time.process_upid = hwui_processes.process_upid)
LEFT JOIN cpu_time_rt_hwui_tasks ON (cpu_time_rt_hwui_tasks.process_upid = hwui_processes.process_upid)
LEFT JOIN cpu_time_rt ON (cpu_time_rt.process_upid = hwui_processes.process_upid)
LEFT JOIN cpu_time_skottie_animator ON (cpu_time_skottie_animator.process_upid = hwui_processes.process_upid)
LEFT JOIN cpu_time_ui_thread ON (cpu_time_ui_thread.process_upid = hwui_processes.process_upid)
WHERE hwui_processes.process_name='org.skia.skottie'
)
);

View File

@ -1,23 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.skia.skottie"
android:versionCode="1"
android:versionName="1.0">
package="org.skia.skottie"
android:versionCode="1"
android:versionName="1.0">
<application
android:allowBackup="false"
android:theme="@android:style/Theme.Holo.Light"
android:name=".SkottieApplication"
android:label="Skottie">
<application
android:name=".SkottieApplication"
android:allowBackup="false"
android:label="Skottie"
android:theme="@android:style/Theme.Holo.Light">
<activity android:name=".PerfActivity">
</activity>
<activity android:name=".SkottieActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<activity android:name=".SkottieActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
<!-- END_INCLUDE(manifest) -->
</manifest>

View File

@ -0,0 +1,82 @@
package org.skia.skottie;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieDrawable;
import com.airbnb.lottie.RenderMode;
public class PerfActivity extends Activity {
int rawAssets[] = {
R.raw.star, R.raw.movie_loading, R.raw.uk, R.raw.white_material_wave_loading,
R.raw.body_movin, R.raw.check_animation, R.raw.confetti, R.raw.gears,
R.raw.hand_sanitizer, R.raw.heart_preloader, R.raw.i_was_scared_after_that_brouhaha,
R.raw.im_thirsty, R.raw.true_will, R.raw.workout_monkey_stay_healthy,
R.raw.ripple_loading_animation
};
@Override
protected void onCreate(Bundle savedInstanceState) {
//Remove title bar
this.requestWindowFeature(Window.FEATURE_NO_TITLE);
//Remove notification bar
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
// Run activity with:
// adb shell am start -n org.skia.skottie/.PerfActivity --ei renderer 0 --ei file 0
// renderer is 0 to 2, file is 0 to 14
Intent intent = getIntent();
int renderer = intent.getIntExtra("renderer", 0);
int file = intent.getIntExtra("file", 0);
if (file < 0 || file >= rawAssets.length) {
return;
}
switch (renderer) {
case 0:
// render with airbnb hardware lottie player
runLottie(rawAssets[file], true);
break;
case 1:
// render with airbnb software lottie player
runLottie(rawAssets[file], false);
break;
case 2:
// render with skottie player
runSkottie(rawAssets[file]);
break;
default:
break;
}
}
void runSkottie(int id) {
SkottieView view = new SkottieView(this);
view.setSource(getResources().openRawResource(id));
view.getSkottieAnimation().start();
setContentView(view);
}
void runLottie(int id, boolean useHardware) {
LottieAnimationView lottie = new LottieAnimationView(this);
lottie.setAnimation(id);
if (useHardware) {
lottie.setRenderMode(RenderMode.HARDWARE);
} else {
lottie.setRenderMode(RenderMode.SOFTWARE);
}
lottie.setRepeatMode(LottieDrawable.RESTART);
lottie.setRepeatCount(LottieDrawable.INFINITE);
lottie.playAnimation();
setContentView(lottie);
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
{"v":"5.5.7","meta":{"g":"LottieFiles AE 0.1.20","a":"","k":"","d":"","tc":""},"fr":60,"ip":0,"op":30,"w":300,"h":300,"nm":"All Preloaders","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[52.5,52.5,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"hasMask":true,"masksProperties":[{"inv":false,"mode":"f","pt":{"a":0,"k":{"i":[[-0.29,-1.59],[0,0],[0.05,-0.31],[2.46,-4.273],[2.662,-2.965],[3.911,-3.417],[3.76,-2.82],[5.1,-3.65],[0.348,0.308],[4.37,3.33],[4.44,3.78],[4.382,5.881],[1.126,5.435],[0.23,1.22],[0,0],[-0.06,0.26],[-0.63,2],[-6.073,3.37],[-6.437,-1.191],[-4.197,-4.783],[-0.147,-0.317],[-0.85,0.79],[-10.845,-9.997],[-1.314,-5.331]],"o":[[0,0],[-0.07,0.3],[-0.629,4.89],[-2.075,3.401],[-3.414,3.914],[-3.59,3.12],[-5,3.76],[-0.348,0.308],[-4.49,-3.16],[-4.6,-3.51],[-5.586,-4.752],[-3.326,-4.444],[-0.35,-1.28],[0,0],[0.06,-0.26],[0.44,-2],[2.11,-6.618],[5.653,-3.301],[6.278,1.037],[0.206,0.282],[1.09,-1.09],[10.777,-10.07],[4.064,3.691],[0.44,1.53]],"v":[[50.5,-15.281],[50.5,-10.811],[50.3,-9.891],[45.62,3.989],[38.5,13.559],[27.5,24.569],[16.5,33.569],[1.2,44.509],[-0.02,44.509],[-13.49,34.999],[-26.93,23.999],[-41.93,7.999],[-48.69,-7.001],[-49.5,-10.671],[-49.5,-15.281],[-49.33,-16.051],[-47.98,-22.051],[-35.24,-37.601],[-16.5,-40.871],[-0.3,-31.871],[0.23,-30.971],[2.98,-33.691],[41.32,-33.821],[49.57,-19.981]],"c":true},"ix":1},"o":{"a":0,"k":100,"ix":3},"x":{"a":0,"k":0,"ix":4},"nm":"Mask 1"}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[126.336,126.336],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":20,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"gf","o":{"a":0,"k":100,"ix":10},"r":1,"bm":0,"g":{"p":2,"k":{"a":0,"k":[0,1,0,0.2235294117647059,1,1,0.6980392156862745,0.5333333333333333],"ix":9}},"s":{"a":0,"k":[0,0],"ix":5},"e":{"a":0,"k":[100,0],"ix":6},"t":2,"h":{"a":0,"k":0,"ix":7},"a":{"a":0,"k":0,"ix":8},"nm":"Gradient Fill 1","mn":"ADBE Vector Graphic - G-Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-0.207,-0.145],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[83.088,83.088],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":30,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"5_white","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[52.5,52.5,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":0,"s":[80,84.211,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":5,"s":[90,94.737,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":9,"s":[100,105.263,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":13,"s":[125,131.579,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":15,"s":[130,136.842,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"t":17,"s":[125,131.579,100]},{"t":29,"s":[80,84.211,100]}],"ix":6}},"ao":0,"w":105,"h":105,"ip":0,"op":30,"st":0,"bm":0}],"markers":[]}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long