Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(204)

Side by Side Diff: Modules/cPickle.c

Issue 189051: Incrementally flush large cPickle output to file Base URL: http://unladen-swallow.googlecode.com/svn/trunk/
Patch Set: revised patch Created 15 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #include "Python.h" 1 #include "Python.h"
2 #include "structmember.h" 2 #include "structmember.h"
3 #include "cPickle.h" 3 #include "cPickle.h"
4 4
5 PyDoc_STRVAR(cPickle_module_documentation, 5 PyDoc_STRVAR(cPickle_module_documentation,
6 "C implementation and optimization of the Python pickle module."); 6 "C implementation and optimization of the Python pickle module.");
7 7
8 #ifndef Py_eval_input 8 #ifndef Py_eval_input
9 #include <graminit.h> 9 #include <graminit.h>
10 #define Py_eval_input eval_input 10 #define Py_eval_input eval_input
11 #endif /* Py_eval_input */ 11 #endif /* Py_eval_input */
12 12
13 #define DEL_LIST_SLICE(list, from, to) (PyList_SetSlice(list, from, to, NULL)) 13 #define DEL_LIST_SLICE(list, from, to) (PyList_SetSlice(list, from, to, NULL))
14 14
15 /* Bump this when new opcodes are added to the pickle protocol. */ 15 /* Bump this when new opcodes are added to the pickle protocol. */
16 #define HIGHEST_PROTOCOL 2 16 #define HIGHEST_PROTOCOL 2
17 17
18 /* Maximum size we ever allow the output buffer to get before flushing. */
19 #define PICKLER_MAX_BUFSIZE 64*1024
20
18 /* 21 /*
19 * Pickle opcodes. These must be kept in synch with pickle.py. Extensive 22 * Pickle opcodes. These must be kept in synch with pickle.py. Extensive
20 * docs are in pickletools.py. 23 * docs are in pickletools.py.
21 */ 24 */
22 #define MARK '(' 25 #define MARK '('
23 #define STOP '.' 26 #define STOP '.'
24 #define POP '0' 27 #define POP '0'
25 #define POP_MARK '1' 28 #define POP_MARK '1'
26 #define DUP '2' 29 #define DUP '2'
27 #define FLOAT 'F' 30 #define FLOAT 'F'
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 int proto; 567 int proto;
565 568
566 /* bool, true if proto > 0 */ 569 /* bool, true if proto > 0 */
567 int bin; 570 int bin;
568 571
569 /* Does the pickle contain any of GET, BINGET or LONG_BINGET? */ 572 /* Does the pickle contain any of GET, BINGET or LONG_BINGET? */
570 int uses_gets; 573 int uses_gets;
571 574
572 /* Write into a local buffer before flushing out to file. output_len 575 /* Write into a local buffer before flushing out to file. output_len
573 tracks the current size; when output_len >= max_output_len, we 576 tracks the current size; when output_len >= max_output_len, we
574 » PyMem_RESIZE. */ 577 » PyMem_RESIZE. In any case if we are pickling to a file we flush
578 » the buffer after it grows to more than PICKLER_MAX_BUFSIZE to
579 » avoid eating up all of memory in that case. */
575 Py_ssize_t max_output_len; 580 Py_ssize_t max_output_len;
576 Py_ssize_t output_len; 581 Py_ssize_t output_len;
577 char *output_buffer; 582 char *output_buffer;
578 583
579 int fast; /* Fast mode doesn't save in memo, don't use if circ ref */ 584 int fast; /* Fast mode doesn't save in memo, don't use if circ ref */
580 PyObject *dispatch_table; 585 PyObject *dispatch_table;
581 int fast_container; /* count nested container dumps */ 586 int fast_container; /* count nested container dumps */
582 PyObject *fast_memo; 587 PyObject *fast_memo;
583 } Picklerobject; 588 } Picklerobject;
584 589
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
649 if (args) retval=args; 654 if (args) retval=args;
650 else { 655 else {
651 PyErr_SetObject(ErrType,Py_None); 656 PyErr_SetObject(ErrType,Py_None);
652 return NULL; 657 return NULL;
653 } 658 }
654 PyErr_SetObject(ErrType,retval); 659 PyErr_SetObject(ErrType,retval);
655 Py_DECREF(retval); 660 Py_DECREF(retval);
656 return NULL; 661 return NULL;
657 } 662 }
658 663
664 /* forward declarations needed by _Pickler_Write */
665 static int _Pickler_FlushToFile(Picklerobject *);
666 static int _Pickler_ClearBuffer(Picklerobject *);
667
659 static int 668 static int
660 _Pickler_Write(Picklerobject *self, const char *s, Py_ssize_t n) 669 _Pickler_Write(Picklerobject *self, const char *s, Py_ssize_t n)
661 { 670 {
662 Py_ssize_t i; 671 Py_ssize_t i;
663 char *buffer; 672 char *buffer;
664 673
665 if (self->output_len + n > self->max_output_len) { 674 if (self->output_len + n > self->max_output_len) {
666 self->max_output_len = (self->output_len + n) * 2; 675 self->max_output_len = (self->output_len + n) * 2;
667 buffer = self->output_buffer; 676 buffer = self->output_buffer;
668 PyMem_RESIZE(buffer, char, self->max_output_len); 677 PyMem_RESIZE(buffer, char, self->max_output_len);
669 if (buffer == NULL) { 678 if (buffer == NULL) {
670 PyErr_NoMemory(); 679 PyErr_NoMemory();
671 return -1; 680 return -1;
672 } 681 }
673 self->output_buffer = buffer; 682 self->output_buffer = buffer;
674 } 683 }
675 /* This is faster than memcpy for the char *s we're copying. */ 684 /* This is faster than memcpy for the char *s we're copying. */
676 for (i = 0; i < n; i++) { 685 for (i = 0; i < n; i++) {
677 self->output_buffer[self->output_len + i] = s[i]; 686 self->output_buffer[self->output_len + i] = s[i];
678 } 687 }
679 self->output_len += n; 688 self->output_len += n;
689
690 if (self.file && self->output_len >= PICKLER_MAX_BUFSIZE) {
691 /* suppress optimization since the optimizer won't get a
692 look at the entire pickled object */
Antoine Pitrou 2010/01/13 13:08:12 You could probably do an early test on `n >= PICKL
Skip 2010/01/13 13:47:16 Sure, but this seems ever-so-slightly easier to ge
Skip 2010/01/13 13:48:59 Done.
693 self->uses_gets = 1;
Antoine Pitrou 2010/01/13 13:08:12 I suppose this is unladen-swallow-specific? I see
Skip 2010/01/13 13:47:16 Correct. See _Pickler_Optimize. It removes PUT o
694 if (_Pickler_FlushToFile(self) < 0)
695 return -1;
696 if (_Pickler_ClearBuffer(self) < 0)
697 return -1;
698 }
699
680 return n; 700 return n;
681 } 701 }
682 702
683 static PyObject * 703 static PyObject *
684 _Pickler_GetString(Picklerobject *self) 704 _Pickler_GetString(Picklerobject *self)
685 { 705 {
686 return PyString_FromStringAndSize(self->output_buffer, 706 return PyString_FromStringAndSize(self->output_buffer,
687 self->output_len); 707 self->output_len);
688 } 708 }
689 709
(...skipping 5877 matching lines...) Expand 10 before | Expand all | Expand 10 after
6567 "1.0", /* Original protocol 0 */ 6587 "1.0", /* Original protocol 0 */
6568 "1.1", /* Protocol 0 + INST */ 6588 "1.1", /* Protocol 0 + INST */
6569 "1.2", /* Original protocol 1 */ 6589 "1.2", /* Original protocol 1 */
6570 "1.3", /* Protocol 1 + BINFLOAT */ 6590 "1.3", /* Protocol 1 + BINFLOAT */
6571 "2.0"); /* Original protocol 2 */ 6591 "2.0"); /* Original protocol 2 */
6572 PyDict_SetItemString(d, "format_version", format_version); 6592 PyDict_SetItemString(d, "format_version", format_version);
6573 PyDict_SetItemString(d, "compatible_formats", compatible_formats); 6593 PyDict_SetItemString(d, "compatible_formats", compatible_formats);
6574 Py_XDECREF(format_version); 6594 Py_XDECREF(format_version);
6575 Py_XDECREF(compatible_formats); 6595 Py_XDECREF(compatible_formats);
6576 } 6596 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b