Forum Xamarin.Android
We are excited to announce that the Xamarin Forums are moving to the new Microsoft Q&A experience. Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

We encourage you to head over to Microsoft Q&A for .NET for posting new questions and get involved today.

Starting a blocking GC Explicit

Im facing a UI freeze for a few seconds and my log shows an explicit running of the GC during that time.

Log:

(29311): Starting a blocking GC Explicit
03-02 12:55:30.656 I/art     (29311): Explicit concurrent mark sweep GC freed 26(1024B) AllocSpace objects, 6(53MB) LOS objects, 32% free, 33MB/49MB, paused 170us total 23.027ms
03-02 12:55:30.657 D/Mono    (29311): GC_TAR_BRIDGE bridges 204 objects 245 colors 204 ignored 13 sccs 204 xref 15 cache 0/0 setup 0.06ms tarjan 0.11ms scc-setup 0.07ms gather-xref 0.01ms xref-setup 0.00ms cleanup 0.04ms
03-02 12:55:30.657 D/Mono    (29311): GC_BRIDGE: Complete, was running for 24.92ms
03-02 12:55:30.657 D/Mono    (29311): GC_MAJOR: (LOS overflow) time 9.80ms, stw 12.35ms los size: 15636K in use: 14758K
03-02 12:55:30.657 D/Mono    (29311): GC_MAJOR_SWEEP: major size: 1872K in use: 845K
[0:] (1)                          @@@ Copy WI Constructor 92
[0:] (1)                          @@@ Default WI Constructor 93
[0:] (1)    (->)                        ImageProcessing.ImageProcessingModel.Resample   
[0:] (1)                              Resample Averaging to W=1400  H=1813
03-02 12:55:30.734 I/art     (29311): Starting a blocking GC Explicit
03-02 12:55:30.750 I/art     (29311): Explicit concurrent mark sweep GC freed 71(2504B) AllocSpace objects, 0(0B) LOS objects, 32% free, 33MB/49MB, paused 190us total 15.100ms
03-02 12:55:30.751 D/Mono    (29311): GC_TAR_BRIDGE bridges 197 objects 237 colors 197 ignored 11 sccs 197 xref 15 cache 0/0 setup 0.06ms tarjan 0.11ms scc-setup 0.06ms gather-xref 0.01ms xref-setup 0.00ms cleanup 0.04ms
03-02 12:55:30.751 D/Mono    (29311): GC_BRIDGE: Complete, was running for 17.08ms
03-02 12:55:30.751 D/Mono    (29311): GC_MAJOR: (LOS overflow) time 5.46ms, stw 6.71ms los size: 40164K in use: 39282K
03-02 12:55:30.751 D/Mono    (29311): GC_MAJOR_SWEEP: major size: 1872K in use: 844K
[0:] (1)    (<-)                        ImageProcessing.ImageProcessingModel.Resample     elapsed: 00:01.259
[0:] (1)                          dstImage  W 1400, H 1813,  /data/user/0/capture/files/.images/job20170302125443/.display/scan2_DisplayBase.jpg
[0:] (1)    (<-)                    ImageProcessing.ImageProcessingModel.ProcessWorkingImage      elapsed: 00:01.413
[0:] (1)    (->)                    ImageProcessing.ImageProcessingModel.SaveWorkingImage   
03-02 12:55:32.059 I/Choreographer(29311): Skipped 102 frames!  The application may be doing too much work on its main thread.
03-02 12:55:32.432 I/art     (29311): Starting a blocking GC Explicit
03-02 12:55:32.451 I/art     (29311): Explicit concurrent mark sweep GC freed 928(21KB) AllocSpace objects, 1(9MB) LOS objects, 27% free, 42MB/58MB, paused 218us total 19.424ms
03-02 12:55:32.452 D/Mono    (29311): GC_TAR_BRIDGE bridges 1 objects 1 colors 1 ignored 0 sccs 1 xref 0 cache 0/0 setup 0.10ms tarjan 0.01ms scc-setup 0.03ms gather-xref 0.00ms xref-setup 0.00ms cleanup 0.02ms
03-02 12:55:32.452 D/Mono    (29311): GC_BRIDGE: Complete, was running for 20.26ms
03-02 12:55:32.452 D/Mono    (29311): GC_MINOR: (Nursery full) time 2.23ms, stw 4.80ms promoted 1K major size: 1872K in use: 846K los size: 52196K in use: 51314K
[0:] (1)    (<-)                    ImageProcessing.ImageProcessingModel.SaveWorkingImage     elapsed: 00:00.520
[0:] (1)    (<-)                ImageProcessing.ImageProcessingModel.ProcessImage     elapsed: 00:02.270
[0:] (1)    (->)                ImageProcessing.ImageProcessingModel.ProcessImage   
[0:] (1)                      srcImage  /data/user/0/capture/files/.images/job20170302125443/.display/scan2_DisplayBase.jpg
[0:] (1)    (->)                    ImageProcessing.ImageProcessingModel.LoadWorkingImage   
[0:] (1)                          @@@ Default WI Constructor 94
[0:] (1)    (<-)                    ImageProcessing.ImageProcessingModel.LoadWorkingImage     elapsed: 00:00.230
[0:] (1)                      @@@ Default WI Constructor 95
[0:] (1)    (->)                    ImageProcessing.ImageProcessingModel.ProcessWorkingImage    
[0:] (1)                          srcImage  W 1400, H 1813, 
03-02 12:55:32.888 I/art     (29311): Starting a blocking GC Explicit
03-02 12:55:32.908 I/art     (29311): Explicit concurrent mark sweep GC freed 8(280B) AllocSpace objects, 3(33MB) LOS objects, 35% free, 28MB/44MB, paused 175us total 19.709ms
03-02 12:55:32.909 D/Mono    (29311): GC_TAR_BRIDGE bridges 199 objects 240 colors 199 ignored 13 sccs 199 xref 15 cache 0/0 setup 0.06ms tarjan 0.11ms scc-setup 0.07ms gather-xref 0.01ms xref-setup 0.00ms cleanup 0.04ms
03-02 12:55:32.909 D/Mono    (29311): GC_BRIDGE: Complete, was running for 21.36ms
03-02 12:55:32.909 D/Mono    (29311): GC_MAJOR: (LOS overflow) time 13.25ms, stw 15.68ms los size: 10940K in use: 10063K
03-02 12:55:32.909 D/Mono    (29311): GC_MAJOR_SWEEP: major size: 1872K in use: 843K
[0:] (1)                          @@@ Copy WI Constructor 96
[0:] (1)                          @@@ Default WI Constructor 97
[0:] (1)    (->)                        ImageProcessing.ImageProcessingModel.Rotate 
[0:] (1)    (<-)                        ImageProcessing.ImageProcessingModel.Rotate   elapsed: 00:00.177
[0:] (1)                          @@@ Rotated 90  id 97
[0:] (1)                          dstImage  W 1813, H 1400,  /data/user/0/capture/files/.images/job20170302125443/.display/scan2_Display.jpg
[0:] (1)    (<-)                    ImageProcessing.ImageProcessingModel.ProcessWorkingImage      elapsed: 00:00.263
[0:] (1)    (->)                    ImageProcessing.ImageProcessingModel.SaveWorkingImage   
03-02 12:55:33.139 D/Mono    (29311): [0x7c5f7e5450] hill climbing, change max number of threads 6
03-02 12:55:33.482 I/art     (29311): Starting a blocking GC Explicit
03-02 12:55:33.503 I/art     (29311): Explicit concurrent mark sweep GC freed 930(21KB) AllocSpace objects, 2(19MB) LOS objects, 35% free, 28MB/44MB, paused 217us total 21.207ms
03-02 12:55:33.504 D/Mono    (29311): GC_TAR_BRIDGE bridges 198 objects 238 colors 198 ignored 11 sccs 198 xref 15 cache 0/0 setup 0.13ms tarjan 0.15ms scc-setup 0.12ms gather-xref 0.01ms xref-setup 0.00ms cleanup 0.06ms
03-02 12:55:33.504 D/Mono    (29311): GC_BRIDGE: Complete, was running for 23.45ms
03-02 12:55:33.504 D/Mono    (29311): GC_MAJOR: (Minor allowance) time 10.30ms, stw 13.03ms los size: 20856K in use: 19978K
03-02 12:55:33.504 D/Mono    (29311): GC_MAJOR_SWEEP: major size: 1872K in use: 844K
[0:] (1)    (<-)                    ImageProcessing.ImageProcessingModel.SaveWorkingImage     elapsed: 00:00.475
[0:] (1)    (<-)                ImageProcessing.ImageProcessingModel.ProcessImage     elapsed: 00:01.033
[0:] (1)    (<-)            ImageProcessing.ImageProcessingModel.RenderDisplayImage   elapsed: 00:03.339

I don't understand why the GC keeps running intensively this is actually giving a bad UI experience. Please find below the code , Im basically using a RecyclerView fashioned as a viewflipper, exploiting its swipe to dismiss to load the next image. Also at a time only one image is loaded, yet the GC runs drastically affecting the performance.

public class ThumbnailPageOfCardAdapter : RecyclerView.Adapter, ItemTouchHelperAdapter
    {
        CapturedImage thumbnailDetaiPropertyChangedEvent;
        BaseActivity activity;
        private List<String> mItems = new List<string>();
        Bitmap imageBitmap;

        ViewModelMaster vmMaster;
        BitmapFactory.Options options;
        GridViewHolder gridItemHolder;
        Utilities _utility;
        public ThumbnailPageOfCardAdapter(BaseActivity activity)
            : base()
        {
            this.activity = activity;
            mItems.Clear();

            //a dummy string is maintained in the list to mimic the adapter changes by adding and removing. 
            //This cause the calling of OnBindViewHolder whenever a change occurs. 
            //The layout is then set with the corresponing image bitmap.
            mItems.Add("Dummy String");
            vmMaster = ViewModelMaster.Instance;
            _utility = Utilities.Instance;
            _utility.AppCombat = activity;

            options = new BitmapFactory.Options();
            options.InJustDecodeBounds = false;
            options.InBitmap=imageBitmap;
            options.InPreferredConfig = Bitmap.Config.Argb8888;
        }


        public override int ItemCount
        {
            get
            { return mItems.Count; }
        }


        public override long GetItemId(int position)
        {
            return base.GetItemId(position);
        }

        public void OnItemDelete()
        {
            NotifyDataSetChanged();
        }

        public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
        {
            gridItemHolder = holder as GridViewHolder;
            RecycleImageBitmap();
            setImage();
            setAnimation(gridItemHolder.ItemView, position);
        }


        public void RecycleImageBitmap()
        {
            if (imageBitmap != null)
            {
                imageBitmap.Recycle();
                imageBitmap = null;
            }
        }

        public void setImage()
        {
            imageBitmap = BitmapFactory.DecodeFile(vmMaster.ViewerVM.DisplayFile.Filename, options);
            if (imageBitmap.Height < 1000 && imageBitmap.Width < 1000)
            {
                Bitmap resizedBitmap = Bitmap.CreateScaledBitmap(imageBitmap, imageBitmap.Width * 4, imageBitmap.Height * 4, false);
                gridItemHolder._detailImage.SetImageBitmap(resizedBitmap);
            }
            else {
                gridItemHolder._detailImage.SetImageBitmap(imageBitmap);
            }
        }

        private void setAnimation(View viewToAnimate, int position)
        {
            // If the bound view wasn't previously displayed on screen, it's animated
            Animation animation;
            if (ThumbnailDetail._swipeDirection == ThumbnailDetail.SwipeDirection.Right)
                animation = AnimationUtils.LoadAnimation(activity, Resource.Animation.SlideInLeft);
            else
                animation = AnimationUtils.LoadAnimation(activity, Resource.Animation.SlideInRight);
            viewToAnimate.StartAnimation(animation);

        }
        public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
        {
            var inflater = (LayoutInflater)activity.GetSystemService(Context.LayoutInflaterService);
            View view = inflater.Inflate(Resource.Layout.ThumbnailDetailCardLayout, parent, false);

            return new GridViewHolder(view);
        }

        public class GridViewHolder : RecyclerView.ViewHolder, ItemTouchHelperViewHolder
        {
            public ImageView _detailImage;
            public GridViewHolder(View itemView)
                : base(itemView)
            {
                _detailImage = (ImageView)itemView.FindViewById(Resource.Id.thumbnail_detail);
            }
            public void onItemSelected()
            {
            }

            public void onItemClear()
            {
            }
        }

        public bool onItemMove(int fromPosition, int toPosition)
        {
            return false;
        }

        public void onItemDismiss(int position)
        {
            if (ThumbnailDetail._swipeDirection == ThumbnailDetail.SwipeDirection.Right)
            {
                if (!(_utility.selectedThumbnailDetail <= 0))
                {
                    _utility.selectedThumbnailDetail = _utility.selectedThumbnailDetail - 1;
                }
            }
            else
            {
                if (!(_utility.selectedThumbnailDetail >= (vmMaster.ViewerVM.ImageCollection.Count - 1)))
                {
                    _utility.selectedThumbnailDetail = _utility.selectedThumbnailDetail + 1;
                }
            }    
            RecycleImageBitmap();
            mItems.RemoveAt(position);
            //a dummy string is maintained in the list to mimic the adapter changes by adding and removing.
            mItems.Insert(position, "Dummy String");
            NotifyItemInserted(position);
            NotifyDataSetChanged();
        }
    }

Posts

  • DavidBlankleyDavidBlankley USMember ✭✭

    Did you solve this? I've recently had the GC start going crazy on me as well so I'm curious if there were specific things you did to resolve it. And yes, I'm dealing with Images too.

    Notably, iOS runs about 10x faster.

  • TheGreatOneTheGreatOne USMember ✭✭

    Where ya able to come up with a solution?

  • LjusnanLjusnan DEMember ✭✭✭

    Maybe you should use LargeHeap=true. Also, there is a new option for a experimental concurrent garbage collection in the project properties. You could try this.

Sign In or Register to comment.