How does OctoPrint implement G-Code Caching


I'm currently building a 3d printer, that is of my own design. The mechanics, electronics and software are all custom. The control software uses g-code; naturally. I also own an Anet A8 3d printer, with Marlin firmware. With Marlin I have noticed that commands have a simple "OK" response. Based on what little I know about the inner workings of Marlin that OK happens after the line has been interpreted but before the movement has occurred (please correct me if I'm wrong).

Marlin and other firmware do not appear to have a way of caching commands. If OctoPrint sends 10 commands does Marlin say OK for each or OK for all ten? This brings me to my real question.

How does OctoPrint instruct a printer to cache commands instead of needing to send them one at a time?

If it does not, then I would like to propose the use of g-code's line number feature (N<0-9>). Here's how it would work:

Octoprint Sends 10 lines numbered 1 to 10 to Machine.
Machine responds with OK for each line, also echoing back the entire line that OK was for.

<- N009 G1 X0.4 Y2 Z.04
-> OK; N009 G1 X0.4 Y2 Z.04

Emergency commands like M112 however would not be cached, and as such would be executed immediately.


Hi @kurtnelle,

AFAIK, buffering is initially activated by some firmware. The technique differs between the firmware types.

There is no real handshake between client (printer) and server (OctoPrint) that directly handles the buffer.
OctoPrint waits for an OK from the printer, that means that the line is processed, or it reacts to a resend <linenumber> of the printer.

When the printer is not fast enough, it may send a buffer full message.


As soon as one of these buffered commands is received it is acknowledged and stored locally. If the local buffer is full, then the acknowledgment is delayed until space for storage in the buffer is available. This is how flow control is achieved.

Kewl. This answers my question.


I wouldn't change the specification before getting a lot of buy-in from whoever has to interpret that... :cough:foosel:cough:


Or getting agreement across the board of firmware devs out there (from my experience: not gonna happen), because otherwise we've just made everything even more complicated than it already is (spoiler: it's a nightmare)


OK, so G-CODE handling is not likely to change. Marlin and others have an alternative feature where it can execute from the SD card. Is octoprint able to send the entire g-code file over then instruct the device to execute from card? Is there a functionality or plugin that can do that? If not, then would that be possible to do in a plugin, or would it require a fundamental change to OctoPrint?


Yes, since about 2013, but due to the nature of the involved protocol it's sloooooow :turtle:


The micro controller that I'm using can use it's usb client connection as a virtual serial port (or i can hard a hardware one like the FTDI chip). I suspect that I can get over 1Mbps using that method. The SD card interface also uses 4 wires for increased speed and I happen to know that the throughput of that interface is around 1Mbps.

If this is the case, then would Octoprint simply work faster? If not then what would be the next bottleneck?


The ping-pong protocol. See the linked FAQ entry.


Sigh, so it's a complex problem with a non trivial solution.

Last part. So we have the file cached. OctoPrint give the command to start. How does OctoPrint know the progress of the print so that it can update it's estimated completion time and percentage?


I have an issue with the phrase "cached" here. It's a GCODE upload living in its file storage. Or - in case of an SD print - it doesn't have it at all and has to rely on (minimal) information provided by the printer. And it knows where in the file it is when it is the party controlling the job and sending the file to the printer line by line, and how big the file is. In case of printing from the printer's SD, it regularly polls that information from the printer via M27. Printer responds with something along the lines of SD printing byte 123/49823948 and that gets parsed into current position vs complete size.

Oh don't get me started on the clusterfsck that is 3d printer communications.


I wonder how things would improve if the OctoPi image were to implement a 50MB, say, RAM disk? And then if the Settings indicated that this feature was turned on...

  • When the job has been selected to print...
    • OctoPrint copies the file from ~/.octoprint/uploads to the RAM disk
    • The version on the RAM disk is selected to print
    • The job proceeds from there

There would be a small delay in shuffling the file sideways into RAM but it is, in effect, then cached on the OctoPrint side of things. I have a feeling that this would make streaming a bit smoother.

I do say all this from ignorance of how it works now, but I've just read your response and it may work.


The bottleneck is not reading from the file system. The bottleneck is the connection to the printer. Moving the file to a ram disk prior to printing would achieve nothing but increase complexity, make cross platform compatibility a nightmare and add an additional variable that could cause failure.


Bummer. I had such hope for that.