aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDmitry Antipov2013-10-08 10:40:09 +0400
committerDmitry Antipov2013-10-08 10:40:09 +0400
commitf8498081911e4c1381c4bed5ac3b664ceca57d64 (patch)
treed96b7bf86daef23ecae0f9239ef79bff81500490 /src
parentb7d5bd823c239a8ee3613abcc4e24fe290a673d0 (diff)
downloademacs-f8498081911e4c1381c4bed5ac3b664ceca57d64.tar.gz
emacs-f8498081911e4c1381c4bed5ac3b664ceca57d64.zip
Do not allocate huge temporary memory areas and objects while encoding
for file I/O, thus reducing an enormous memory usage for large buffers. See http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00180.html. * coding.h (struct coding_system): New member raw_destination. * coding.c (setup_coding_system): Initialize it to zero. (encode_coding_object): If raw_destination is set, do not create dst_object. Add comment. * fileio.c (toplevel): New constant E_WRITE_MAX. (e_write): Do not encode more than E_WRITE_MAX characters per one loop iteration. Use raw_destination if E_WRITE_MAX characters is encoded.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog13
-rw-r--r--src/coding.c6
-rw-r--r--src/coding.h4
-rw-r--r--src/fileio.c42
4 files changed, 57 insertions, 8 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 217a8b3d269..06733a2455f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,16 @@
12013-10-08 Dmitry Antipov <dmantipov@yandex.ru>
2
3 Do not allocate huge temporary memory areas and objects while encoding
4 for file I/O, thus reducing an enormous memory usage for large buffers.
5 See http://lists.gnu.org/archive/html/emacs-devel/2013-10/msg00180.html.
6 * coding.h (struct coding_system): New member raw_destination.
7 * coding.c (setup_coding_system): Initialize it to zero.
8 (encode_coding_object): If raw_destination is set, do not create
9 dst_object. Add comment.
10 * fileio.c (toplevel): New constant E_WRITE_MAX.
11 (e_write): Do not encode more than E_WRITE_MAX characters per one loop
12 iteration. Use raw_destination if E_WRITE_MAX characters is encoded.
13
12013-10-08 Jan Djärv <jan.h.d@swipnet.se> 142013-10-08 Jan Djärv <jan.h.d@swipnet.se>
2 15
3 * nsterm.m (windowDidExitFullScreen:): 16 * nsterm.m (windowDidExitFullScreen:):
diff --git a/src/coding.c b/src/coding.c
index c10fb375672..ac828a48683 100644
--- a/src/coding.c
+++ b/src/coding.c
@@ -5761,6 +5761,7 @@ setup_coding_system (Lisp_Object coding_system, struct coding_system *coding)
5761 coding->safe_charsets = SDATA (val); 5761 coding->safe_charsets = SDATA (val);
5762 coding->default_char = XINT (CODING_ATTR_DEFAULT_CHAR (attrs)); 5762 coding->default_char = XINT (CODING_ATTR_DEFAULT_CHAR (attrs));
5763 coding->carryover_bytes = 0; 5763 coding->carryover_bytes = 0;
5764 coding->raw_destination = 0;
5764 5765
5765 coding_type = CODING_ATTR_TYPE (attrs); 5766 coding_type = CODING_ATTR_TYPE (attrs);
5766 if (EQ (coding_type, Qundecided)) 5767 if (EQ (coding_type, Qundecided))
@@ -8352,6 +8353,11 @@ encode_coding_object (struct coding_system *coding,
8352 { 8353 {
8353 if (BUFFERP (coding->dst_object)) 8354 if (BUFFERP (coding->dst_object))
8354 coding->dst_object = Fbuffer_string (); 8355 coding->dst_object = Fbuffer_string ();
8356 else if (coding->raw_destination)
8357 /* This is used to avoid creating huge Lisp string.
8358 NOTE: caller who sets `raw_destination' is also
8359 responsible for freeing `destination' buffer. */
8360 coding->dst_object = Qnil;
8355 else 8361 else
8356 { 8362 {
8357 coding->dst_object 8363 coding->dst_object
diff --git a/src/coding.h b/src/coding.h
index 2c01a05d197..0472bec99de 100644
--- a/src/coding.h
+++ b/src/coding.h
@@ -512,6 +512,10 @@ struct coding_system
512 `charbuf', but at `src_object'. */ 512 `charbuf', but at `src_object'. */
513 unsigned chars_at_source : 1; 513 unsigned chars_at_source : 1;
514 514
515 /* Nonzero if the result of conversion is in `destination'
516 buffer rather than in `dst_object'. */
517 unsigned raw_destination : 1;
518
515 /* Set to 1 if charbuf contains an annotation. */ 519 /* Set to 1 if charbuf contains an annotation. */
516 unsigned annotated : 1; 520 unsigned annotated : 1;
517 521
diff --git a/src/fileio.c b/src/fileio.c
index 1a2bdfa237c..c7125534e63 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -5263,6 +5263,10 @@ a_write (int desc, Lisp_Object string, ptrdiff_t pos,
5263 return 1; 5263 return 1;
5264} 5264}
5265 5265
5266/* Maximum number of characters that the next
5267 function encodes per one loop iteration. */
5268
5269enum { E_WRITE_MAX = 8 * 1024 * 1024 };
5266 5270
5267/* Write text in the range START and END into descriptor DESC, 5271/* Write text in the range START and END into descriptor DESC,
5268 encoding them with coding system CODING. If STRING is nil, START 5272 encoding them with coding system CODING. If STRING is nil, START
@@ -5289,9 +5293,16 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
5289 coding->src_multibyte = SCHARS (string) < SBYTES (string); 5293 coding->src_multibyte = SCHARS (string) < SBYTES (string);
5290 if (CODING_REQUIRE_ENCODING (coding)) 5294 if (CODING_REQUIRE_ENCODING (coding))
5291 { 5295 {
5292 encode_coding_object (coding, string, 5296 ptrdiff_t nchars = min (end - start, E_WRITE_MAX);
5293 start, string_char_to_byte (string, start), 5297
5294 end, string_char_to_byte (string, end), Qt); 5298 /* Avoid creating huge Lisp string in encode_coding_object. */
5299 if (nchars == E_WRITE_MAX)
5300 coding->raw_destination = 1;
5301
5302 encode_coding_object
5303 (coding, string, start, string_char_to_byte (string, start),
5304 start + nchars, string_char_to_byte (string, start + nchars),
5305 Qt);
5295 } 5306 }
5296 else 5307 else
5297 { 5308 {
@@ -5308,8 +5319,15 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
5308 coding->src_multibyte = (end - start) < (end_byte - start_byte); 5319 coding->src_multibyte = (end - start) < (end_byte - start_byte);
5309 if (CODING_REQUIRE_ENCODING (coding)) 5320 if (CODING_REQUIRE_ENCODING (coding))
5310 { 5321 {
5311 encode_coding_object (coding, Fcurrent_buffer (), 5322 ptrdiff_t nchars = min (end - start, E_WRITE_MAX);
5312 start, start_byte, end, end_byte, Qt); 5323
5324 /* Likewise. */
5325 if (nchars == E_WRITE_MAX)
5326 coding->raw_destination = 1;
5327
5328 encode_coding_object
5329 (coding, Fcurrent_buffer (), start, start_byte,
5330 start + nchars, CHAR_TO_BYTE (start + nchars), Qt);
5313 } 5331 }
5314 else 5332 else
5315 { 5333 {
@@ -5330,11 +5348,19 @@ e_write (int desc, Lisp_Object string, ptrdiff_t start, ptrdiff_t end,
5330 5348
5331 if (coding->produced > 0) 5349 if (coding->produced > 0)
5332 { 5350 {
5333 char *buf = (STRINGP (coding->dst_object) 5351 char *buf = (coding->raw_destination ? (char *) coding->destination
5334 ? SSDATA (coding->dst_object) 5352 : (STRINGP (coding->dst_object)
5335 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte)); 5353 ? SSDATA (coding->dst_object)
5354 : (char *) BYTE_POS_ADDR (coding->dst_pos_byte)));
5336 coding->produced -= emacs_write_sig (desc, buf, coding->produced); 5355 coding->produced -= emacs_write_sig (desc, buf, coding->produced);
5337 5356
5357 if (coding->raw_destination)
5358 {
5359 /* We're responsible for freeing this, see
5360 encode_coding_object to check why. */
5361 xfree (coding->destination);
5362 coding->raw_destination = 0;
5363 }
5338 if (coding->produced) 5364 if (coding->produced)
5339 return 0; 5365 return 0;
5340 } 5366 }