-
-
Notifications
You must be signed in to change notification settings - Fork 534
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
database as_dbc_string() TypeError using bitstruct.c #271
Comments
Hello, I'm having the same issue as I want to use the decode function with multiprocessing for my project. The pickling does not work. It's this commit which introduces the error, especially these lines. For a quick fix I would propose to make it configurable which version is imported (bitstruct vs bitstruct.c). In the current code if it is possible bitstruct.c is always imported. A long term solution would be to make bitstruct.c pickleable, but I dont know how. Is this possible? @eerimoq Do you need help implementing any of the changes? Best regards |
@andlaus is the new maintainer, and I'm sure he appreciates all help he can get. |
yes, help is always appreciated :) I guess that in this concrete case, I might need to come back to you if changes to the bistruct or bitstruct.c turn out to be the best solution. My current naive view is that bitstruct.c should be replaced by bitstruct if the performance impact is negligible, or if it is not, all bitstruct.c objects should become pickleable. Let's see, it should not be too hard. (Famous last words.) |
Pickling supportIt is possible to make c extensions pickleable. See more information here. The link is wrong in the post, but the edit is too short to fix it. Here is the correct link to PyMethodDef. Unfortunately I still dont quite understand the way forward with this as I never have written a c extension in Python. May be this code is relevant? BenchmarkingI've just benchmarked the first test case of bitstruct and the c implementation is much faster: %timeit packed = pack('u1u1s6u7u9', 0, 0, -2, 65, 22)
# bitstruct.c
# 239 ns ± 1.91 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
# bitstruct
# 18 µs ± 336 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) Also looking at test, but probably more suited for another issue: cantools and bitstruct would be greatly suitable for hypothesis. This is a very low level test, here is a more practical benchmark. import cantools
db = cantools.database.Database()
db.add_dbc_string("""
BO_ 257 TestMessage: 6 Vector__XXX
SG_ TestSignal1 : 16|16@1- (1,0) [0|0] "" Vector__XXX
SG_ TestSignal2 : 32|16@1- (1,0) [0|0] "" Vector__XXX
SG_ TestSignal3 : 0|16@1- (1,0) [0|0] "" Vector__XXX
""")
%timeit db.decode_message(0x101, b"FFFFFF")
# bitstruct.c
# 7.04 µs ± 172 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
# bitstruct
# 11.2 µs ± 185 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) For this very specific case bitstruct.c is not much faster. Of course this does not give the full picture for every decoding operation. May be it is just a cherry picked example. I did a little more digging and used line_profiler to see where time is spent: bitstruct
bitstruct.c
The part where bitstruct is used is only on line 103 and 104. The dict comprehension is still as slow and _decode_field is a pure Python function. I hope this helps. All points are open for discussion and feedback is welcome. Best regards |
hm, this is not exactly what I meant: I am aware that, on its own,
The "Setup time" is the time required to parse the database, while "Decode time" is the time required to decode the raw CAN frames via I guess that I will give making |
I'm having the same problem getting the "can't pickle bitstruct.c.CompiledFormatDict objects" exception when trying to use the cache for faster loading. Also I have huge blfs with a lot of messages that need to be decoded. By utilising multiprocessing the dbc object has to be passed as a parameter but since it is not fully pickable with the bitstruct.c integration, I can't utilise the benefits of multiprocessing. What I've done so far is checking out the repo, and enforcing the use of bitstruct instead of bitstruct.c by reversing this commit. I'm really relying on the dbc object being picklable because although the bistruct.c is faster, with bitstruct the blf files I'm using can be decoded 50% faster. Can we just make the use of bitstruct.c or bitstruct optional? |
bitstruct is pretty essential w.r.t. encoding and decoding messages, so making it optional is (probably) not in the cards. I agree pickleability is more important than performance, though, i.e. the default should be switched to |
Yes, I can do that tomorrow. |
If there is a problem with bitstruct, please open an issue on that project. |
done: eerimoq/bitstruct#24 |
Is it then still needed to open a PR to switch the default to |
yes. This hopefully will not cause us any headaches, though...
I agree. But for this, it first needs to become pickleable ;) @eerimoq: Do you intend to fix this issue or shall I give it a go? (the latter will probably take substantially longer.) |
@andlaus I'll give it a try during the weekend, so no need for you to work on it right now. |
since eerimoq/bitstruct#24, should have addressed that issue, I'm closing it. feel free to re-open if the problem still persists... |
@andlaus Is the revision of bitstruct pinned or will it update on the next cantools release? |
requirements.txt says it is unpinned. could you tag a new cantools release? this issue seemed to have affected more people than usual... |
Have released. Has already propagated through for my by now. |
bitstruct did not update when doing pip cantools uninstall/install. Will make another release to add require bitstruct >= 8.12.1. Done. |
Python Version: 3.8.5
Cantools Version 34.2.0+
OS: Windows 10 (1909)
This works fine in cantools version 34.1.0. From the commits it appears there was a change from using bistruct to using bitstruct.c. Reverting this change in 34.2.0 does fix the issue.
Further analysis shows bitstruct was at version 8.10.0, updating to 8.11.1 can also resolve the issue.
I am no expert but I think this means that the setup.py needs to have the required bitstruct version upped?
Test code
Error Messages
The text was updated successfully, but these errors were encountered: