Deprecate xxxSync() methods?

140 views
Skip to first unread message

George Moschovitis

unread,
May 9, 2015, 8:19:02 AM5/9/15
to mi...@dartlang.org
Now that we have async/await is there really any reason for the xxxSync() methods in 'dart:io'?
Perhaps they should be deprecated (and removed in Dart 2.0).

-g.

Joao Pedrosa

unread,
May 9, 2015, 10:54:41 AM5/9/15
to mi...@dartlang.org
Hi,

You can remove them, but you may not be able to remove the need for them. They have already tried to remove some of them before, but predictability in order of processing can still matter. Async programming have what we could describe as high level queues. But there is a need for them to communicate with lower level stuff and predictability may be important then. For example, programs may take input from "standard in" and "standard err". Which are separate. But not quite. The order of the stuff that comes from them may need to be maintained.

It doesn't feel like long ago when they were promoting Async programming in Node.JS. And yet they are still having their doubts about it and sometimes they move their systems into Go instead.

Also performance of Async processing may take a hit from all of the indirections. Sometimes off-loading that work to the Operating System may be better.

I think that in the programming world, Sync programming could be considered the Goliath and Async programming could be considered the David. I'm not sure that the David is ready yet, but you never know! ;-)

Cheers,
Joao

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.

Andreas Kirsch

unread,
May 9, 2015, 12:01:01 PM5/9/15
to mi...@dartlang.org
Your argument is interesting. For it, I would suggest that raw blocking could be moved into a particular Future implementation.
For example, we could wrap every *Sync method in a Future.value instance. This would preserve strict order and still expose the Future interface instead. So I see this as an implementation detail not a design obstacle.

George Moschovitis

unread,
May 10, 2015, 2:07:21 AM5/10/15
to mi...@dartlang.org


They have already tried to remove some of them before, but predictability in order of processing can still matter. 

What do you mean here? Await doesn't enforce an 'order of processing'? Can you elaborate?

-g.

Danny Tuppeny

unread,
May 10, 2015, 4:32:19 AM5/10/15
to mi...@dartlang.org
On Sunday, 10 May 2015 07:07:21 UTC+1, George Moschovitis wrote:
They have already tried to remove some of them before, but predictability in order of processing can still matter. 

What do you mean here? Await doesn't enforce an 'order of processing'? Can you elaborate?

If you read a file synchronously (blocking), you can be sure no other code on this thread runs during that period and the code that gets the file content executes first. If you use await, there's a possibility that there are other things in the "queue" that could run before your "file read complete" code (because it gets converted to a callback that gets added to a queue).

I'm not sure anyone would write code that would fail because of this; but I suspect it's not hard to fabricate something that would behave differently.

Personally; I think there's value in the sync methods in io. Sometimes you just want to write something where there's no penalty in blocking, and the mental overhead of async just isn't worth it (eg. a console app util, or reading config at startup of your web app, where nothing can be processed until it's loaded anyway). I wouldn't suggest removing them unless there's some real benefit to having them gone.

Vadim Tsushko

unread,
May 10, 2015, 6:05:38 AM5/10/15
to mi...@dartlang.org


воскресенье, 10 мая 2015 г., 13:32:19 UTC+5 пользователь Danny Tuppeny написал:

Personally; I think there's value in the sync methods in io. Sometimes you just want to write something where there's no penalty in blocking, and the mental overhead of async just isn't worth it (eg. a console app util, or reading config at startup of your web app, where nothing can be processed until it's loaded anyway). I wouldn't suggest removing them unless there's some real benefit to having them gone.

Absolutely. In my practice dart is very useful for command-line scripting. And for such tasks I prefer use sync interfaces whenever it possible.
It makes debugging much more pleasant experience.

 

Andreas Kirsch

unread,
May 10, 2015, 6:56:21 AM5/10/15
to mi...@dartlang.org
Instead of all the sync methods, dart:io could just implement a method that actually blocks on a Future completion. I'd rather have everything async than duplicate methods everywhere that have blocking semantics. It would simplify the API and programming a lot.
--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new

To unsubscribe from this group and stop receiving emails from it, send an email to misc+uns...@dartlang.org.


--
Why is this e-mail so short? Answer: five.sentenc.es.

Vadim Tsushko

unread,
May 10, 2015, 7:44:23 AM5/10/15
to mi...@dartlang.org


воскресенье, 10 мая 2015 г., 15:56:21 UTC+5 пользователь Andreas Kirsch написал:
Instead of all the sync methods, dart:io could just implement a method that actually blocks on a Future completion. I'd rather have everything async than duplicate methods everywhere that have blocking semantics. It would simplify the API and programming a lot.


How such API would look? Would it be something like 

    file.open();
    blockSync();

instead of current

    file.openSync();

And what can be done with something like

    if(file.existsSync()) {
      .....
    } 



Joao Pedrosa

unread,
May 10, 2015, 7:53:03 AM5/10/15
to mi...@dartlang.org
Hi,

With Async programming you can mimic some order of processing, but it is not a given yet. You still have just 1 thread of execution, and all of the Async queues need to share that thread. In some "impure" environments like .NET which support multiple threads, sync, async, etc, users may try to come up with their own custom Async features by employing threads...

With Async programming we are delaying the execution of those queues. With just 1 queue, if you delay it, you may still be fairly sure that order would be maintained it the queue were executed. But with multiple, competing queues, the order would not necessarily match the one you had imagined. With Async programming we are moving some of the operating system's responsibility into our programs, all so that we get a somewhat safe shared memory with some concurrency.

Something that comes about a lot in Async programming is that the program may finish executing and the queues would still have data to be processed. In a command line tool that finishes executing in milliseconds, you may have to wait till those queues are cleared so that you don't lose data. But even in a server environment you have to be sure that when you want to restart the server that all of the queues are finished. The queues having to finish processing is like a program whose data hasn't been flushed yet.

With Sync programming, sometimes you can be sure that the data is "flushed" as soon as you issue the command. With Async programming, you are not so sure anymore.

I like Async programming as an ideal because it has shared memory! It is probably an OK tradeoff in a GUI application that works from the network. It is a kind of sandbox since you cannot spawn threads on your own. Its purpose then is mainly to download and upload data without blocking your UI. With Node.JS it started changing into also being useful on the server, so long as it does not block the thread for long or cause many bugs... If Async programming was just that, it could have likely been reduced to just a library used for transferring data. A GUI was already "async" by default because of the need to respond to events.

We can blame "Async" on Node.JS and Microsoft's .NET. :-)

Cheers,
Joao



--

Lasse R.H. Nielsen

unread,
May 10, 2015, 8:00:23 AM5/10/15
to mi...@dartlang.org
On Sun, May 10, 2015 at 12:56 PM, 'Andreas Kirsch' via Dart Misc <mi...@dartlang.org> wrote:
Instead of all the sync methods, dart:io could just implement a method that actually blocks on a Future completion. I'd rather have everything async than duplicate methods everywhere that have blocking semantics. It would simplify the API and programming a lot.

Blocking an Isolate waiting on a future completion is ... tricky. For one thing, it requires the isolate to be unblocked in order to actually complete the future. You can do hacks to get around that, but it's not going to be pretty, nor safe from deadlocks.


/L
--
Lasse R.H. Nielsen - l...@google.com  
'Faith without judgement merely degrades the spirit divine'
Google Denmark ApS - Frederiksborggade 20B, 1 sal - 1360 København K - Denmark - CVR nr. 28 86 69 84

George Moschovitis

unread,
May 10, 2015, 3:15:34 PM5/10/15
to mi...@dartlang.org
I'm not sure anyone would write code that would fail because of this;

Agreed.
 
and the mental overhead of async just isn't worth it 

no mental overhead from two concepts, await, sync, just use await everywhere, it's more consistent, e.g.

    if (!await targetDir.exists()) {
      await targetDir.create();
    }

vs

    if (!targetDir.existsSync()) {
      targetDir.createSync();
    }

personally, I think the await version is more consistent (and I started to use this in small cli scripts).

-g.



 

George Moschovitis

unread,
May 10, 2015, 3:16:25 PM5/10/15
to mi...@dartlang.org
It makes debugging much more pleasant experience.

Ah, that's an issue. However, the solution would be to improve debugging for await in general.

-g.

Vadim Tsushko

unread,
May 10, 2015, 4:02:39 PM5/10/15
to mi...@dartlang.org


понедельник, 11 мая 2015 г., 0:15:34 UTC+5 пользователь George Moschovitis написал:
I'm not sure anyone would write code that would fail because of this;

Agreed.
 
and the mental overhead of async just isn't worth it 

no mental overhead from two concepts, await, sync, just use await everywhere, it's more consistent, e.g.

    if (!await targetDir.exists()) {
      await targetDir.create();
    }

vs

    if (!targetDir.existsSync()) {
      targetDir.createSync();
    }


I'm vaguely recollecting Alex Tatumazer's remarks about that. As I understand he told something like this: with `await` as syntactical sugar available we inevitably will be using `await` before almost every method returning future in our code. Why not sprinkle some more sugar and auto add that `await` implicitly.   
 

Danny Tuppeny

unread,
May 11, 2015, 7:21:58 AM5/11/15
to mi...@dartlang.org
On 10 May 2015 at 11:56, 'Andreas Kirsch' via Dart Misc <mi...@dartlang.org> wrote:
Instead of all the sync methods, dart:io could just implement a method that actually blocks on a Future completion. I'd rather have everything async than duplicate methods everywhere that have blocking semantics. It would simplify the API and programming a lot.

.NET's Task<T> has this (.Wait()/Result), but it's not really a nice API; it feels like a bodge. I've also had people ask for help and show my code that fails because they didn't block on some threaded task that sets some shared data, then try to use it, and it didn't work (the second half of their method ran before the background work had completed).

Having synchronous versions is significantly easier. Unless there's a big win in taking it out; I don't see huge value in removing the sync versions. .NET has a bit of a convention with suffixing methods with Async when they return tasks, which works out well (webClient.DownloadString returns string, webClient.DownloadStringAsync returns Task<String>).

Also; let's not forget that there is an overhead in going Async. There have been some benchmarks showing that for some things, that overhead can be bigger than just doing sync work (there was some discussion when I questioned some sync stuff in the shelf package some time ago).


On 10 May 2015 at 20:15, George Moschovitis <george.mo...@gmail.com> wrote:
and the mental overhead of async just isn't worth it 

no mental overhead from two concepts, await, sync, just use await everywhere, it's more consistent, e.g.

Not true. The debugging experience is different, and you need to understand what's really happening with your code. As mentioned above; I've often had to help people with async code because they didn't full understand how await worked (and it's not as simple as saying "well they shouldn't be writing it then" because it was I that started putting it in to APIs they're calling ;o)).

I don't think it's particularly complicated, but there's certainly some knowledge you need, and it adds some complexity. Eg. if you make something async, you often have to go async "all the way up" to make sure something further up the chain isn't expecting it to have been synchronously.

Dart currently has a pretty low barrier to entry. I think forcing simple console apps to use async will significantly raise the bar to getting started :(

George Moschovitis

unread,
May 11, 2015, 3:02:17 PM5/11/15
to mi...@dartlang.org

Not true. The debugging experience is different, and you need to understand what's really happening with your code. As mentioned above; I've often had to help people with async code because they didn't full understand how await worked (and it's not as simple as saying "well they shouldn't be writing it then" because it was I that started putting it in to APIs they're calling ;o)).

OK. 

Alex Tatumizer

unread,
May 11, 2015, 3:11:32 PM5/11/15
to mi...@dartlang.org
@Vadim: there was a discussion about auto-await a while back. The main argument, as much as I remember, is that it's impossible to generate *efficient* javascript code to support the feature. But even in VM (where, I believe, technical hurdles are not as high), we still have logical problems. For example, you need to be able to write a declaration of return value as "T or Future<T>". In other words, you need union types. There's some write-up by Gilad that addresses the issue of union types and I think "T or Future<T>" was one of motivations. But it's only a necessary condition, not sure it will lead to auto-await (some people may not like it). In the very least, union type T or Future<T> can make functions a bit more composable.

Joel Trottier-Hébert

unread,
May 11, 2015, 3:35:43 PM5/11/15
to mi...@dartlang.org
I don't see how auto-await could be viable. I mean you could want to not-await something no? At least, it has happened to me already several times.

Joel Trottier-Hebert

On Mon, May 11, 2015 at 3:11 PM, Alex Tatumizer <tatu...@gmail.com> wrote:
@Vadim: there was a discussion about auto-await a while back. The main argument, as much as I remember, is that it's impossible to generate *efficient* javascript code to support the feature. But even in VM (where, I believe, technical hurdles are not as high), we still have logical problems. For example, you need to be able to write a declaration of return value as "T or Future<T>". In other words, you need union types. There's some write-up by Gilad that addresses the issue of union types and I think "T or Future<T>" was one of motivations. But it's only a necessary condition, not sure it will lead to auto-await (some people may not like it). In the very least, union type T or Future<T> can make functions a bit more composable.

--

Alex Tatumizer

unread,
May 11, 2015, 5:51:11 PM5/11/15
to mi...@dartlang.org
Auto-await means: you don't have to write "await expr, it will automatically "await" every Future (dynamically - based on runtime type of the Future). Then you need to have a way to explicitly guard (in some or other manner) Futures that you don't want to be awaited (e.g. by writing rawFuture(expr) or something)
I'm afraid that is not a good idea anyway.

Joel Trottier-Hébert

unread,
May 11, 2015, 10:14:42 PM5/11/15
to mi...@dartlang.org
That would break so much stuff that didn't do the transition of async-await.

Joel Trottier-Hebert
Reply all
Reply to author
Forward
0 new messages