-
Notifications
You must be signed in to change notification settings - Fork 146
reorder opcodes on nvm3 #212
Comments
I don't think moving them is a good idea. |
PUSHBYTESX (1-75) pattern is not very efficient Erik... I'll explain why. Currently, we can use PUSHBYTES from 0 to 75 (opcodes 0x00-0x4b), an inheritance from Bitcoin VM (https://en.bitcoin.it/wiki/Script), also the following opcodes PUSHDATA1, 2 and 4 (that goes up to 4GiB). Regarding numbers, we can directly PUSH 1 to 16 only (opcodes 0x51-0x60), another inheritance from Bitcoin. On total, 96 opcodes are dedicated to this. Yet, if we want to push number 17, which is a small number, this would require two ops: PUSHBYTES1 + 17, and this happens to all small numbers after 16. I am constructing a serialization standard for Neo for a while, inspired on real "Neo" stuff, and I believe the VarBytes pattern on Neo is more efficient than any of these (inherited from Bitcoin). I propose a simplification that would be very likely more efficient than any of these. Proposed table:
We have:
Efficieny on stack operations: extra ops: Another PUSHVARHUGE would be interesting to cover memory allocations after 2^32 bytes, as this may happen if NVM is used on local systems which are 64-bit based (more than 4GiB memory). This can be done after PUSHVARBYTES opcode, or as a special case for value 0x00 (as we will already have PUSH 0). Some espace reserved for cryptographic/big int modular computations would also be nice, although I would prefer this as an EXTENSION opcode (as discussed in another issue). ======= Please think about this Erik... I know NVM opcodes by head now, reimplemented these on C++, JavaScript, so I can assure you this is not a crazy man talking 😂 I studied Bitcoin VM, Ethereum VM, and took a look at all proposals of VM for blockchains out of there, although not as much details as these two. I also studied WASM quite a lot. So, we have an opportunity here, since we are open to reorganizing NVM3, this can be an amazing shot. |
@erikzhang @shargon @lightszero please consider the above proposal. |
About reorder opcodes, I agree. And in my view. I think keep 4 is enough. pushbytes1 for number keep |
@lightszero precisely that. The proposal is to reduce to few: pushbyte, pushbytes2, 4, 8, 20, 32, 33, 64. These as commonly used. The rest can be varbytes. Regarding direct number push, I think we need many, otherwise, to push a single byte (such as number 7), we need two opcodes... |
pushbytes20, 16 and 32 are useful for hashes |
But take in mind that this opcodes never reduce the performance. Maybe with push bytes64, is enough. |
I didnt understand your last point Shargon, can you clarify? you mean we only need pushbytes64, and the rest can be varbytes? The difference indeed is just one extra byte for size,but if we know we will use it (a lot!),its good to have. E,g, 0x21 is currently pushbytes33... if we dont have that, we will use a lot: pushvarbyte + 33 + key (one byte extra,but it works). |
@shargon @lightszero @erikzhang please help me update this comparison table, to compare approaches: LEGEND:
Igor: From this table, it's very positive in my opinion that the new approach is able to drastically reduce overheads in most numeric operations. Please add your conclusions here too, and feel free to update the table with other highlights. |
|
It's slightly less efficient (on the table, with ever decreasing impact for bigger values), but much more "standard" regarding current Neo serialization model. I think this counts a lot, to have a strong identity... better than being perfectly efficient, I prefer being simple to understand and easily attract more devs/adopters to the protocol. |
Agree, one opcode for dynamic size is enough following the neo standard |
|
@roman-khimov that's precisely the point! If you look at the table up there, it's not just reordering, it's a total rewrite of neo-vm push system. It's completely different, focusing on performance and simplicity first, based on lessons learned from neo-vm2. Just to highlight: that table is just for PUSH. P.S.: Some studies I did last year, and are available on nvm-optimizer project: https://github.com/NeoResearch/nvm-opt (The Inlining example is the best of all.. reduction of dozens opcodes to just three). |
Yeah, I do see it and, to be fair, I do like it. It's just that I'm not sure we're properly taking into account the data that we have in Mainnet/Testnet, real scripts and contracts that we have. You obviously have way more experience with this VM than I do and most probably your suggestions are correct, but for me it would be very interesting to check these suggestions against real data to either prove them or improve them. For example, PUSHX (0-127) --- do we really need that many of them? What are the most commonly pushed values? I don't know. But checking against real-world scripts can help here. And if we have a VM design very close to Bitcoin's one then we can also consider some data from it. |
@roman-khimov this proposal has two big aspects involved: (1) simplicity (2) efficiency.
That being said, I'm not against analyzing the whole chain to watch pros and cons of this proposal, but I don't think it will be measurable in any performance metric, as the biggest gain of 50% happens on push numbers 17-127, which are not very common I guess (we would need to infer from PUSHBYTES2 pattern, as these didn't even exist...). |
Please review #235. |
As discussed on #208, it could be a good idea to reorganize opcodes on nvm3.
One thing I would propose is to move PushX opcodes to the beggining, so 05 would be number 5, and so on... this could be connected to a low-level serialization standard.
The text was updated successfully, but these errors were encountered: