Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading large models on android #145

Closed
NeluQi opened this issue Feb 23, 2021 · 8 comments
Closed

Loading large models on android #145

NeluQi opened this issue Feb 23, 2021 · 8 comments

Comments

@NeluQi
Copy link

NeluQi commented Feb 23, 2021

Good day. The problem is the lack of RAM on the device when loading large models.

There are large models consisting of many gtlf files.

What is your recommendation for loading large models?

@atteneder
Copy link
Owner

Hi,

3D model optimization in general is a huge topic that could span multiple books. There's even lot's of software that tackles the problem (more or less well and some quite expensive). I'll try to only give some concrete, glTF/glTFast related tips.

Profile First

Seriously, open the Unity Profiler and make a deep memory snapshot to see what exactly within your glTF files is taking up the most space and if that is justified.

Texture

If your textures use up a lot of RAM:

  • Are they absolutely needed? (I've seen single color 2k textures and normal maps with close to zero impact)
  • Can you get away with scaling them down (reduce resolution) ?
  • Use the KTX texture format with Basis Universal compression. They'll use 4-8 times less RAM at runtime

Geometry

  • Don't use embed (base 64 encoded) buffers
  • Don't re-use vertex buffers across primitives
  • Remove unused vertex attributes (No texture applied => No need for UVs; Rough reflecion only => no need for tangents)

An open source tool that worked wonders on glTFs for me in the past is meshoptimizer/gltfpack. It can reduce the mesh and encode textures to KTX. Make sure you don't use its mesh compression as it is not supported in glTFast yet.

hth

@NeluQi
Copy link
Author

NeluQi commented Feb 23, 2021

What is the reason for the large GC?
Currently, GC in ManagetHeap.UsedSize takes up the most memory space when loading.

Android apps just crash when RAM is full, is there a way to fix this?

What is more optimal to create a new GLTFast.GLTFast and call the load, or use the same GLTFast.GLTFast?

image
image
image
image

`*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Version '2020.2.5f1 (e2c53f129de5)', Build type 'Development', Scripting Backend 'mono', CPU 'armeabi-v7a'
Build fingerprint: 'samsung/dream2qltezh/dream2qltechn:7.1/N2G48H/G9550ZHU1AQEE:user/release-keys'
Revision: '12'
ABI: 'arm'
Timestamp: 2021-02-23 16:48:51+0300
pid: 5702, tid: 5722, name: UnityMain >>> com.ProjectTest.Viewer <<<
uid: 10192
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
r0 00000084 r1 00000007 r2 d4a61ec5 r3 00000084
r4 058ceb04 r5 a4426afc r6 b7079c44 r7 b1ef0010
r8 b7079c8c r9 d3c4b008 r10 05584f39 r11 b7079b28
ip 06d3f918 sp b7079b08 lr 06c23198 pc 0c4175b4

backtrace:
#00 pc 000175b4 /system/lib/arm/nb/libc.so

managed backtrace:
#00 (wrapper managed-to-native) UnityEngine.JsonUtility:FromJsonInternal (string,object,System.Type)
#1 UnityEngine.JsonUtility:FromJson (string,System.Type) </Users/bokken/buildslave/unity/build/Modules/JSONSerialize/Public/JsonUtility.bindings.cs:42>
#2 UnityEngine.JsonUtility:FromJson<T_REF> (string) </Users/bokken/buildslave/unity/build/Modules/JSONSerialize/Public/JsonUtility.bindings.cs:30>
#3 GLTFast.GLTFast:ParseJson (string) <F:\Developer\ProjectTest\Viewer\Library\PackageCache\com.atteneder.gltfast@f728859\Runtime\Scripts\GltFast.cs:375>
#4 GLTFast.GLTFast/d__55:MoveNext () <F:\Developer\ProjectTest\Viewer\Library\PackageCache\com.atteneder.gltfast@f728859\Runtime\Scripts\GltFast.cs:318>
#5 System.Runtime.CompilerServices.AsyncTaskMethodBuilder1<bool>:Start<GLTFast.GLTFast/<ParseJsonAndLoadBuffers>d__55> (GLTFast.GLTFast/<ParseJsonAndLoadBuffers>d__55&) <0x7f> #06 GLTFast.GLTFast:ParseJsonAndLoadBuffers (string,System.Uri) <0x137> #07 GLTFast.GLTFast/<LoadGltf>d__58:MoveNext () <F:\Developer\ProjectTest\Viewer\Library\PackageCache\com.atteneder.gltfast@f7288594b6\Runtime\Scripts\GltFast.cs:549> #08 System.Runtime.CompilerServices.AsyncTaskMethodBuilder1:Start<GLTFast.GLTFast/d__58> (GLTFast.GLTFast/d__58&) <0x7f>
#9 GLTFast.GLTFast:LoadGltf (string,System.Uri) <0x137>
#10 GLTFast.GLTFast/d__53:MoveNext () <F:\Developer\ProjectTest\Viewer\Library\PackageCache\com.atteneder.gltfast@f728859\Runtime\Scripts\GltFast.cs:266>
#11 System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:InvokeMoveNext (object) <0x87>
#12 System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) <0x1b7>
#13 System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) <0x2b>
#14 System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:Run () <0xbf>
#15 System.Threading.Tasks.AwaitTaskContinuation:InvokeAction (object) <0x3f>
#16 System.Threading.Tasks.AwaitTaskContinuation:RunCallback (System.Threading.ContextCallback,object,System.Threading.Tasks.Task&) <0x67>
#17 System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation:Run (System.Threading.Tasks.Task,bool) <0xeb>
#18 System.Threading.Tasks.Task:FinishContinuations () <0x297>
#19 System.Threading.Tasks.Task:FinishStageThree () <0x9f>
#20 System.Threading.Tasks.Task1<TResult_REF>:TrySetResult (TResult_REF) <0xff> #21 System.Runtime.CompilerServices.AsyncTaskMethodBuilder1<TResult_REF>:SetResult (TResult_REF) <0xa7>
#22 GLTFast.Loading.DefaultDownloadProvider/d__0:MoveNext () <F:\Developer\ProjectTest\Viewer\Library\PackageCache\com.atteneder.gltfast@f728859\Runtime\Scripts\DefaultDownloadProvider.cs:29>
#23 System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:InvokeMoveNext (object) <0x87>
#24 System.Threading.ExecutionContext:RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) <0x1b7>
#25 System.Threading.ExecutionContext:Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) <0x2b>
#26 System.Runtime.CompilerServices.AsyncMethodBuilderCore/MoveNextRunner:Run () <0xbf>
#27 System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter:RunAction (object) <0x3f>
#28 UnityEngine.UnitySynchronizationContext/WorkRequest:Invoke () </Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/UnitySynchronizationContext.cs:153>
#29 UnityEngine.UnitySynchronizationContext:Exec () </Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/UnitySynchronizationContext.cs:83>
#30 UnityEngine.UnitySynchronizationContext:ExecuteTasks () </Users/bokken/buildslave/unity/build/Runtime/Export/Scripting/UnitySynchronizationContext.cs:107>
#31 (wrapper runtime-invoke) object:runtime_invoke_void (object,intptr,intptr,intptr)

stack:
b7079ac8 98f69081
b7079acc 06c4963c /data/app/com.ProjectTest.Viewer-1/lib/arm/libmonobdwgc-2.0.so
b7079ad0 0000007e
b7079ad4 b7079ab0
b7079ad8 00000001
b7079adc 0c210c2c /system/lib/arm/liblog.so
b7079ae0 00000001
b7079ae4 a26f7ce0
b7079ae8 00000082
b7079aec d4a61ec5 /system/lib/libLLVM.so
b7079af0 058ceb04
b7079af4 a4426afc
b7079af8 b7079c44
b7079afc b1ef0010
b7079b00 b7079c8c
b7079b04 06c23184 /data/app/com.ProjectTest.Viewer-1/lib/arm/libmonobdwgc-2.0.so
#00 b7079b08 b7079c8c
b7079b0c 00000084
b7079b10 00000004
b7079b14 00000007
b7079b18 a26f7ce0
b7079b1c 00000000
b7079b20 00000004
b7079b24 00000000
b7079b28 b7079b48
b7079b2c 06c18838 /data/app/com.ProjectTest.Viewer-1/lib/arm/libmonobdwgc-2.0.so
b7079b30 b7079c8c
b7079b34 06c230a0 /data/app/com.ProjectTest.Viewer-1/lib/arm/libmonobdwgc-2.0.so
b7079b38 00000000
b7079b3c a26f7ce0
b7079b40 00000004
b7079b44 00000000
`

@atteneder
Copy link
Owner

I presume you profiled the Editor in Playmode. It's recommended to always profile (debug) builds, since the editor runtime distorts the profiling data. Take a look at the Profiler docs to learn more.
I usually profile a standalone build, since it's the fastest.

The heavy stuff in Others is likely Editor related and won't be a problem on the device.

Scene Memory is the interesting bit. Looks like Textures are not a problem at all and there's quite some mesh data, but nothing extreme.

What Android device do your run this on? How much memory does it have?
Looks a bit suspicious, but I have to test your data myself. Feel free to provide it, if you can.

@NeluQi
Copy link
Author

NeluQi commented Feb 23, 2021

I presume you profiled the Editor in Playmode. It's recommended to always profile (debug) builds, since the editor runtime distorts the profiling data. Take a look at the Profiler docs to learn more.
I usually profile a standalone build, since it's the fastest.

The heavy stuff in Others is likely Editor related and won't be a problem on the device.

Scene Memory is the interesting bit. Looks like Textures are not a problem at all and there's quite some mesh data, but nothing extreme.

What Android device do your run this on? How much memory does it have?
Looks a bit suspicious, but I have to test your data myself. Feel free to provide it, if you can.

Thanks for helping me.
Tested on Android 7. 3 GB of RAM. In my task, BIM models are used (ifc -> gtlf). gltf models were divided into files of 10-100 mb. There are about 1000 such files. Total weight 2.3 GB. Unfortunately, I cannot share the model.

When the RAM is full, the application crashes, is there any way to handle this exception? (try cath - doesn't work). I would like to stop loading when the RAM threshold is reached

I will attach screenshots of profiling on the device.

I work with BIM models. They can be huge. Consist of one large file or be split into 2-5k small files. Can you give me a couple of tips for dealing with these conditions? Now I do not load the entire model at once, but only the gtlf closest to the camera (When exporting to gtlf, there is metadata on the coordinates of each individual gtlf file). However, I would like to load as much as possible, ideally the entire model.

image
image
image
image

@atteneder
Copy link
Owner

Thanks for helping me.

you're welcome

Tested on Android 7. 3 GB of RAM. In my task, BIM models are used (ifc -> gtlf). gltf models were divided into files of 10-100 mb. There are about 1000 such files. Total weight 2.3 GB. Unfortunately, I cannot share the model.

I understand. Yes, the sheer mass of geometry is too much.

When the RAM is full, the application crashes, is there any way to handle this exception? (try cath - doesn't work). I would like to stop loading when the RAM threshold is reached

I don't know. Not sure about Android, but iOS informs apps when they are about to run out of memory, which is very vague and sometimes very conservative. You won't get a number of how much memory you've got left.

Also not sure if glTFast can fail gracefully when memory runs out. Should be investigated.

I work with BIM models. They can be huge. Consist of one large file or be split into 2-5k small files. Can you give me a couple of tips for dealing with these conditions? Now I do not load the entire model at once, but only the gtlf closest to the camera (When exporting to gtlf, there is metadata on the coordinates of each individual gtlf file). However, I would like to load as much as possible, ideally the entire model.

  • CAD/BIM data is often too complex. Try to optimize and reduce the models either manually or with dedicated tools
  • Discard glTFs that are not needed/visible anymore. This way you could regain some of the RAM. Combined with caching this might improve your situation.

@NeluQi
Copy link
Author

NeluQi commented Feb 23, 2021

Thank you very much, I will think in this direction

Can you give a hint about caching? What kind of cache are you talking about? The files themselves are downloaded in advance to devices

@atteneder
Copy link
Owner

Can you give a hint about caching? What kind of cache are you talking about? The files themselves are downloaded in advance to devices

Yes, this is what I meant. Caching glTF files (including .bin buffers and textures) on local drives.

@atteneder
Copy link
Owner

I've created #147 with regards to running out of memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants