http icon indicating copy to clipboard operation
http copied to clipboard

Http download is 3x times slower on Web vs Desktop

Open tomekit opened this issue 1 year ago • 2 comments

Steps to reproduce

Run code: flutter run --release on Web then click a button, it will download ~18MB file. Repeat tests on non-web (e.g. desktop platform), download speed shall be much higher.

On my ~40Mbps download connection, Linux maxes out download speed. On Web speed seem to be throttled for some reason.

Linux

Download file http://localhost:8080/20MB.zip
flutter: Downloaded 20971520 in 3975ms

Web

Download file http://localhost:8080/20MB.zip
Downloaded 20971520 in 12xxxms

Dependencies

flutter pub add http

Proxy tunnel required on Web to avoid CORS issue. In order to make this test uniform proxy is used also on non-Web.

mitmproxy -s cors.py --mode reverse:http://xcal1.vodafone.co.uk

cors.py

from mitmproxy import http

def response(flow):
        flow.response.headers["Access-Control-Allow-Origin"] = "*"
        flow.response.headers["Access-Control-Allow-Headers"] = "*"

Code sample

Code sample
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  void activateDownload() async {

    // final url = 'http://xcal1.vodafone.co.uk/20MB.zip';
    final url = 'http://localhost:8080/20MB.zip'; // Use: `mitmproxy -s cors.py --mode reverse:http://xcal1.vodafone.co.uk` to avoid CORS issues on Web

    List<int> buffer = [];
    print('\n1) downloadBytesSimple');
    print('\nDownload file $url');
    await downloadBytesSimple(buffer, url);
  }

  static Future<void> downloadBytesSimple(List<int> buffer, String url) async {
    var headers = {
      'Cache-Control': 'no-cache'
    };

    var startTime = DateTime.timestamp();
    final response = await http.get(Uri.parse(url), headers: headers);
    print('Downloaded ${response.contentLength} in ${DateTime.timestamp().difference(startTime).inMilliseconds}ms');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          activateDownload();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

What target platforms are you seeing this bug on?

Web

OS/Browser name and version | Device information

Version 123.0.6312.58 (Official Build) (64-bit) Ubuntu 23.10

Does the problem occur on emulator/simulator as well as on physical devices?

Yes

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[✓] Flutter (Channel stable, 3.19.5, on Ubuntu 23.10 6.5.0-27-generic, locale en_US.UTF-8)
    • Flutter version 3.19.5 on channel stable at /opt/flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 300451adae (12 days ago), 2024-03-27 21:54:07 -0500
    • Engine revision e76c956498
    • Dart version 3.3.3
    • DevTools version 2.31.1

[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at /home/tomek/Android/Sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = /home/tomek/Android/Sdk
    • Java binary at: /opt/android-studio/jbr/bin/java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)
    • All Android licenses accepted.

[✓] Chrome - develop for the web
    • Chrome at google-chrome

[✓] Linux toolchain - develop for Linux desktop
    • Ubuntu clang version 16.0.6 (15)
    • cmake version 3.27.4
    • ninja version 1.11.1
    • pkg-config version 1.8.1

[✓] Android Studio (version 2023.1)
    • Android Studio at /opt/android-studio
    • Flutter plugin version 76.3.3
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-17.0.7b1000.6-10550314)

[✓] VS Code (version 1.78.2)
    • VS Code at /usr/share/code
    • Flutter extension can be installed from:
      🔨 https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter

[✓] Connected device (2 available)
    • Linux (desktop) • linux  • linux-x64      • Ubuntu 23.10 6.5.0-27-generic
    • Chrome (web)    • chrome • web-javascript • Google Chrome 123.0.6312.58

[✓] Network resources
    • All expected network resources are available.

• No issues found!

Originally posted here: https://github.com/flutter/flutter/issues/146494

tomekit avatar Apr 09 '24 15:04 tomekit

Hi @tomekit

On the browser, we are using a very small wrapper over XMLHTTPRequest so this is most likely a browser issue.

Do you see the same issue when using package:fetch_client?

brianquinlan avatar May 24 '24 00:05 brianquinlan

Unfortunately my environment has changed in the meantime and I no longer can reproduce this problem. I am currently using Flutter 3.22.0 and Ubuntu 24.04 LTS, previously Flutter 3.19.5 and Ubuntu 23.10

I knot that previously I've tried this on multiple different browsers (Chrome and Firefox) and result were the same (poor download speed on Web).

Currently the speed using the example I've provided above, is somewhat comparable between Web and desktop, although certainly my poor 40Mb/s broadband is a limiting factor.

I've also updated file endpoints, as previous links expired. Since the new links don't handle CORS on Web, I've added a simple mitmproxy command to add them. This also means that transport no longer happen on HTTPS, but when tried some example HTTPS endpoint results were the same.

tomekit avatar May 24 '24 05:05 tomekit

When v1.3.0 of pkg:http is released (should be soon) we're hoping that the new streaming implementation will improve performance.

kevmoo avatar Jan 19 '25 20:01 kevmoo