RE: Further adventures in the land of 64-bit linux
Tim Peters <[email protected]> Mon, 16 Sep 2002 22:06:53 -0400
| Newsgroups | gmane.comp.python.snake-farm.user |
|---|---|
| Message-ID | <[email protected]> |
[Anders Qvist, on test_longexp]
> ...
> The behaviour seems exponential, for nothing untoward is apparent with
> small number of elements in the list.
The parse tree built for this list is huge, though. test_longexp is a pain
in the ass that's failed to work on various platforms since it was first
introduced. That got fixed for all known platforms after 2.2.1 was
released, via a combination of switching to pymalloc for the small
allocations, and doing aggressive overallocation for monstrously large (many
children) parse nodes.
> As numbers grow into tens of thousands, the memory usage starts to
> balloon.
This is so on all platforms -- the test is extreme.
> Technically, the machine could prolly pass the test, had it not been
> for its shortage of memory.
>
> [ 22:40 ] - ./python
> Python 2.3a0 (#2, Sep 16 2002, 17:37:08)
> [GCC egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
> >>> l = eval ("[" + "2," * 30000 + "]")
> [47434 refs]
>
> PID USER PRI NI SIZE RSS SHARE STAT LIB %CPU %MEM TIME COMMAND
> 30153 quest 5 0 24952 24M 2464 S 23M 0.0 20.3 0:04 python
>
> It's late, so I'll have to continue the hunt later. Here's the
> backtrace from gdb, but it doesn't seem to point to what's wrong.
To the contrary, I expect it pointed directly at the culprit <wink>:
> #0 0x12011e3ec in PyNode_AddChild (n1=0x200026166c8, type=301, str=0x0,
> lineno=1) at ../python/dist/src/Parser/node.c:95
and line 95 is a realloc() call. As a parse node grows large,
PyNode_AddChild doubles the amount of memory it asks for every time it runs
out of room.
[Guido]
> Could it be that the parse tree uses twice the memory on a 64-bit
> machine, and that that is simply too much? Give it a try with smaller
> values of 65580. (:-)
test_longexp consumes about 25MB of data space on my 32-bit box. A parse
node contains two pointers so at least those two fields are twice as big on
a 64-bit box. It may (or may not) help to rearrange the struct decl to
order the fields from widest to narrowest:
Current:
typedef struct _node {
short n_type;
char *n_str;
int n_lineno;
int n_nchildren;
struct _node *n_child;
} node;
Possibly more space-efficient:
typedef struct _node {
char *n_str;
struct _node *n_child;
int n_lineno;
int n_nchildren;
short n_type;
} node;
At least one n_child vector grows very large in test_longexp.