#6208: [with patch, needs review] Improving gap interface by pre-compiling
certain
regular expressions
-------------------------+--------------------------------------------------
Reporter: SimonKing | Owner: SimonKing
Type: enhancement | Status: new
Priority: major | Milestone: sage-4.0.2
Component: interfaces | Keywords: gap interface expect regular expression
-------------------------+--------------------------------------------------
At http://groups.google.com/group/sage-
support/browse_thread/thread/657ef562de60fc6a
Jerome pointed out that the built in comparison of permutation groups
sometimes is rather sluggish compared with comparison of their lists of
elements.
While trying to find a reason, I found that the method ``_execute_line``
of the gap interface makes a non-optimal use of regular expressions: One
and the same pattern is compiled over and over again.
I did not succeed to solve the poster's original concern. But at least I
could speed up the gap interface.
Without the patch, I had
{{{
----------------------------------------------------------------------
| Sage Version 4.0, Release Date: 2009-05-29 |
| Type notebook() for the GUI, and license() for information. |
----------------------------------------------------------------------
sage: G=SymmetricGroup(7)
sage: time L=[X for X in G if X.order()==2]
CPU times: user 10.19 s, sys: 2.12 s, total: 12.31 s
Wall time: 15.48 s
}}}
With the patch, I have
{{{
----------------------------------------------------------------------
| Sage Version 4.0, Release Date: 2009-05-29 |
| Type notebook() for the GUI, and license() for information. |
----------------------------------------------------------------------
Loading Sage library. Current Mercurial branch is: expect-devel
sage: G=SymmetricGroup(7)
sage: time L=[X for X in G if X.order()==2]
CPU times: user 4.02 s, sys: 0.17 s, total: 4.19 s
Wall time: 6.13 s
}}}
__How does the patch work?__
The method ``_execute_line`` contains a ``while`` loop. In the loop, the
expect interface is called, searching for one long and one short pattern.
Without my patch, ``expect`` would compile the two patterns over and over
again. With my patch, the patterns will be compiled ''once'' (I think the
``_start`` method is an appropriate place), stored as attributes, and then
``expect_list`` is called without the need to re-compile the patterns.
Here is another evidence that it works. Without the patch:
{{{
sage: gap._start()
sage: prun gap._execute_line('b:=1;')
3258 function calls (3243 primitive calls) in 0.015 CPU seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
26 0.001 0.000 0.010 0.000 sre_compile.py:501(compile)
26 0.001 0.000 0.002 0.000
sre_compile.py:367(_compile_info)
26 0.001 0.000 0.003 0.000 sre_parse.py:385(_parse)
7 0.001 0.000 0.001 0.000
sre_compile.py:213(_optimize_charset)
15 0.001 0.000 0.001 0.000 {select.select}
1 0.001 0.001 0.001 0.001 {method 'clear' of 'dict'
objects}
8 0.001 0.000 0.003 0.000 pexpect.py:914(expect_list)
186 0.001 0.000 0.001 0.000 sre_parse.py:188(__next)
83 0.001 0.000 0.011 0.000 re.py:227(_compile)
36/31 0.001 0.000 0.001 0.000 sre_parse.py:146(getwidth)
31/26 0.000 0.000 0.002 0.000 sre_compile.py:38(_compile)
657 0.000 0.000 0.000 0.000 {method 'append' of 'list'
objects}
8 0.000 0.000 0.012 0.001
pexpect.py:815(compile_pattern_list)
26 0.000 0.000 0.004 0.000 sre_parse.py:669(parse)
156 0.000 0.000 0.001 0.000 sre_parse.py:207(get)
656/651 0.000 0.000 0.000 0.000 {len}
...
}}}
With the patch:
{{{
sage: gap._start()
sage: prun gap._execute_line('b:=1;')
478 function calls in 0.006 CPU seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
15 0.004 0.000 0.004 0.000 {select.select}
8 0.001 0.000 0.005 0.001 pexpect.py:914(expect_list)
15 0.000 0.000 0.004 0.000
pexpect.py:498(read_nonblocking)
188 0.000 0.000 0.000 0.000 {built-in method search}
15 0.000 0.000 0.000 0.000 {posix.read}
1 0.000 0.000 0.006 0.006 gap.py:573(_execute_line)
15 0.000 0.000 0.000 0.000 pexpect.py:739(isalive)
30 0.000 0.000 0.000 0.000 {posix.waitpid}
1 0.000 0.000 0.000 0.000
sre_compile.py:367(_compile_info)
1 0.000 0.000 0.000 0.000 sre_compile.py:501(compile)
2 0.000 0.000 0.000 0.000 {posix.write}
2 0.000 0.000 0.000 0.000 re.py:227(_compile)
2 0.000 0.000 0.000 0.000 pexpect.py:656(send)
1 0.000 0.000 0.000 0.000 sre_parse.py:385(_parse)
32 0.000 0.000 0.000 0.000 {built-in method start}
1 0.000 0.000 0.006 0.006 <string>:1(<module>)
25 0.000 0.000 0.000 0.000 {method 'append' of 'list'
objects}
2 0.000 0.000 0.000 0.000
pexpect.py:815(compile_pattern_list)
1 0.000 0.000 0.000 0.000 sre_parse.py:146(getwidth)
15 0.000 0.000 0.000 0.000 {method 'find' of 'str'
objects}
2 0.000 0.000 0.004 0.002 pexpect.py:855(expect)
8 0.000 0.000 0.000 0.000 {method 'index' of 'list'
objects}
5 0.000 0.000 0.000 0.000 sre_parse.py:188(__next)
15 0.000 0.000 0.000 0.000 {method 'lower' of 'str'
objects}
1 0.000 0.000 0.000 0.000 sre_parse.py:669(parse)
2 0.000 0.000 0.000 0.000 {time.sleep}
1 0.000 0.000 0.000 0.000 sre_compile.py:486(_code)
20 0.000 0.000 0.000 0.000 {len}
...
}}}
Now I am curious what ``select.select`` refers to. But I think the
improvement is clear.
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/6208>
Sage <http://sagemath.org/>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en
-~----------~----~----~----~------~----~------~--~---