2014-02-12 59 views
1

我最近开始做一个速度最快的应用程序。 方法很简单:Android多线程SpeedTest有性能问题

我instanciate多个线程都下载相同的不可压缩文件,然后我计算平均下载速度。

但我觉得我有一些表演问题。当我用多个线程开始测试时,我在logCat中看到很多GC_CONCURRENT freedWAIT_FOR_CONCURRENT_GC。 我不明白来自哪里。

习惯性地这些问题似乎出现在某些circumpstances,像instanciating太多对象或对象庞大,但我不认为这是这里的情况...

这里是我的代码(简化 - 无速度计算):

public class SpeedTest extends Activity{ 

    private final int NB_THREADS = 2; 
    private long bytesIn; 
    private long downloadTime; 

    private List<Downloader> downloaders = new ArrayList<Downloader>(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState){ 

     super.onCreate(savedInstanceState); 
     setContentView(R.layout.speed_test); 

     bytesIn = 0; 

     for (int i = 0; i < NB_THREADS; i++){ 
      downloaders.add(new Downloader()); 
      downloaders.get(i).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, i); 
     } 
    } 

    private synchronized void addBytes(){ bytesIn++; } 

    private class Downloader extends AsyncTask<Integer, Void, Void>{ 

     @Override 
     protected Void doInBackground(Integer... params){ 

      Log.d("eduine", "Downloader " + params[0] + " started"); 

      try{ 

       InputStream stream = new URL("http://test-de-vitesse.ariase.com/ariasetool/1mb_random.bin").openConnection().getInputStream(); 

       while((stream.skip(1)) != 0){ 
        addBytes(); 
       } 

       stream.close(); 

      }catch (MalformedURLException e){ 
       e.printStackTrace(); 
       Log.e("eduine", "malformed url : " + e.getMessage()); 
      }catch (IOException e){ 
       e.printStackTrace(); 
       Log.e("eduine", "io error : " + e.getMessage()); 
      } 

      Log.d("eduine", "Downloader " + params[0] + " terminated"); 

      return null; 
     } 
    } 
} 

所以我想知道是否有人已经遇到此问题,或者有任何想法,为什么会出现这些表演的问题,因为它扭曲了速度的计算。

在此先感谢!


编辑:忘了发布logCat,对不起。

02-12 14:18:40.945: D/eduine(15637): Downloader 0 started 
02-12 14:18:40.955: D/eduine(15637): Downloader 1 started 
02-12 14:18:41.355: D/dalvikvm(15637): GC_CONCURRENT freed 3102K, 33% free 7552K/11240K, paused 3ms+3ms, total 20ms 
02-12 14:18:41.395: D/dalvikvm(15637): GC_CONCURRENT freed 1564K, 33% free 7533K/11240K, paused 3ms+3ms, total 18ms 
02-12 14:18:41.465: D/dalvikvm(15637): GC_CONCURRENT freed 1657K, 33% free 7537K/11240K, paused 2ms+7ms, total 20ms 
02-12 14:18:41.465: D/dalvikvm(15637): WAIT_FOR_CONCURRENT_GC blocked 8ms 
02-12 14:18:41.485: D/dalvikvm(15637): GC_CONCURRENT freed 1657K, 33% free 7541K/11240K, paused 2ms+3ms, total 17ms 
02-12 14:18:41.485: D/dalvikvm(15637): WAIT_FOR_CONCURRENT_GC blocked 10ms 
02-12 14:18:41.505: D/dalvikvm(15637): GC_CONCURRENT freed 1669K, 33% free 7533K/11240K, paused 3ms+1ms, total 17ms 
02-12 14:18:41.505: D/dalvikvm(15637): WAIT_FOR_CONCURRENT_GC blocked 10ms 
02-12 14:18:41.525: D/dalvikvm(15637): GC_CONCURRENT freed 1609K, 33% free 7537K/11240K, paused 3ms+3ms, total 16ms 
02-12 14:18:41.545: D/dalvikvm(15637): GC_CONCURRENT freed 1669K, 34% free 7529K/11240K, paused 3ms+2ms, total 16ms 
02-12 14:18:41.545: D/dalvikvm(15637): WAIT_FOR_CONCURRENT_GC blocked 13ms 

等等等等......直到

02-12 14:21:14.795: D/dalvikvm(16164): GC_CONCURRENT freed 1537K, 33% free 7533K/11240K, paused 3ms+2ms, total 16ms 
02-12 14:21:14.815: D/dalvikvm(16164): GC_CONCURRENT freed 1537K, 33% free 7533K/11240K, paused 2ms+2ms, total 15ms 
02-12 14:21:14.835: D/dalvikvm(16164): GC_CONCURRENT freed 1537K, 33% free 7533K/11240K, paused 2ms+3ms, total 16ms 
02-12 14:21:14.845: D/eduine(16164): Downloader 0 terminated at 1392211274859 
02-12 14:21:14.855: D/dalvikvm(16164): GC_CONCURRENT freed 1545K, 34% free 7529K/11240K, paused 3ms+3ms, total 17ms 
02-12 14:21:14.915: D/eduine(16164): Downloader 1 terminated at 1392211274925 

编辑:使用线程池同样的问题,下面的代码。

public class SpeedTest extends Activity{ 

    private final int NB_OF_THREADS = 8; 
    private long bytesIn; 
    private long start; 

    ExecutorService executorService = new ThreadPoolExecutor(NB_OF_THREADS, NB_OF_THREADS, 1, TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(NB_OF_THREADS, true), new ThreadPoolExecutor.CallerRunsPolicy()); 

    @Override 
    protected void onCreate(Bundle savedInstanceState){ 

     super.onCreate(savedInstanceState); 
     setContentView(R.layout.speed_test); 

     bytesIn = 0; 
     start = System.currentTimeMillis(); 
     for (int i = 0; i < NB_OF_THREADS; i++) executorService.submit(new Downloader(i)); 
    } 

    private synchronized void addByte(){ bytesIn++; } 

    private class Downloader implements Runnable{ 

     private int id; 
     private InputStream stream; 
     private long downloadTime; 

     public Downloader(int _id){ id = _id; } 

     @Override 
     public void run(){ 

      Log.d("eduine", "Downloader " + id + " started at " + System.currentTimeMillis()); 

      try{ 

       HttpURLConnection connexion = (HttpURLConnection) new URL("http://test-de-vitesse.ariase.com/ariasetool/1mb_random.bin").openConnection(); 
       connexion.setUseCaches(false); 
       stream = connexion.getInputStream(); 

       while((stream.skip(1)) != 0) addByte(); 

       stream.close(); 

       downloadTime = (System.currentTimeMillis() - start); 
       downloadTime = downloadTime == 0 ? 1 : downloadTime; 

      }catch (MalformedURLException e){ 
       e.printStackTrace(); 
       Log.e("eduine", "malformed url : " + e.getMessage()); 
      }catch (IOException e){ 
       e.printStackTrace(); 
       Log.e("eduine", "io error : " + e.getMessage()); 
      } 

      Log.d("eduine", "Downloader " + id + " terminated at " + System.currentTimeMillis()); 
     } 
    } 
} 

回答

0

线程对象本身为其堆栈消耗大量内存。为了从实例化/空闲线程中清理你的测试,不要使用AsyncTask(它创建线程),而是事先创建一个固定的线程池,开始测试,等待它结束,然后关闭线程池。

+0

即使使用ThreadPool我也有同样的问题。发布我的代码上面,如果你想看到它。 – eduine

+0

看起来像海量内存分配 - 删除发生在别的地方。制作最小程序并在Android上运行。制作更小的程序并使用gc登录在桌面上运行它。 –

+0

我终于找到了错误,实际上有一个分配问题,我在我的循环中重新分配了一个字节[],所以有这么大量的内存使用。现在解决,谢谢。 – eduine