Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9142981
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 17, 20262026-06-17T09:54:39+00:00 2026-06-17T09:54:39+00:00

I’m new to threads (don’t kill me for my implementation below :) and I

  • 0

I’m new to threads (don’t kill me for my implementation below 🙂 and I need to do multiple blurring passes of pixels on a separate thread (see below). It’s not the most efficient implementation of box blur (it’s from Gaussian Filter without using ConvolveOp) but the performance spikes don’t occur on the Nexus 7 tablet but they do occur on the Nexus 4 phone.

I’ve posted my testing sample (running on Android 4.2 – see below).

I don’t think it is caused by the GC thrashing the memory (it doesn’t coincide with the spikes).

I think it might be something to do with cache locality or hardware memory thrashing – but I’m not sure.

What would cause the spikes? Sometimes they are sudden onset – e.g. spike of 50%. Sometimes they are slow onset – e.g. spikes increasing/decreasing monotonically, with spikes as follows -> 5%, 10%, 20%, 10%, 5%.

How could I stop them from occurring when doing heavy array processing?

This doesn’t occur on the Nexus 7 tablet which I have also tested (see results below)

Side question: What is the best way to sleep and restart my thread correctly (new to threads)?


MainActivity.java


package com.example.test;

import android.os.Bundle;
import android.app.Activity;

public class MainActivity extends Activity {

    private MainThread thread;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        thread = new MainThread();

        thread.setRunning(true);
        thread.start();

        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onResume() {

        super.onResume();
        thread.setRunning(true);

    }

    @Override
    protected void onPause() {

        super.onPause();
        thread.setRunning(false);

    }

}

MainThread.java


package com.example.test;

import android.util.Log;

public class MainThread extends Thread {

    int[] pixels;
    int kernel_rows = 2;
    int kernel_cols = 2;
    int width = 512;
    int height = 512;

    @Override
    public void run() {

        while (running) {

            long start = System.currentTimeMillis();

            for (int row = kernel_rows / 2; row < height - kernel_rows / 2; row++) {
                for (int col = kernel_cols / 2; col < width - kernel_cols / 2; col++) {

                    float pixel = 0;

                    // iterate over each pixel in the kernel
                    for (int row_offset = 0; row_offset < kernel_rows; row_offset++) {
                        for (int col_offset = 0; col_offset < kernel_cols; col_offset++) {

                            // subtract by half the kernel size to center the
                            // kernel
                            // on the pixel in question
                            final int row_index = row + row_offset
                                    - kernel_rows / 2;
                            final int col_index = col + col_offset
                                    - kernel_cols / 2;

                            pixel += pixels[row_index * width + col_index] * 1.0f / 4.0f;

                        }
                    }

                    pixels[row * width + col] = (int) pixel;

                }

            }

            long stop = System.currentTimeMillis();

            long delta = stop - start;

            Log.d("DELTA", Long.toString(delta));

        }

    }

    private boolean running;

    public void setRunning(boolean running) {

        this.pixels = new int[512 * 512];
        this.running = running;

    }

}

Logs


Nexus 4 phone (ms):

01-13 10:56:05.663: D/DELTA(13507): 76
01-13 10:56:05.773: D/DELTA(13507): 107
01-13 10:56:05.843: D/DELTA(13507): 77
01-13 10:56:05.923: D/DELTA(13507): 75
01-13 10:56:06.053: D/DELTA(13507): 127
01-13 10:56:06.133: D/DELTA(13507): 78
01-13 10:56:06.213: D/DELTA(13507): 81
01-13 10:56:06.293: D/DELTA(13507): 80
01-13 10:56:06.353: D/DELTA(13507): 77
01-13 10:56:06.433: D/DELTA(13507): 79
01-13 10:56:06.513: D/DELTA(13507): 79
01-13 10:56:06.624: D/DELTA(13507): 106
01-13 10:56:06.694: D/DELTA(13507): 76

Nexus 7 tablet (ms):

01-13 11:01:03.283: D/DELTA(3909): 84
01-13 11:01:03.373: D/DELTA(3909): 85
01-13 11:01:03.453: D/DELTA(3909): 85
01-13 11:01:03.543: D/DELTA(3909): 84
01-13 11:01:03.623: D/DELTA(3909): 85
01-13 11:01:03.703: D/DELTA(3909): 84
01-13 11:01:03.793: D/DELTA(3909): 85
01-13 11:01:03.873: D/DELTA(3909): 84
01-13 11:01:03.963: D/DELTA(3909): 85
01-13 11:01:04.043: D/DELTA(3909): 84
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-17T09:54:41+00:00Added an answer on June 17, 2026 at 9:54 am

    I think I may have somewhat mitigated this effect on the Nexus 4. There is still some variability in calculation consistency but it is bearable – I think – can’t see too many huge spikes – outside of thread startup/shutdown. I’ve done this using the Android NDK and c p_threads to spawn a native thread that is mostly left alone by Java (or so I’m told) until the foreground application is changed or closed.

    Here is the code:


    MainActivity.java


    package com.example.test;
    
    import android.os.Bundle;
    import android.app.Activity;
    
    public class MainActivity extends Activity {
    
        static {
    
            System.loadLibrary("native");
    
        }
    
        private native void init();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
    
            super.onCreate(savedInstanceState);
    
            // Initializes and spawns native thread
            init();
    
            setContentView(R.layout.activity_main);
    
        }
    
    }
    

    native.c


    (which should be put into a jni folder at the root of the Android project)

    #include <time.h>
    #include <pthread.h>
    #include <jni.h>
    #include <android/log.h>
    
    #define APPNAME "DELTA"
    
    int* pixels;
    int kernel_rows = 2;
    int kernel_cols = 2;
    int width = 60;
    int height = 39;
    
    int running = 1;
    
    // from android samples
    /* return current time in milliseconds */
    static double now_ms(void) {
    
        struct timespec res;
        clock_gettime(CLOCK_REALTIME, &res);
        return 1000.0 * res.tv_sec + (double) res.tv_nsec / 1e6;
    
    }
    
    // initialize thread/begin it
    jint Java_com_example_testa_MainActivity_init(JNIEnv* env, jobject javaThis) {
    
        int i1 = 1;
    
        pthread_t thread;
        void *run();
    
        pthread_create(&thread, NULL, run, &i1);
        pthread_join(thread, NULL);
    
        return 0;
    
    }
    
    // thread function
    void *run(int *x) {
    
        // init pixels within thread
        pixels = (int*) malloc(sizeof(int) * width * height);
    
        // loop until stopped - java won't interfere
        // unless closed/switch application (or so I'm told)
        while (running) {
    
            double start = now_ms();
    
            int row, col, row_offset, col_offset;
    
            for (row = kernel_rows / 2; row < height - kernel_rows / 2; row++) {
    
                for (col = kernel_cols / 2; col < width - kernel_cols / 2; col++) {
    
                    float pixel = 0;
    
                    // iterate over each pixel in the kernel
                    for (row_offset = 0; row_offset < kernel_rows; row_offset++) {
                        for (col_offset = 0; col_offset < kernel_cols;
                                col_offset++) {
    
                            // subtract by half the kernel size to center the
                            // kernel
                            // on the pixel in question
    
                            int row_index = row + row_offset - kernel_rows / 2;
                            int col_index = col + col_offset - kernel_cols / 2;
    
                            pixel += pixels[row_index * width + col_index] * 1.0f
                                    / 4.0f;
    
                        }
    
                    }
    
                    pixels[row * width + col] = (int) pixel;
    
                }
    
            }
    
            double end = now_ms();
    
            double delta = end - start;
    
            __android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "%f", delta);
    
        }
    
        pthread_exit(0);
    
    }
    

    Android.mk


    (which should be put into a jni folder at the root of the Android project)

    LOCAL_PATH := $(call my-dir)
    MY_PATH := $(LOCAL_PATH)
    include $(call all-subdir-makefiles)
    
    include $(CLEAR_VARS)
    
    LOCAL_PATH := $(MY_PATH)
    
    LOCAL_MODULE    := native
    LOCAL_LDLIBS := -llog
    LOCAL_SRC_FILES := native.c
    
    include $(BUILD_SHARED_LIBRARY)
    

    Summary


    Reduced cost of code by ~20-30% and decreased variability by an order of magnitude.

    The code is compiled by executing the ndk-build command from the NDK library provided by Android at the root folder (found here: http://developer.android.com/tools/sdk/ndk/index.html).


    Results


    Nexus 4 (ms):

    01-14 13:41:21.132: V/DELTA(23679): 56.554199
    01-14 13:41:21.192: V/DELTA(23679): 58.568604
    01-14 13:41:21.252: V/DELTA(23679): 59.484131
    01-14 13:41:21.302: V/DELTA(23679): 56.768066
    01-14 13:41:21.362: V/DELTA(23679): 54.692383
    01-14 13:41:21.412: V/DELTA(23679): 51.823730
    01-14 13:41:21.472: V/DELTA(23679): 55.668945
    01-14 13:41:21.522: V/DELTA(23679): 56.920654
    01-14 13:41:21.582: V/DELTA(23679): 56.371094
    01-14 13:41:21.642: V/DELTA(23679): 58.507568
    01-14 13:41:21.702: V/DELTA(23679): 59.697754
    01-14 13:41:21.752: V/DELTA(23679): 53.990723
    01-14 13:41:21.812: V/DELTA(23679): 55.669189
    

    Nexus 7 (ms):

    01-14 13:41:25.685: V/DELTA(2916): 65.867920
    01-14 13:41:25.745: V/DELTA(2916): 65.986816
    01-14 13:41:25.815: V/DELTA(2916): 66.685059
    01-14 13:41:25.885: V/DELTA(2916): 67.033936
    01-14 13:41:25.945: V/DELTA(2916): 65.703857
    01-14 13:41:26.015: V/DELTA(2916): 66.653076
    01-14 13:41:26.085: V/DELTA(2916): 66.922119
    01-14 13:41:26.145: V/DELTA(2916): 67.030029
    01-14 13:41:26.215: V/DELTA(2916): 67.014893
    01-14 13:41:26.285: V/DELTA(2916): 67.034912
    01-14 13:41:26.345: V/DELTA(2916): 67.089844
    01-14 13:41:26.415: V/DELTA(2916): 65.860107
    01-14 13:41:26.485: V/DELTA(2916): 65.642090
    01-14 13:41:26.545: V/DELTA(2916): 65.574951
    01-14 13:41:26.615: V/DELTA(2916): 65.991943
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm new to using the Perl treebuilder module for HTML parsing and can't figure
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I want use html5's new tag to play a wav file (currently only supported
In my XML file chapters tag has more chapter tag.i need to display chapters
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I don't have much knowledge about the IPv6 protocol, so sorry if the question
I'm trying to convert HTML to plain text. I get many &\#8217; &\#8220; etc.
Does anyone know how can I replace this 2 symbol below from the string
I need a function that will clean a strings' special characters. I do NOT
I have thousands of HTML files to process using Groovy/Java and I need to

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.