Some (complex) processors have dedicated hardware to handle the I2C or SPI transaction. Other (simpler) processors do not. In such processors with no supporting hardware the bus must be emulated using software. This takes time away from other processor activities.
You will have to determine if the processor in your Arduino (and there are many different types of Arduinos which use many different processors) has hardware to support I2C and / or SPI bus transactions with out help from the software.
Note: Even in cases where there is hardware to handle I2C and / or SPI transactions, badly written software can still trip up the processor and make it unavailable for other purposes.
Note: Even in cases where there is no hardware to handle the I2C and / or SPI transactions, well written software can handle a moderate demand from tasks while also handling serial bus processing.
[Comments based on Arduino board type added later to answer:]
You are using an Arduino Mega 2560 which uses the Atmel ATmega2560 processor (one of several described in the linked-to specification). Searching the ATmega640 documentation shows matches for "TWI" (Atmel's equivelent to Philips' I2C) and SPI. So, if the I2C or SPI driver software has been well written for the ATmega2560 processor, it should be using the processor's hardware. Which makes the I2C or SPI feature more (but not entirely) immune to what ever else you have the processor running.
At this point it would be prudent for you to check if you are using such a driver. Make sure you are not using a driver which "emulates" these protocols in software. Also, make sure, if there is a hardware restriction, that you are using the pins on the processor designated for the type of bus used. Some driver may be extremely flexible allowing you to designate a pin with out hardware support and automatically implementing the protocol in software.
[Comments based on code added later to answer:]
You are your self implementing what might be handed off to built in processor hardware in software. Specifically you are emulating the PWM hardware feature in software. It is likely that even the most efficient I2C or SPI code (even with supporting hardware) will effect such sensitive software.
It would take a fair amount of work to make this software "work better". In general, you should consider not using delays and implementing a call-back paradigm based on a timed interrupts.
Alternatively, you might investigate why the Arduino PWM driver does not give you enough resolution. The hardware may in fact provide more resolution than the driver permits. Re-writing the PWM driver may be easier solution.