bertrandmartel / speed-test-lib

:cloud: JSpeedTest : speed test client library for Java/Android
MIT License
381 stars 119 forks source link

Continuous sampling of UL and DL rate #5

Closed arianaa30 closed 8 years ago

arianaa30 commented 8 years ago

Very interesting library. I want to develop a profiler Android app that every say 4 seconds gets UL and DL rates and saves as a .csv file (plus I will add some extra info such as time stamp, and others). I quickly noticed I can set time interval for DL and UL, right? Does it given me enough flexibility to do my tasks? How easy is it to do that? Any working examples?

bertrandmartel commented 8 years ago

You can set a custom report interval with a Timer instance, and calling :

Here is a working example. Replace :

timer.scheduleAtFixedRate(task, 0, 400);

with

timer.scheduleAtFixedRate(task, 0, 4000);
arianaa30 commented 8 years ago

Cool. The java version works perfectly! But it actually doesn't run forever; it runs until the upload is finished. Maybe I should manually add a loop to do it continuously. Any other easier ways?

BTw, I was trying to use it on Android following your example on using an AsyncTask :-|

bertrandmartel commented 8 years ago

In that case, you could use startDownloadRepeat which will start a download on the specified host/uri/port, and will restart the download when it is finished until repeatWindow is elapsed. reportPeriodMillis is the number of millis between each report dispatched in repeatListener, an interface that will also tell you when your time window is finished :

    /**
     * Start repeat download task
     *
     * @param hostname           server hostname
     * @param port               server port
     * @param uri                uri to fetch to download file
     * @param repeatWindow       time window for the repeated download in milliseconds
     * @param reportPeriodMillis time interval between each report in milliseconds
     * @param repeatListener     listener for download repeat task completion & reports
     */
    public void startDownloadRepeat(String hostname,
                                    int port,
                                    String uri,
                                    int repeatWindow,
                                    int reportPeriodMillis,
                                    IRepeatListener repeatListener)

You can find an example of its usage here

This startDownloadRepeat was designed to provide the user a fixed duration download in case your speed test server endpoint has too small file size

For your usecase, you could set any time duration you want. You can still call speedTestSocket.forceStopTask(); when you are done.

For the upload method, doing the same as download repeat was not needed because content-length is (usually) set by the client (whereas for download you may not have an uri that match your need for small/big files). Nevertheless, trying not to be dependent on your speed test server your are using it could be worth adding a startUploadRepeat to the library, I will look at that in the next days. But for now, for upload, you can upload a "large enough" file and stop uploading when you want to, or re-starting a new upload as you suggest. The upload example is located here.

Let me know if you have any issue

arianaa30 commented 8 years ago

Thanks. I'll work on this. Please add the uploadRepeat. I'll wait for it!

arianaa30 commented 8 years ago

BTW, in the example file, I downloaded Apache logging libraries. But there LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR); which is not resolved. Where is it coming from? Tnx!

bertrandmartel commented 8 years ago

LogUtils is a helper class for Logs located in examples folder. If you are developing on Android, you can replace all those log entries with android.util.Log

arianaa30 commented 8 years ago

Haha I didn't notice the .java files! Thanks. So yeah, I'm targeting Android eventually.

arianaa30 commented 8 years ago

Well, the repeat option doesn't really work for me. The rate keeps increasing continuously (I use report.getTransferRateBit()/(1024*1024) for Mbps). Is this the bitrate in that moment, or the average until that point? Any workaround for my problem? I need to report the average bitrate of whatever received within 3 seconds, maybe starting from connection initiation. Probably I should just have a loop, everytime initiate the connection from beginning using regular downloadRate method (not repeat one).

A better approach can be to initiate once, and everytime start from the beginning of file so at least we get real relative rates. I am guessing the increase is because of TCP's congestion control.

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
1.0753003
9.209792
18.219315
15.779048
19.689457
21.617085
22.16147
22.337727
22.529728
arianaa30 commented 8 years ago

I'm actually done with implementing it using the repeat class. The rate is very relevant to the size of files! The bigger the file, the higher the rates!

Anyways, do you happen to know when you can update the uploadRepeat?

bertrandmartel commented 8 years ago

I have a working setup for Android with startDownloadRepeat


public class SpeedTestTask extends AsyncTask<Void, Void, String> {

    private final static String TAG = SpeedTestTask.class.getSimpleName();

    /**
     * speed examples server host name.
     */
    private final static String SPEED_TEST_SERVER_HOST = "2.testdebit.info";

    /**
     * spedd examples server uri.
     */
    private final static String SPEED_TEST_SERVER_URI_DL = "/fichiers/10Mo.dat";

    /**
     * speed examples server port.
     */
    private final static int SPEED_TEST_SERVER_PORT = 80;

    /**
     * speed test duration set to 11s.
     */
    private static final int SPEED_TEST_DURATION = 60000;

    /**
     * amount of time between each speed test report set to 1s.
     */
    private static final int REPORT_INTERVAL = 1000;

    /**
     * set socket timeout to 3s.
     */
    private static final int SOCKET_TIMEOUT = 3000;

    private SpeedTestSocket speedTestSocket = new SpeedTestSocket();

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

        speedTestSocket.setSocketTimeout(SOCKET_TIMEOUT);

        speedTestSocket.addSpeedTestListener(new ISpeedTestListener() {

            @Override
            public void onDownloadPacketsReceived(final long packetSize, final float transferRateBitPerSeconds, final
            float
                    transferRateOctetPerSeconds) {
                //called when download is finished
            }

            @Override
            public void onDownloadError(final SpeedTestError speedTestError, final String errorMessage) {

                if (speedTestError != SpeedTestError.FORCE_CLOSE_SOCKET) {
                    Log.e(TAG, "download error");
                }
            }

            @Override
            public void onUploadPacketsReceived(final long packetSize, final float transferRateBitPerSeconds, final
            float transferRateOctetPerSeconds) {
                //called when upload is finished
            }

            @Override
            public void onUploadError(final SpeedTestError speedTestError, final String errorMessage) {

                Log.e(TAG, "upload error");
            }

            @Override
            public void onDownloadProgress(final float percent, final SpeedTestReport downloadReport) {
                //notify download progress
            }

            @Override
            public void onUploadProgress(final float percent, final SpeedTestReport uploadReport) {
                //notify upload progress
            }
        });

        speedTestSocket.startDownloadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_DL,
                SPEED_TEST_DURATION, REPORT_INTERVAL, new
                        IRepeatListener() {
                            @Override
                            public void onFinish(final SpeedTestReport report) {

                                Log.i(TAG, "---------------------DOWNLOAD FINISHED------------------");

                                Log.i(TAG, "progress             : " + report.getProgressPercent() + "%");
                                Log.i(TAG, "transfer rate bit    : " + report.getTransferRateBit() + "b/s");
                                Log.i(TAG, "transfer rate octet  : " + report.getTransferRateOctet() + "B/s");
                                Log.i(TAG, "uploaded for now     : " + report.getTemporaryPacketSize()
                                        + "/" + report.getTotalPacketSize());

                                if (report.getStartTime() > 0) {
                                    Log.i(TAG, "amount of time       : " +
                                            ((report.getReportTime() - report.getStartTime()) / 1000) + "s");
                                }
                                Log.i(TAG, "---------------------------------------------------------");
                            }

                            @Override
                            public void onReport(final SpeedTestReport report) {

                                Log.i(TAG, "---------------current download report------------------");

                                Log.i(TAG, "progress             : " + report.getProgressPercent() + "%");
                                Log.i(TAG, "transfer rate bit    : " + report.getTransferRateBit() + "b/s");
                                Log.i(TAG, "transfer rate octet  : " + report.getTransferRateOctet() + "B/s");
                                Log.i(TAG, "uploaded for now     : " + report.getTemporaryPacketSize()
                                        + "/" + report.getTotalPacketSize());

                                if (report.getStartTime() > 0) {
                                    Log.i(TAG, "amount of time       : " +
                                            ((report.getReportTime() - report.getStartTime()) / 1000) + "s");
                                }
                                Log.i(TAG, "---------------------------------------------------------");
                            }
                        });

        return null;
    }
}

This give me something like


I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 84.971664%
I/SpeedTestTask: transfer rate bit    : 4.6240992E7b/s
I/SpeedTestTask: transfer rate octet  : 5780124.0B/s
I/SpeedTestTask: uploaded for now     : 2.9891078E8/300000000
I/SpeedTestTask: amount of time       : 50s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 86.638336%
I/SpeedTestTask: transfer rate bit    : 4.649368E7b/s
I/SpeedTestTask: transfer rate octet  : 5811710.0B/s
I/SpeedTestTask: uploaded for now     : 3.0473043E8/310000000
I/SpeedTestTask: amount of time       : 51s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 88.305%
I/SpeedTestTask: transfer rate bit    : 3.6740672E7b/s
I/SpeedTestTask: transfer rate octet  : 4592584.0B/s
I/SpeedTestTask: uploaded for now     : 3.102706E8/320000000
I/SpeedTestTask: amount of time       : 52s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 89.973335%
I/SpeedTestTask: transfer rate bit    : 4.5548456E7b/s
I/SpeedTestTask: transfer rate octet  : 5693557.0B/s
I/SpeedTestTask: uploaded for now     : 3.160365E8/320000000
I/SpeedTestTask: amount of time       : 53s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 91.64%
I/SpeedTestTask: transfer rate bit    : 4.2044548E7b/s
I/SpeedTestTask: transfer rate octet  : 5255568.5B/s
I/SpeedTestTask: uploaded for now     : 3.2130736E8/330000000
I/SpeedTestTask: amount of time       : 54s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 93.305%
I/SpeedTestTask: transfer rate bit    : 4.6457996E7b/s
I/SpeedTestTask: transfer rate octet  : 5807249.5B/s
I/SpeedTestTask: uploaded for now     : 3.2752797E8/330000000
I/SpeedTestTask: amount of time       : 55s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 94.971664%
I/SpeedTestTask: transfer rate bit    : 4.847984E7b/s
I/SpeedTestTask: transfer rate octet  : 6059980.0B/s
I/SpeedTestTask: uploaded for now     : 3.3294502E8/340000000
I/SpeedTestTask: amount of time       : 56s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 96.638336%
I/SpeedTestTask: transfer rate bit    : 4.6582276E7b/s
I/SpeedTestTask: transfer rate octet  : 5822784.5B/s
I/SpeedTestTask: uploaded for now     : 3.3877178E8/340000000
I/SpeedTestTask: amount of time       : 57s
I/SpeedTestTask: ---------------------------------------------------------
I/SpeedTestTask: ---------------current download report------------------
I/SpeedTestTask: progress             : 98.305%
I/SpeedTestTask: transfer rate bit    : 4.684538E7b/s
I/SpeedTestTask: transfer rate octet  : 5855672.5B/s
I/SpeedTestTask: uploaded for now     : 3.4471158E8/350000000
I/SpeedTestTask: amount of time       : 58s
I/SpeedTestTask: ---------------------------------------------------------

As you can see, bit rate per second fluctuates, can you check that code in your environment ?

I'm planning to implement startUploadRepeat for tomorrow

arianaa30 commented 8 years ago

Yes, this is similar what I wrote. It works. But the fluctuations are high which is normal. But I don't know why when you change the download file size to say 1Mb, the rates get smaller! I don't have a reason for that.

Anyways, I'll wait for your upload then. Basically at a given time stamp, I need to profile both download and upload rate.

bertrandmartel commented 8 years ago

I have released v1.12 with

You can find an example of startUploadRepeat here

Let me know it that fix your issue

arianaa30 commented 8 years ago

Thanks. I updated my app with it. Not yet tested.

bertrandmartel commented 8 years ago

You can either

or

You can call your next download/upload request in your Timer callback for the first case or in onFinish callback for 2nd case.

arianaa30 commented 8 years ago

Can you help me with the second method? I'm a bit confused. Here are both the DL and UL:

            speedTestSocket.startDownloadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_DL,
                    SPEED_TEST_DURATION, REPORT_INTERVAL, new
                            IRepeatListener() {
                                @Override
                                public void onFinish(final SpeedTestReport report) {
                                }

                                @Override
                                public void onReport(final SpeedTestReport report) {
                                    String result = report.getTransferRateBit()/(1024) +" Kbps (DOWNLOAD), ";
                                    String timeStamp= (report.getReportTime() - report.getStartTime()) / 1000 + "s";

                                    result+=timeStamp;

                                    Log.i("speed test", "speed test: "+result);
                                    publishProgress(result);
                                }
                            });

            speedTestSocket.startUploadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_UL,
                    SPEED_TEST_DURATION, REPORT_INTERVAL, FILE_SIZE, new
                            IRepeatListener() {

                                @Override
                                public void onFinish(SpeedTestReport report) {
                                    // TODO Auto-generated method stub

                                }

                                @Override
                                public void onReport(SpeedTestReport report) {
                                    String result = report.getTransferRateBit()/(1024) +" Kbps (UPLOAD), ";
                                    String timeStamp= (report.getReportTime() - report.getStartTime()) / 1000 + "s";

                                    result+=timeStamp;

                                    Log.i("speed test", "speed test: "+result);
                                    publishProgress(result);
                                }

            });
arianaa30 commented 8 years ago

I think putting them in two different functions (or threads) and one calling the other in its finish() is what you mean:

We start by calling startDownload(); and it goes on...

        void startDownload(){
            speedTestSocket.startDownloadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_DL,
                    SPEED_TEST_DURATION, REPORT_INTERVAL, new
                            IRepeatListener() {
                                @Override
                                public void onFinish(final SpeedTestReport report) {
                                    startUpload();
                                }

                                @Override
                                public void onReport(final SpeedTestReport report) {
                                    String result = report.getTransferRateBit()/(1024) +" Kbps (DOWNLOAD), ";
                                    String timeStamp= (report.getReportTime() - report.getStartTime()) / 1000 + "s";

                                    result+=timeStamp;

                                    Log.i("speed test", "speed test: "+result);
                                    publishProgress(result);
                                }
                            });
}

        void startUpload(){
            speedTestSocket.startUploadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_UL,
                    SPEED_TEST_DURATION, REPORT_INTERVAL, FILE_SIZE, new
                            IRepeatListener() {

                                @Override
                                public void onFinish(SpeedTestReport report) {
                                    // TODO Auto-generated method stub
                                    startDownload();
                                }

                                @Override
                                public void onReport(SpeedTestReport report) {
                                    String result = report.getTransferRateBit()/(1024) +" Kbps (UPLOAD), ";
                                    String timeStamp= (report.getReportTime() - report.getStartTime()) / 1000 + "s";

                                    result+=timeStamp;

                                    Log.i("speed test", "speed test: "+result);
                                    publishProgress(result);
                                }
            });
        }
arianaa30 commented 8 years ago

This shows error. Maybe because of having the same connection?!

08-26 14:40:51.201: E/AndroidRuntime(10797):    at fr.bmartel.speedtest.SpeedTestSocket.connectAndExecuteTask(SpeedTestSocket.java:330)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at fr.bmartel.speedtest.SpeedTestSocket.writeUpload(SpeedTestSocket.java:991)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at fr.bmartel.speedtest.SpeedTestSocket.startUpload(SpeedTestSocket.java:978)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at fr.bmartel.speedtest.SpeedTestSocket.startUploadRepeat(SpeedTestSocket.java:683)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at fr.bmartel.speedtest.SpeedTestSocket.startUploadRepeat(SpeedTestSocket.java:858)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at com.example.profiler.SpeedTestTask2.startUpload(SpeedTestTask2.java:127)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at com.example.profiler.SpeedTestTask2$2.onFinish(SpeedTestTask2.java:110)
08-26 14:40:51.201: E/AndroidRuntime(10797):    at fr.bmartel.speedtest.SpeedTestSocket$3.run(SpeedTestSocket.java:756)
bertrandmartel commented 8 years ago

Thank you for reporting this bug, I've released to v1.13 with a bugfix. The threadpool was not reinitialized. I have also added an example chaining download + upload (repeat API) here. Sorry for that, let me know if that works for you

arianaa30 commented 8 years ago

Thanks! But it doesn't give me the desired output. OK, what it does is whenever the download is finished, go to upload. Assuming these as my settings:

    private static final int SPEED_TEST_DURATION = 100000;
    private static final int REPORT_INTERVAL = 3000;
    private static final int SOCKET_TIMEOUT = 3000;

So it downloads until 100s!

And btw, if we set both the time window and report interval to 3000, then no report is out! We are already finished. And if we set SPEED_TEST_DURATION = 3001, then I get download error after the first report!

arianaa30 commented 8 years ago

This is what I get from your chainingRepeat example:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.
3723.0227 DOWNLOAD
4119.9604 DOWNLOAD
4431.499 DOWNLOAD
4431.499 DOWNLOAD FINISHED
16:35:20.232 [pool-2-thread-1] ERROR fr.bmartel.speedtest.examples.RepeatDownloadExample - Socket Closed caused by socket force close
    /**
     * speed test duration set to 11s.
     */
    private static final int SPEED_TEST_DURATION = 3000;

    /**
     * amount of time between each speed test report set to 1s.
     */
    private static final int REPORT_INTERVAL = 1000;

    /**
     * set socket timeout to 3s.
     */
    private static final int SOCKET_TIMEOUT = 3000;
bertrandmartel commented 8 years ago

This is normal behavior, you get Socket Closed caused by socket force close because forceStopTask is called and your callback onDownloadError is called with FORCE_CLOSE_SOCKET to warn you socket has been closed because of forceStopTask API and not because there was other issues such as INVALID_HTTP_RESPONSE, SOCKET_ERROR or SOCKET_TIMEOUT. To catch error

if (speedTestError != SpeedTestError.FORCE_CLOSE_SOCKET) {
   //socket was unexpectedly closed, check speedTestError variable to see what happened
}
bertrandmartel commented 8 years ago

I've released v1.14 with another bugfix for the threadpool. Multiple successive download / upload work without problem with this version

bertrandmartel commented 8 years ago

For the issue with the test duration / report interval with the same value not displaying any report, this is somewhat normal, you will actually get a report in onFinish(final SpeedTestReport report) so if the report interval is >= to test duration, you will actually receive one report in onFinish callback

arianaa30 commented 8 years ago

For the test duration, yes, it is normal. Right, we can look into the report from Finish(). Let me test the new version!

arianaa30 commented 8 years ago

Ok, now we are one step further. We can log only the finish which happens every 3 seconds. private static final int SPEED_TEST_DURATION = 3000;

    /**
     * amount of time between each speed test report set to 1s.
     */
    private static final int REPORT_INTERVAL = 3000;

    /**
     * set socket timeout to 3s.
     */
    private static final int SOCKET_TIMEOUT = 3000;

But is the logic of chaining example correct?! Here we only get two sequences, 1 DL and then 1 UL. Probably we should manually add reference to download in the finish() of Upload listener?

17:24:51.875 [pool-2-thread-1] ERROR fr.bmartel.speedtest.examples.RepeatDownloadExample - Socket Closed caused by socket force close
40775.05 DOWNLOAD FINISHED
6828.4775 UPLOAD FINISHED
bertrandmartel commented 8 years ago

You can do something like this if you want to download + upload twice :

private int chainCount = 2;

private void startDownload() {

    speedTestSocket.startDownloadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_DL,
            SPEED_TEST_DURATION, REPORT_INTERVAL, new
                    IRepeatListener() {
                        @Override
                        public void onFinish(final SpeedTestReport report) {

                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                                LOGGER.debug("---------------------DOWNLOAD FINISHED------------------");
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                            }
                            LogUtils.logReport(report, LOGGER);

                            startUpload();
                        }

                        @Override
                        public void onReport(final SpeedTestReport report) {
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("---------------current download report------------------");
                            }
                            LogUtils.logReport(report, LOGGER);
                        }
                    });
}

private void startUpload() {

    speedTestSocket.startUploadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT,
            SPEED_TEST_SERVER_URI_UL,
            SPEED_TEST_DURATION, REPORT_INTERVAL, FILE_SIZE, new
                    IRepeatListener() {
                        @Override
                        public void onFinish(final SpeedTestReport report) {

                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                                LOGGER.debug("---------------------UPLOAD " +
                                        "FINISHED------------------");
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                            }
                            LogUtils.logReport(report, LOGGER);

                            chainCount--;

                            if (chainCount > 0) {
                                startDownload();
                            }
                        }

                        @Override
                        public void onReport(final SpeedTestReport report) {
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("---------------current upload " +
                                        "report------------------");
                            }
                            LogUtils.logReport(report, LOGGER);
                        }
                    });
}

And call in your thread

startDownload();

This gives me

--------------------------------------------------------
---------------------DOWNLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 1241451.1b/s
transfer rate octet  : 155181.39B/s
uploaded for now     : 1.0E7/10000000
amount of time       : 3s
--------------------------------------------------------
--------------------------------------------------------
---------------------UPLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 584698.9b/s
transfer rate octet  : 73087.36B/s
uploaded for now     : 1000000.0/1000000
amount of time       : 3s
--------------------------------------------------------
--------------------------------------------------------
---------------------DOWNLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 3875788.0b/s
transfer rate octet  : 484473.5B/s
uploaded for now     : 1.0E7/10000000
amount of time       : 3s
--------------------------------------------------------
--------------------------------------------------------
---------------------UPLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 732746.3b/s
transfer rate octet  : 91593.29B/s
uploaded for now     : 1000000.0/1000000
amount of time       : 3s
--------------------------------------------------------
arianaa30 commented 8 years ago

Right. This is what I also proposed the other time. This works great! Thanks! I hope adding GPS point to the profiling isn't a problem. Because that also has a listener and integrating all these together is not that easy...

arianaa30 commented 8 years ago

I was just going to sleep, but was thinking about this. What was the fix you made that the biyrate results now make more sense?

Sent from my phone. Pls excuse typos and brevity.

On Aug 26, 2016 5:41 PM, "Bertrand Martel" notifications@github.com wrote:

You can do something like this if you want to download + upload twice :

private int chainCount = 2;

private void startDownload() {

    speedTestSocket.startDownloadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT, SPEED_TEST_SERVER_URI_DL,
            SPEED_TEST_DURATION, REPORT_INTERVAL, new
                    IRepeatListener() {
                        @Override
                        public void onFinish(final SpeedTestReport report) {

                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                                LOGGER.debug("---------------------DOWNLOAD FINISHED------------------");
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                            }
                            LogUtils.logReport(report, LOGGER);

                            startUpload();
                        }

                        @Override
                        public void onReport(final SpeedTestReport report) {
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("---------------current download report------------------");
                            }
                            LogUtils.logReport(report, LOGGER);
                        }
                    });
}

private void startUpload() {

    speedTestSocket.startUploadRepeat(SPEED_TEST_SERVER_HOST, SPEED_TEST_SERVER_PORT,
            SPEED_TEST_SERVER_URI_UL,
            SPEED_TEST_DURATION, REPORT_INTERVAL, FILE_SIZE, new
                    IRepeatListener() {
                        @Override
                        public void onFinish(final SpeedTestReport report) {

                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                                LOGGER.debug("---------------------UPLOAD " +
                                        "FINISHED------------------");
                                LOGGER.debug(LogUtils.LOG_REPORT_SEPARATOR);
                            }
                            LogUtils.logReport(report, LOGGER);

                            chainCount--;

                            if (chainCount > 0) {
                                startDownload();
                            }
                        }

                        @Override
                        public void onReport(final SpeedTestReport report) {
                            if (LOGGER.isDebugEnabled()) {
                                LOGGER.debug("---------------current upload " +
                                        "report------------------");
                            }
                            LogUtils.logReport(report, LOGGER);
                        }
                    });
}

And call in your thread

startDownload();

This gives me


---------------------DOWNLOAD FINISHED------------------

progress : 100.0% transfer rate bit : 1241451.1b/s transfer rate octet : 155181.39B/s uploaded for now : 1.0E7/10000000

amount of time : 3s


---------------------UPLOAD FINISHED------------------

progress : 100.0% transfer rate bit : 584698.9b/s transfer rate octet : 73087.36B/s uploaded for now : 1000000.0/1000000

amount of time : 3s


---------------------DOWNLOAD FINISHED------------------

progress : 100.0% transfer rate bit : 3875788.0b/s transfer rate octet : 484473.5B/s uploaded for now : 1.0E7/10000000

amount of time : 3s


---------------------UPLOAD FINISHED------------------

progress : 100.0% transfer rate bit : 732746.3b/s transfer rate octet : 91593.29B/s uploaded for now : 1000000.0/1000000

amount of time : 3s

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/akinaru/speed-test-lib/issues/5#issuecomment-242868989, or mute the thread https://github.com/notifications/unsubscribe-auth/AFQSzUjsccr_NOjRtr0OVYjteJtMUBCiks5qj2uGgaJpZM4JsNZG .

bertrandmartel commented 8 years ago

The average was calculated between the new value and the previous transfer rate which was wrong. Now, each transfer rate value is stored and the average is calculated between all the value + the new value. This only concern the startDownloadRepeat and startUploadRepeat API

bertrandmartel commented 8 years ago

I've released v1.15 with another bugfix for a correct calculation of the last transfer rate we get in getRepeatReport internal API which is the method giving you the report when using startDownloadRepeat and startUploadRepeat. Now the average is calculated between all the previous terminated download/upload + the current one with a weight depending on the packet number downloaded/uploaded for now. It should give you a more precised transfer rate value

arianaa30 commented 8 years ago

Thats great! I'll check it out now...

Sent from my phone. Pls excuse typos and brevity.

On Aug 27, 2016 8:03 AM, "Bertrand Martel" notifications@github.com wrote:

I've released v1.15 with another bugfix for a correct calculation of the last transfer rate we get in getRepeatReport internal API which is the method giving you the report when using startDownloadRepeat and startUploadRepeat. Now the average is calculated between all the previous terminated download/upload + the current one with a weight depending on the packet number downloaded/uploaded for now. It should give you a more precised transfer rate value

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/akinaru/speed-test-lib/issues/5#issuecomment-242916025, or mute the thread https://github.com/notifications/unsubscribe-auth/AFQSzWqNjg9Vx9hTb_TeNVjG2namH6X0ks5qkDWYgaJpZM4JsNZG .

arianaa30 commented 8 years ago

Everything is great. I'm not sure if you want to change it, but the report time always gives the same value which makes sense because we are starting from beginning on every part, but in the whole chaining scenario it does not make sense.

String timeStamp= (report.getReportTime() - report.getStartTime()) / 1000 + "s";

bertrandmartel commented 8 years ago

Based on the current example, you can do

Add two global variable

private static int reportTime = SPEED_TEST_DURATION * chainCount * 2 / 1000;

private static int reportCount;

in startDownloadRepeat() 's onFinish callback :

@Override
public void onFinish(final SpeedTestReport report) {

    ....

    displayTime(report);
    reportCount++;

    startUpload();
}

In startUploadRepeat 's onFinish callback

@Override
public void onFinish(final SpeedTestReport report) {

   .....

    chainCount--;
    displayTime(report);
    reportCount++;

    if (chainCount > 0) {
        startDownload();
    }
}

The display method :

private void displayTime(SpeedTestReport report) {

    System.out.println("report time : " + ((reportCount * SPEED_TEST_DURATION + report.getReportTime() - report
            .getStartTime()) / 1000) + " / " +
            reportTime );
}

This give :

--------------------------------------------------------
---------------------DOWNLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 1.6106805E7b/s
transfer rate octet  : 2013350.6B/s
uploaded for now     : 5000000.0/5000000
amount of time       : 3s
--------------------------------------------------------
report time : 3 / 12
--------------------------------------------------------
---------------------UPLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 1.1702719E7b/s
transfer rate octet  : 1462839.9B/s
uploaded for now     : 3997635.0/5000000
amount of time       : 3s
--------------------------------------------------------
report time : 6 / 12
--------------------------------------------------------
---------------------DOWNLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 2.1058128E7b/s
transfer rate octet  : 2632266.0B/s
uploaded for now     : 7302100.0/8000000
amount of time       : 3s
--------------------------------------------------------
report time : 9 / 12
--------------------------------------------------------
---------------------UPLOAD FINISHED------------------
--------------------------------------------------------
progress             : 100.0%
transfer rate bit    : 1.1384874E7b/s
transfer rate octet  : 1423109.2B/s
uploaded for now     : 3932100.0/4000000
amount of time       : 3s
--------------------------------------------------------
report time : 12 / 12
arianaa30 commented 8 years ago

Hi, One thing that I notice sometimes is that when there is a connection failure (no wifi is available) and network goes away, the profiling process stops and continues later which violates our timing deadline (the time counter is still the same). Is there any ways to handle it? So in those cases, it should calculate the "no connection" as 0 and go on for every period! I will do more experiments to see if this always happens. Because we need to profile with high speed and this is important and the profiling shouldn't halt.

arianaa30 commented 8 years ago

I just did some tests and yeah...when I was moving and wifi was switching, the rates halted and actually didn't update even when I got Wifi again. These disconnections should also be a part of my profiling data and it is like the rates are 0 (which makes sense). Are you an Android guy? Maybe if needed you can take a look at my super simple code attached? Profiler.zip I just read values of your rates (each every 2 seconds) and log it every 4 seconds when both DL and UL are calculated.

bertrandmartel commented 8 years ago

If a download/upload error is received during startDownloadRepeat or startUploadRepeat, socket is closed and onFinish is not called. I dont understand when you say the process continues later. Because onFinish is not called, there wont be any more DL/UL. From your code, you seem never to stop DL/UL as there dont seem to have any stop condition (or maybe Im missing something). In ISpeedTestListener callback onDownloadError & onUploadError, if you receive anything other than FORCE_CLOSE_SOCKET, you could continue or stop your process to your likings. If you want to "calculate the "no connection" as 0" you can do this from those error callback and go on to next UL/DL if you want to

arianaa30 commented 8 years ago

OK, the thing is for a portion of time where there is no network, we shouldn't flag the whole period as 0. Only that portion contributes to 0. But if there is no other ways, it is fine to count the whole period as 0.

Right now all my listeners are empty, right? So basically if anything happens, it doesn't take any actions.

"if you receive anything other than FORCE_CLOSE_SOCKET, you could continue or stop your process to your likings." How can I continue?!

bertrandmartel commented 8 years ago

You can try something like this :

@Override
public void onDownloadError(final SpeedTestError speedTestError, final String errorMessage) {

    if (speedTestError != SpeedTestError.FORCE_CLOSE_SOCKET) {
        reportCount++;
        startUpload();
    }
}

@Override
public void onUploadError(final SpeedTestError speedTestError, final String errorMessage) {

    if (speedTestError != SpeedTestError.FORCE_CLOSE_SOCKET) {
        chainCount--;
        reportCount++;

        if (chainCount > 0) {
            startDownload();
        }
    }
}
arianaa30 commented 8 years ago

I see. Plus I guess I have to pass 0 as the result of that report.

arianaa30 commented 8 years ago

Interesting! I got a -30515 kbps as a download rate at some point!

bertrandmartel commented 8 years ago

I'll investigate that issue, thank you for reporting

bertrandmartel commented 8 years ago

I've just released v1.16 which fix this issue. The problem was that timeStart which is the timestamp at the beginning of the test (download or upload) was set in reading thread and in writing thread for download. Now these timing variables are only set just before reading task here. For upload there was no change for that, there were already set just after flushing HTTP header and before flushing the uploaded file here.

The problem you have observed occurred when there was a significant timing after the reading task ended because it is launched in a singlethreaded threadpool and the next download task to be run will have to wait for the threadpool to be empty for the new task. Thus the timeStart of the new task was > timeEnd of previous task which would result in negative transfer rate

arianaa30 commented 8 years ago

Cool. I will update my code with v1.16.

arianaa30 commented 8 years ago

What is the reason of having if (speedTestError != SpeedTestError.FORCE_CLOSE_SOCKET)? What is different with this type of error? I just wanted to do resume the app even when no connection exists, so I removed this condition. But I see my app stopping unexpectedly in the beginning! Maybe this is thrown in the very beginning of running app?

bertrandmartel commented 8 years ago

FORCE_CLOSE_SOCKET means the socket was closed because api forceStopTask was called. This is called internally when downloadRepeat or uploadRepeat is finished. If you call forceStopTask yourself anywhere in your code, it will trigger FORCE_CLOSE_SOCKET which means the socket is closed as it is expected to be. Everything other than FORCE_CLOSE_SOCKET is unexpected.

arianaa30 commented 8 years ago

Hi, Do you have any documentations on how speed tests are technically done? Is it similar to here? https://support.speedtest.net/hc/en-us/articles/203845400-How-does-the-test-itself-work-How-is-the-result-calculated-

BTW, do you think I shall use "2.testdebit.info" for server, or my own local server (in my university)? I'm in the US.

bertrandmartel commented 8 years ago

This library doesn't calculate latency/jitter, it doesn't adjust the chunk size depending on the connection speed either and doesn't provide pre-estimation of the connection speed based on small chunk sent to/from server. It doesn't detect anomaly either, for instance here, it is taking away X% slowest chunk and X% fastest chunk downloaded.

You should choose your speed test server depending on the latency you got. The smaller latency the better. 2.testdebit.info is located in France so you shouldn't use it in the US. You have a list of speed test server here

The most reliable tool I know to perform speed test is iperf : https://github.com/esnet/iperf

arianaa30 commented 8 years ago

Cool. Thanks for the list of servers. How should I use a specific server then? There should be a repository for a test file. This is not mentioned there!

bertrandmartel commented 8 years ago

I have added some notes about Speed test issue in the readme here. I also added a non-exhaustive list of speed test server which includes speedtest.net servers with the list I gave you above. Also I have recently added FTP support so FTP server with anonymous access can be used with this library now