Perf optimization for writing one byte in memory#1465
Conversation
|
It looks like most of the Travis failures are |
|
Thank you @ehennenfent I just changed the order of type checks. |
ehennenfent
left a comment
There was a problem hiding this comment.
Reviewed 1 of 1 files at r3.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on @catenacyber)
manticore/native/memory.py, line 966 at r3 (raw file):
if m is None: raise InvalidMemoryAccess(addr, "w") if not force and not m.access_ok("w"):
Checking the memory permissions on each byte is going to be slow. We'll approve this for now, but in the future we should try to make this faster by checking the permissions for the first and last byte of each write and skipping over per-byte checks if the beginning and end are both valid (and in the same map)
But we have only one byte as that is the point of this PR. manticore/manticore/native/memory.py Line 1180 in 81f8f97 |
Not necessarily "instead", but yes, we should modify the loop such that it's not necessary to check the memory permissions for every single byte. We can save that for a different PR. |
I guess I will do the upper loop modification first and then see if this PR is always relevant |
|
With the upper loop modification, I get 0.6 seconds cumulated for ais3_crackme with command With only the upper loop change (ie not using |
| else: | ||
| # overwrite all previous items | ||
| if address + offset in self._symbols: | ||
| del self._symbols[address + offset] |
There was a problem hiding this comment.
I think that the CI fails with a timeout because we removed this. It might be that it ends up in an infinite loop.
Also, the test_mix_of_concrete_and_symbolic test fails.
In this test we:
- Create memory with 0, 2, 4, 6 offsets/indexes/memory cells as concrete values and 1, 3, 5, 7 as symbolic.
- Assert if those concretes/symbolic addresses are really concrete/symbolic.
- Swap indexes of concrete/symbolic memory cells and reinitialise memory bytes to concrete/symbolic values.
- We reassert those. Here, the test fails.
This is because we don't delete the old symbolic mappings, so in mem._symbols we have old 1, 3, 5, 7 symbolic cells and 0, 2, 4, 6 new symbolic cells. The 1, 3, 5, 7 should not be there.
There was a problem hiding this comment.
I am going to try fixing that by readding the del ... and see if it works.
|
oops, I think you may have accidentally automatically closed this because of the text in #1506 |
|
I spend some time on this code/issue, analyzed it and found out that yes, indeed we need this or similar improvement, but the code present here is not complete and a bit overcomplex imho. I am closing this issue and I am going to propose another solution along with other improvements. By the way, the benchmark used here - A better one is here: import time
from manticore.core.smtlib import ConstraintSet
from manticore.native.memory import SMemory32
def test_write_concrete():
t1 = time.time()
mem = SMemory32(ConstraintSet())
buf = mem.mmap(None, 0x1000, "rw")
for i in range(1000):
mem[buf:buf+0x1000] = "a" * 0x1000
t2 = time.time()
print(f"test_write_concrete: {t2-t1} seconds")
test_write_concrete()Here are my results:
Just to be clear, the current PR has the following issues:
|
|
Bravo for the rework, glad I could help.
Interesting.
I agree that write1 is not so good to introduce
How so ? |
Thanks :).
Yeah, it is good as a real use case but it might be hard (and slow) to measure the right impact/improvement in regards to the given functionality when using it.
I guess we can play with it in the future, but for now its speed-up is probably negligible.
Assignments like |
Tested on ais3_crackme example
Function
writecalled 19164 times goes down from 2.076 seconds cumulated to 0.914 seconds by using this newwrite1function (on 42 seconds total time)This code may be less readable though...
This change is