Skip to content

core and std: Optimize write*!() and print*!() for a single argument #22335

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

erickt
Copy link
Contributor

@erickt erickt commented Feb 14, 2015

Before this patch, write!(wr, "foo") was not as fast as wr.write_all("foo".as_bytes()) because the underlying write_fmt has some overhead in order to work with multiple arguments. This PR speeds that up by optimizing this specific case.

@rust-highfive
Copy link
Contributor

r? @huonw

(rust_highfive has picked a reviewer for you, use r? to override)

@emberian
Copy link
Member

@bors r+ bc7dd057 rollup

@erickt
Copy link
Contributor Author

erickt commented Feb 14, 2015

@bors r-

Ugh. This is actually a breaking change. Doing write!(wr, "{{") would now produce "{{" instead of "{". I'll have to tweak this

@erickt
Copy link
Contributor Author

erickt commented Feb 14, 2015

Turns out panic! right now also has this issue. panic!("{") produces a single "{", panic!("{{") produces "{{", panic!("{ {}", 5) produces a compile time error, and panic!("{{ {}", 5) produces "{ 5".

@pczarn
Copy link
Contributor

pczarn commented Feb 15, 2015

format_args! could expand to a single string literal.

@erickt
Copy link
Contributor Author

erickt commented Feb 16, 2015

@pczarn: Unfortunately then format_args!("foo") would be then returning a different type than format_args!("{}", 5), which would cause all sorts of havoc. I think we instead need a format_arg!(fmt) that uses the same syntax as format_args! but only allows for one argument. I have that implemented and I'll push it up in a few moments after I make sure it passes the tests locally first.

@erickt erickt force-pushed the single-write branch 2 times, most recently from c6ad5eb to a3e5cb3 Compare February 16, 2015 03:27
///
/// ```
#[macro_export]
macro_rules! format_arg { ($fmt:expr) => ({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect the two cases need to be in the same macro definition to be rendered,

macro_rules! format_args {
     ($fmt: expr) => ({ /* compiler built-in */ });
     ($fmt: expr, $($args: tt)*) => ({ /* compiler built-in */ });
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@erickt pointed out my mistake on IRC (interpreted this just a variation of format_args rather than a new format_arg macro).

In any case, I think the doc string for this needs updating, since AFAICT, it doesn't return Arguments any more.

Before this patch, `write!(wr, "foo")` was not as fast as
`wr.write_str("foo")` because the underlying write_fmt has some overhead
in order to work with multiple arguments.
@erickt
Copy link
Contributor Author

erickt commented Feb 16, 2015

@huonw: I also have a branch that merges format_arg!() and format_args!() if we want to go that direction.

@alexcrichton
Copy link
Member

If this is adding a new format_arg! macro then I think this needs an RFC behind it (as it's adding a new macro to the prelude).

#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
($fmt:expr) => {
format_arg!($fmt).to_string()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this different from format_args!($fmt, $($arg)*).to_string()?

@pczarn
Copy link
Contributor

pczarn commented Feb 16, 2015

@erickt: you can add a method for extracting the only string piece out of fmt::Arguments and avoid adding a new macro.

@erickt
Copy link
Contributor Author

erickt commented Feb 17, 2015

@pczarn: doing that would be doing roughly the same amount of work Writer::write_fmt does, so at that point it'd be better to stick with what we've got right now. If we don't want this optimization, it's easy enough to call Writer::write_str. I'll close this for now in deference for an RFC, since I don't think I'd be able to do this without adding a new macro, or changing format_args to work differently for a single format string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants