PERF: join empty frame
- [x] [Tests added and passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#writing-tests) if fixing a bug or adding a new feature
- [x] All [code checks passed](https://pandas.pydata.org/pandas-docs/dev/development/contributing_codebase.html#pre-commit).
- [x] Added an entry in the latest `doc/source/whatsnew/vX.X.X.rst` file if fixing a bug or adding a new feature.

Similar to #45838, but for `DataFrame.join`. 

`DataFrame.join` already had a fast path for joining with an empty frame but it only covered a limited set of cases. This PR makes the fast path a bit faster and covers additional cases. 

```
import pandas as pd 
import numpy as np

N = 10_000_000

df = pd.DataFrame({'A': np.arange(N)})
df_empty = pd.DataFrame(columns=['B', 'C'], dtype='int64')

%timeit df.join(df_empty, how='inner')
932 ms ± 83.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)       <- main
285 µs ± 4.29 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)  <- PR


> do we have sufficient asv's to cover this?

Added an asv to cover this. @jreback - greenish, errors look unrelated Could you merge in main one more time? (failures look unrelated but good to be sure) @mroeschke - merged main. greenish again, let me know if you think the error is related Thanks @lukemanley. The failure was unrelated