How tight is your timing?
How much delay and/or jitter can you tolerate?
i.e. how much time can your code tolerate being delayed while writing output to the LCD?
Depending on how much overhead time your code can tolerate it will determine what direction you can go and/or what you need to do.
Until you know that, it will be trial and error, which can waste lots of time and IMO is a waste of time.
So the first thing you need to know is how much overhead time can you tolerate.
--- bill
Some additional information:
I2C usually has more overhead than direct pin control.
The shield that you are using uses I2C and it uses an MCP23017 16 pin i/o expander to control the LCD.
The adafruit LCD libraries for their products that use I2C expanders are REALLY SLOW.
They try to emulate the Arduino pin control API so there are lots of i2c bytes being sent to control each pin and their code controls each pin separately.
A better way to control an i/o expander chip controlling an LCD is to control multiple pins at once which can dramatically reduce the overhead and speed things up significantly.
In other words the way their libraries are designed and written they are slow with lots of overhead.
Also, the way the microchip i/o expanders like the MCP23017 or MCP2308 work they have more i2c overhead than a PCF8574. In other words for a given i2c clock rate, the PCF8574 can control its output pins faster than the microchip expanders.
On the positive side, the MCP23017 can run with a much faster i2c clock than the PCF8574.
The default clock on the Arduino is 100Khz. The MCP23017 can run up to 1.7Mhz assuming a good h/w design with proper pullups.
The AVR can support an i2c master clock of 800Khz
Here are some actual timing numbers that show the actual amount of overhead in us for transferring a single byte to the display.
The first set of numbers is for a backpack that adafruit makes that uses a MCP23008.
This chips works similar to the one on the shield you have but the shield will have a little more overhead given it uses a MCP23016 chip and given the way Adafruit designed the shield.
There are two sets of numbers.
The top set is when the Adafruit LiquidCrystal library is used.
The bottom set is my hd44780 library which is much more efficient.
3882 us Adafruit library with MCP23008 @ 100kHz with #292 backpack
1492 us Adafruit library with MCP23008 @ 400kHz with #292 backpack
1131 us Adafruit library with MCP23008 @ 800kHz with #292 backpack
649 us hd44780 hd44780_I2Cexp with MCP23008 @ 100Khz with #292 backpack
230 us hd44780 hd44780_I2Cexp with MCP23008 @ 400Khz with #292 backpack
168 us hd44780 hd44780_I2Cexp with MCP23008 @ 800Khz with #292 backpack
You can see how the times get shorter when the i2c clock is bumped up but that the Adafruit library is much slower than my hd44780 library.
The next set of numbers is for using a typical LCD keypad shield that uses direct pin control and an analog pin for reading the buttons.
285 us LiquidCrystal Library with typical LCD keypad Shield
92 us hd44780 hd44780_pinIO with typical LCD keypad Shield
You can see that it is quite a bit faster than the Adafruit I2C LCD library even when the i2c clock is bumped up to 800kHz.
My hd44780 library using pin control it is about 42 times faster than the Adafruit I2C LCD library.
While these i2c tests were done on the Adafruit #292 backpack, the timing on your shield should be similar but a bit slower than the #292 backpack due to the shield you have using a MCP23016 and the way Adafruit has wired it up to the LCD and buttons.
Once you know the maximum timing overhead you can tolerate in your other code you decide what direction you need to take.
Keep in mind that these timings are for an individual character.
So if you sent more than one character with a lcd.print() etc... each character will take the amount of time shown.
--- bill