Firebase存储的上传/下载速度非常慢

时间:2016-08-21 15:02:11

标签: android firebase firebase-storage

故事

我在我的应用中使用Firebase存储将大文件上传到Firebase存储。文件大多是视频,有时甚至可能超过2 GB。

我做了什么

这就是我所做的。

UploadTask originalUpload = originalDestination.putFile(Uri.fromFile(originalSource));
            mCurrentUploadTask = originalUpload;
            originalUpload.addOnProgressListener(mOnProgressUpdateListener);
originalUpload.addOnSuccessListener(mOriginalSuccessListener);

请注意,我也将这些同步任务转换为异步,因为我需要在后台处理所有内容,

Tasks.await(originalUpload);

问题

这个问题很奇怪而且出乎意料。上传/下载效果很好,但速度非常慢。

我的互联网连接速度很好,只有1 MBps,但这些文件永远不会以这种速度传输。它大约是100-150 KBps,几乎是我网络可用速度的15%。

在提出此声明之前,我已经多次在几个不同的网络上测试。无处,我发现Firebase充分利用了可用带宽,而其他非Firebase下载/上传工作则全速运行。

我的应用需要下载和上传大文件,因此无法承受以如此低的速度传输。 Firebase完全没有预料到这一点。

请告诉我,如果我在执行中做错了,或者这是Firebase的固有问题?

更新

我也遇到了只有上传的问题。当我下载某些内容并且我只是关闭Wifi时,下载会因此错误而被取消。

com.google.firebase.storage.StorageException: An unknown error occurred, please check the HTTP result code and inner exception for server response.

Read error: ssl=0xb7e7a510: I/O error during system call, Connection timed out
                                                                           javax.net.ssl.SSLException: Read error: ssl=0xb7e7a510: I/O error during system call, Connection timed out
                                                                               at com.android.org.conscrypt.NativeCrypto.SSL_read(Native Method)
                                                                               at com.android.org.conscrypt.OpenSSLSocketImpl$SSLInputStream.read(OpenSSLSocketImpl.java:699)
                                                                               at com.android.okio.Okio$2.read(Okio.java:113)
                                                                               at com.android.okio.RealBufferedSource.read(RealBufferedSource.java:48)
                                                                               at com.android.okhttp.internal.http.HttpConnection$FixedLengthSource.read(HttpConnection.java:446)
                                                                               at com.android.okio.RealBufferedSource$1.read(RealBufferedSource.java:168)
                                                                               at java.io.InputStream.read(InputStream.java:162)
                                                                               at com.google.firebase.storage.FileDownloadTask.run(Unknown Source)
                                                                               at com.google.firebase.storage.StorageTask$5.run(Unknown Source)
                                                                               at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
                                                                               at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
                                                                               at java.lang.Thread.run(Thread.java:818)

但是当我为上传做同样的事情时,它只是等待连接,如果我再次打开Wifi,它会重新连接并恢复。为什么只在下载文件时才会出现问题? getFile()API再次出现问题吗?

仅供参考,我没有更改上传和下载的超时设置。它们是默认值。

2 个答案:

答案 0 :(得分:2)

我认为这不是为了反驳你的观察,而是作为比较点。作为测试,我使用下面的代码上传了一个~50MB的文件并计算了进度。该测试在带有家庭WiFi连接的三星Galaxy S3(4.4.2)上运行(在加利福尼亚州)。平均吞吐量大约为760KB /秒。

我使用同一网络在其他手机设备上运行相同的测试,吞吐量从300KB /秒到850KB /秒(Moto X Pure; Marshmallow)。

private void uploadTest() {
    // This file is ~50MB
    final File file = new File("/storage/emulated/0/DCIM/Camera/20160821_101145.mp4");
    // Upload the file
    Log.i(TAG, String.format("uploadTest: Starting upload of %5.2fMB file",
            file.length()/1024.0/1024.0));

    FirebaseStorage.getInstance().getReference("test").putFile(Uri.fromFile(file))
            .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    Log.i(TAG, "onSuccess: Done");
                }
            }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
            Log.i(TAG, String.format("onProgress: %5.2f MB transferred",
                    taskSnapshot.getBytesTransferred()/1024.0/1024.0));
        }
    });
}

这是生成的logcat,删除了一些进度行以使列表更紧凑:

08-21 11:39:17.539 18427-18427/com.qbix.test I/MainActivity: uploadTest: Starting upload of 51.79MB file
08-21 11:39:17.559 18427-18427/com.qbix.test I/MainActivity: onProgress:  0.00 MB transferred
08-21 11:39:25.117 18427-18427/com.qbix.test I/MainActivity: onProgress:  5.00 MB transferred
08-21 11:39:31.654 18427-18427/com.qbix.test I/MainActivity: onProgress: 10.00 MB transferred
08-21 11:39:38.711 18427-18427/com.qbix.test I/MainActivity: onProgress: 15.00 MB transferred
08-21 11:39:45.088 18427-18427/com.qbix.test I/MainActivity: onProgress: 20.00 MB transferred
08-21 11:39:51.375 18427-18427/com.qbix.test I/MainActivity: onProgress: 25.00 MB transferred
08-21 11:39:57.411 18427-18427/com.qbix.test I/MainActivity: onProgress: 30.00 MB transferred
08-21 11:40:03.408 18427-18427/com.qbix.test I/MainActivity: onProgress: 35.00 MB transferred
08-21 11:40:10.886 18427-18427/com.qbix.test I/MainActivity: onProgress: 40.00 MB transferred
08-21 11:40:17.233 18427-18427/com.qbix.test I/MainActivity: onProgress: 45.00 MB transferred
08-21 11:40:23.069 18427-18427/com.qbix.test I/MainActivity: onProgress: 50.00 MB transferred
08-21 11:40:25.792 18427-18427/com.qbix.test I/MainActivity: onProgress: 51.79 MB transferred
08-21 11:40:25.792 18427-18427/com.qbix.test I/MainActivity: onSuccess: Done 

答案 1 :(得分:1)

我一直在做一些测试,我试图找到你看到糟糕表现的底线。 当使用getStream一次读取单个字节时,我能够复制不良性能,但这可以通过读入合理大小的字节缓冲区(256kb缓冲区)来解决。 修复此问题后,我看到的性能等同于直接使用httpsUrlConnection下载。

我想到了三种可能性:

1)您在dns解析期间(到我们的多个ips)看到超时,并且连接池在上传期间不起作用。但这只能解释为什么上传(分块)会很慢。下载不会分块。

2)你所在的地区我们尚未进行优化。我们即将在亚洲和欧洲推出本地支持,以优化绩效。

3)也许你正在将它与httpsurlconnection以外的东西进行比较?你能提供更多关于测试的细节吗?

这是我的测试:

public class MovePlayer : MonoBehaviour
{
    private Vector3 newPos;
    private Vector3 up = new Vector3(0, .3f, 0);
    private bool jumping = false;
    public Rigidbody rigidbody;

    void Start()
    {
        rigidbody = GetComponent<Rigidbody>();
    }

    void Update()
    {
        rigidbody.freezeRotation = true;

        if (!jumping)
        {
            if (Input.GetKeyDown(KeyCode.UpArrow))
            {
                newPos = Vector3.forward + transform.position;
                rigidbody.MoveRotation(Quaternion.Euler(0, 0, 0));
                rigidbody.MovePosition(newPos);
                rigidbody.MovePosition(newPos + up);
            }
            if (Input.GetKeyDown(KeyCode.DownArrow))
            {
                newPos = Vector3.back + transform.position;
                rigidbody.MoveRotation(Quaternion.Euler(0, 180, 0));
                rigidbody.MovePosition(newPos);
                rigidbody.MovePosition(newPos + up);
            }

            if (Input.GetKeyDown(KeyCode.RightArrow))
            {
                newPos = Vector3.right + transform.position;
                rigidbody.MoveRotation(Quaternion.Euler(0, 90, 0));
                rigidbody.MovePosition(newPos);
                rigidbody.MovePosition(newPos + up);
            }
            if (Input.GetKeyDown(KeyCode.LeftArrow))
            {
                newPos = Vector3.left + transform.position;
                rigidbody.MoveRotation(Quaternion.Euler(0, -90, 0));
                rigidbody.MovePosition(newPos);
                rigidbody.MovePosition(newPos + up);
            }
        }
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.CompareTag("Ground"))
            jumping = false;
    }

    void OnCollisionExit(Collision other)
    {
        if (other.gameObject.CompareTag("Ground"))
            jumping = true;
    }
}