Merge pull request #595 from triska/faster_format

ENHANCED: faster format/3 when writing to binary streams
This commit is contained in:
Mark Thom
2020-06-14 12:37:06 -03:00
committed by GitHub
2 changed files with 20 additions and 15 deletions

View File

@@ -375,20 +375,9 @@ format(Fs, Args) :-
format(Stream, Fs, Args) :-
phrase(format_(Fs, Args), Cs),
( stream_property(Stream, type(binary)) ->
% maplist(char_code, Cs, Bytes) is currently a lot slower
% than first converting Cs to an atom, and then to codes.
% In the future, we can ideally avoid creating an atom here,
% since an atom leaves traces in the system.
atom_chars(A, Cs),
atom_codes(A, Bytes),
( member(NonByte, Bytes), NonByte > 255 ->
char_code(Char, NonByte),
throw(error(representation_error(Char), format/3))
; true
),
% For binary streams, we use a specialised internal predicate
% that uses only a single "write" operation for efficiency.
'$put_bytes'(Stream, Bytes)
'$put_bytes'(Stream, Cs)
; maplist(put_char(Stream), Cs)
).
@@ -471,7 +460,7 @@ portray_clause(Term) :-
portray_clause(Stream, Term) :-
phrase(portray_clause_(Term), Ls),
maplist(put_char(Stream), Ls).
format(Stream, "~s", [Ls]).
portray_clause_(Term) -->
{ term_variables(Term, Vs),

View File

@@ -2022,8 +2022,24 @@ impl MachineState {
let mut stream =
self.get_stream_or_alias(self[temp_v!(1)], indices, "$put_bytes", 2)?;
let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2);
let bytes = self.integers_to_bytevec(temp_v!(2), stub);
let mut iter = self.heap_pstr_iter(self[temp_v!(2)]);
let mut bytes = Vec::new();
for c in iter.to_string().chars() {
if c as u32 > 255 {
let stub = MachineError::functor_stub(clause_name!("$put_bytes"), 2);
let err = MachineError::type_error(
self.heap.h(),
ValidType::Byte,
Addr::Char(c),
);
return Err(self.error_form(err, stub));
}
bytes.push(c as u8);
}
match stream.write(&bytes) {
Ok(_) => {